Files
ctask/v0.5.2-spec.md
T
typebasedio a5e508bcb6 docs(v0.5.1): record v0.5.1 completion; check in v0.5.2 spec
Update notes.md with the v0.5.1 Linux portability baseline (commits
7a7b249, 1033072): WSL-native validation passed, install.sh works,
ctask doctor recognizes the Linux statusline helper, the cross-built
Linux binary is statically linked, and WorkspacePath was removed from
new task.yaml metadata. Add load-bearing notes for the new invariants
(CGO_ENABLED=0, install script does not modify shell config) and a
"Next: v0.5.2" pointer.

Also check in v0.5.2-spec.md so the workspace-retrieval round has the
same on-disk durability as the prior specs.
2026-05-07 19:47:01 -04:00

17 KiB

ctask v0.5.2 Spec — Workspace Retrieval and Cross-Workspace Context

Theme

v0.1 = create and resume workspaces v0.2 = understand and continue workspaces later v0.3 = personalize workspaces and support longer-lived project work v0.4 = protect workspaces from concurrent session conflicts v0.5 = separate workspace management from project code v0.5.1 = ctask runs correctly on Linux (WSL and Docker) v0.5.2 = workspaces are discoverable, retrievable, and inspectable across sessions

Problem

Four usability gaps discovered through real usage:

  1. Archived workspaces are a dead end. ctask archive sets metadata and hides the workspace from default listing, but there is no ctask restore to bring it back. Users who archive prematurely must recreate the workspace and manually copy notes.md.

  2. Archived workspaces are invisible to direct lookup. ctask info <workspace> does not find archived workspaces unless the user passes -a. Archived workspaces are still workspaces — users expect to look them up by name.

  3. No cross-workspace context access. When an AI agent works in one workspace, it has no way to read the notes or location of another workspace. Prior work is invisible unless the user manually copies content. ctask should expose workspace context through CLI commands that agents can call.

  4. No shell autocompletion. Workspace names can be long and detailed. Users must type them in full or rely on shell history. Since ctask knows what workspaces exist and uses Cobra, autocompletion should be available.

Design Principles

Two rules govern this spec:

Listing is filtered. Direct lookup is comprehensive. ctask list shows active workspaces by default to keep output clean. Commands that accept a workspace name — info, notes, path, restore — search active and archived workspaces because the user asked for a specific workspace by name.

ctask exposes workspace context through CLI commands. Agents consume it themselves. ctask does not inject context into agent sessions, manage agent memory, or maintain a central knowledge base. It provides commands that print useful text to stdout. Agents (Claude Code or otherwise) can call these commands and read the output. This keeps ctask agent-agnostic and in its lane as a workspace manager.

Scope

  1. ctask restore <workspace> — un-archive a workspace
  2. ctask notes <workspace> — print another workspace's notes.md
  3. ctask path <workspace> — print the absolute path of a workspace
  4. Archived-inclusive direct lookup for info (and other direct-lookup commands)
  5. ctask list --names — machine-readable workspace enumeration
  6. ctask completion <shell> — shell autocompletion
  7. Updated CLAUDE.md seed text for cross-workspace awareness

Workspace Lookup Policy

The resolver (resolveOneResolveQuery) already supports an includeArchived boolean. This spec standardizes how each command sets it.

Active-only lookup

These commands operate on active workspaces. Looking up an archived workspace would be an error.

ctask resume <workspace>     active only (archived → error with restore hint)
ctask archive <workspace>    active only

Archived-inclusive lookup

These commands read or inspect workspaces. The user asked for a specific workspace by name — don't pretend it doesn't exist because it's archived.

ctask info <workspace>       active + archived
ctask notes <workspace>      active + archived
ctask path <workspace>       active + archived
ctask restore <workspace>    active + archived (then require status == archived)

Active-only by default, with --all opt-in

These commands are destructive or start sessions. Defaulting to active-only is safer; --all allows explicit archived access.

ctask delete <workspace>     active only by default; archived allowed with --all/-a
ctask open <workspace>       active only by default; archived allowed with --all/-a

Implementation

For commands currently hardcoding includeArchived=false (archive at cmd/archive.go:29, resume at cmd/resume.go:50): no change needed, these are correct.

For info (cmd/info.go:23): remove the --all/-a flag and always resolve with includeArchived=true. The flag is not needed — info is a read-only lookup and should always find the workspace the user asked for.

For delete and open: keep their existing --all/-a flags with current defaults (active-only). No change needed.

Resume behavior for archived workspaces

When a user runs ctask resume <archived-workspace>, the command should fail with a helpful message:

[ctask] error: workspace "promptvolley-v2" is archived

To restore it:
  ctask restore promptvolley-v2

This keeps archive and restore as intentional lifecycle actions, not something that happens silently through resume.

Implementation note: resume currently resolves with includeArchived=false, so it won't find archived workspaces at all — it just reports "not found." To provide the restore hint, change resume to resolve with includeArchived=true, then check the result's status. If the workspace is active, proceed normally. If archived, print the hint and exit. This way the user gets a specific, actionable message instead of a generic "not found" error.


1. ctask restore <workspace>

Behavior

ctask restore promptvolley-v2

Resolves the workspace using archived-inclusive lookup, then:

  • Verify the workspace status is archived. If it's already active, print an error: workspace "promptvolley-v2" is already active
  • Check for an active session lease (mirror the guard in ctask archive). If a lease is held, refuse with an appropriate message
  • Set status: active in task.yaml. Write the value explicitly — do not omit the field or set it to empty string, even if older code treats empty status as active
  • Clear archived_at (set to zero value / omit from YAML)
  • Update updated_at to current time
  • Write task.yaml
  • Print confirmation:
[ctask] restored: projects/2026-04-24_promptvolley-v2
[ctask] status: active

Rules

  • Restore is metadata-only. No directory moves, no file changes beyond task.yaml
  • Restoring does not start a session. The user runs ctask resume afterward if they want to work in it
  • If a workspace with the same slug exists in active status (edge case: user archived one, created a new one with the same name), the resolver will find both. The resolver's existing ambiguity handling applies — it should report the conflict and ask the user to use the full name

What restore does NOT do

  • Does not launch an agent
  • Does not regenerate CLAUDE.md or any seed files
  • Does not modify notes.md, context/, or any workspace content
  • Does not create a session log entry (no session is started)

2. ctask notes <workspace>

Behavior

ctask notes promptvolley-v2

Resolves the workspace using archived-inclusive lookup, then prints the contents of notes.md to stdout.

# Equivalent to:
cat "$(ctask path promptvolley-v2)/notes.md"

Rules

  • Output is the raw contents of notes.md, no framing or decoration. This makes it directly consumable by agents reading stdout
  • If notes.md does not exist in the workspace, print a clear message to stderr and exit with a non-zero code: [ctask] no notes.md found in workspace "promptvolley-v2"
  • If the workspace is not found, the resolver's existing error handling applies
  • Works on both active and archived workspaces

Why stdout matters

The primary consumer of this command is an AI coding agent running ctask notes <workspace> via shell. The agent reads stdout to get context from prior work. Keeping the output clean (no banners, no status lines) means the agent gets exactly the document content with no parsing needed. Informational messages go to stderr.


3. ctask path <workspace>

Behavior

ctask path promptvolley-v2

Resolves the workspace using archived-inclusive lookup, then prints the absolute filesystem path to stdout.

C:\Users\Warren\ai-workspaces\projects\2026-04-24_promptvolley-v2

or on Linux:

/home/warren/ai-workspaces/projects/2026-04-24_promptvolley-v2

Rules

  • Output is a single line: the absolute, OS-native filesystem path. No trailing newline decoration, no framing
  • The path uses native separators (backslashes on Windows, forward slashes on Linux). This is the real filesystem path, not a display identifier
  • Works on both active and archived workspaces
  • This is QueryResult.Path — already available from the resolver, no new logic needed

Use case

An agent that needs to inspect files in another workspace can run ctask path <workspace> and then read files at that location. Combined with ctask notes, this gives agents full read access to prior workspace context through standard shell commands.


4. ctask info — Archived-Inclusive by Default

Current behavior

ctask info <workspace> requires --all or -a to find archived workspaces. Without the flag, an archived workspace is reported as not found.

New behavior

ctask info <workspace> finds the workspace whether it is active or archived. If the workspace is archived, the info output should include the status clearly:

Task:       promptvolley-v2
Title:      promptvolley-v2
Category:   projects
Status:     archived
...
Archived:   2026-05-01 14:30:00

Implementation

Change cmd/info.go so that the resolver call uses includeArchived=true unconditionally. Remove the --all/-a flag from info — it is no longer needed since info always searches comprehensively.

Why this is correct

The user typed a specific workspace name. They know it exists. Telling them "not found" because it happens to be archived is unhelpful and forces them to guess at the flag. The principle: listing is filtered, direct lookup is comprehensive.


5. ctask list --names

Behavior

ctask list --names

Outputs one workspace directory basename per line, no headers, no table formatting:

2026-04-24_promptvolley-v2
2026-04-22_litlink-v2
2026-05-07_linux-test
ctask list --names --all

Includes archived workspaces in the output.

Rules

  • One directory basename per line (e.g., 2026-04-24_promptvolley-v2, not the bare slug promptvolley-v2). Basenames are unambiguous — bare slugs can collide across categories or dates
  • What list --names outputs, other commands accept as input. The resolver already accepts exact directory basenames
  • Respects existing filters: --all, --archived, --projects, or whatever category/status filters list currently supports
  • No additional decoration: no dates, no status, no categories. This is for machine consumption
  • If no workspaces match, output nothing (empty stdout, zero exit code)

Why this exists

Shell completion scripts and external tooling need a stable, parseable enumeration of workspace names. While Cobra's ValidArgsFunction can enumerate internally, list --names serves agents, shell scripts, and any future integration that needs to discover workspaces without importing ctask's Go code.


6. ctask completion <shell>

Behavior

ctask completion powershell
ctask completion bash
ctask completion zsh
ctask completion fish

Outputs the completion script for the specified shell. The user sources it in their shell profile.

Implementation

Cobra provides built-in completion generation. The implementation is:

  • Enable Cobra's completion command (or add a thin wrapper if customization is needed)
  • Add ValidArgsFunction hooks to every command that accepts a workspace name argument

ValidArgsFunction hooks

Each command gets a completion function that enumerates workspace candidates appropriate to that command's lookup policy:

resume:    active workspaces only
archive:   active workspaces only
restore:   archived workspaces only
info:      active + archived
notes:     active + archived
path:      active + archived
delete:    active workspaces only (flag-aware completion for --all can come later)
open:      active workspaces only (flag-aware completion for --all can come later)

The completion function calls the workspace listing logic internally (no shell-out to ctask list). A shared helper should enumerate slugs with a configurable status filter to avoid duplicating logic across commands.

PowerShell completion

PowerShell is the primary shell on Windows. The user adds the output of ctask completion powershell to their $PROFILE. Tab-cycling through candidates works natively with PowerShell's completion system.

Bash/Zsh completion

For WSL and Linux environments. The user sources the script in .bashrc or .zshrc. This also benefits the workflow where the developer SSHs into a container and uses ctask there.

Rules

  • Completion scripts are generated, not maintained by hand. Cobra handles the shell-specific syntax
  • The completion command itself does not require workspace resolution — it is a utility command
  • Fish completion is included for free via Cobra. No extra work, but no need to test extensively unless a real user needs it

7. CLAUDE.md Seed Text Update

Current state

ctask seeds a CLAUDE.md into each workspace with workspace management instructions. This text does not mention cross-workspace context access.

Addition

Add the following section to the built-in CLAUDE.md template used during workspace creation:

## Cross-Workspace Context

Related work may exist in other ctask workspaces. For project continuation,
migration, debugging, or building on prior work, inspect related workspaces
before making changes.

Available commands:

  ctask list --all          discover all workspaces (including archived)
  ctask info <workspace>    view metadata and status of any workspace
  ctask notes <workspace>   read another workspace's notes.md
  ctask path <workspace>    get the filesystem path to inspect files directly

Treat other workspaces as read-only unless the user explicitly asks you to
modify them.

Rules

  • This text is added to the seed template, not retroactively injected into existing workspaces
  • Users who have customized their seed directory will not see this text unless they add it themselves. This is expected — seeds are user-controlled
  • The text is concise. CLAUDE.md is loaded into the agent's context window at session start; long instructions waste context budget
  • The text is agent-agnostic. It references CLI commands, not Claude-specific features. If AGENTS.md is in use (v0.6), this section belongs there instead, with the CLAUDE.md shim pointing to it

Backward Compatibility

  • Existing workspaces are unaffected. No metadata changes, no layout changes
  • ctask info becomes more permissive (finds archived workspaces), which is strictly a UX improvement — no existing workflow breaks
  • ctask list default behavior is unchanged (active only). --names is additive
  • Existing CLAUDE.md files in workspaces are not modified. The new seed text only applies to newly created workspaces

Non-Goals for v0.5.2

  • ctask find <query> — full-text search across workspaces. Defer until list + notes proves insufficient
  • Claude-specific slash commands or skills files. Defer until the manual workflow proves itself
  • list --json — defer unless a real consumer needs structured output. --names covers the completion and scripting use case
  • Fuzzy or partial-match workspace resolution. The current resolver accepts exact slug, exact basename, and case-insensitive substring. That's sufficient
  • Modifying other workspaces via ctask commands. Cross-workspace access is read-only by design

Build Order

  1. Settle the lookup policy: update info to use includeArchived=true by default. Verify no tests assume the old default
  2. Implement ctask restore with archived-inclusive lookup and active-lease guard
  3. Implement ctask notes with archived-inclusive lookup and clean stdout output
  4. Implement ctask path with archived-inclusive lookup
  5. Update ctask resume to print a helpful restore hint when targeting an archived workspace
  6. Add ctask list --names with filter support
  7. Add ctask completion command and ValidArgsFunction hooks for all workspace-accepting commands
  8. Update CLAUDE.md seed template with cross-workspace context section
  9. Tests:
    • restore: archived workspace restored to active with explicit status: active, already-active workspace refused, lease guard respected, metadata updated correctly
    • notes: prints notes.md content, handles missing notes.md, works on archived workspace
    • path: prints absolute path, correct separators per OS, works on archived workspace
    • info: finds archived workspace without -a flag, flag removed
    • resume: archived workspace refused with restore hint (not generic "not found")
    • list --names: outputs directory basenames one per line, respects --all filter, empty output on no matches, no slug collisions
    • completion: generates valid shell scripts (smoke test — no need to test shell integration)
  10. Full test suite pass on both Windows and Linux