Files
ctask/v0.5.1-spec.md
typebasedio 7a7b2490c2 feat(v0.5.1): Linux portability baseline
- justfile: add build-linux, build-windows, build-all (output to dist/)
- .gitignore: cover ctask, ctask-*, dist/
- scripts/install.sh + scripts/uninstall.sh: POSIX equivalents of .ps1
- remove WorkspacePath metadata field (no production readers; legacy
  task.yaml files continue to parse silently)

Linux smoke-test on WSL/container pending.
See audit-report.md and v0.5.1-spec.md.
2026-05-07 18:22:41 -04:00

8.1 KiB
Raw Permalink Blame History

ctask v0.5.1 Spec — Linux Portability Baseline

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)

Problem

ctask was developed on Windows and has only been built and tested there. The developer now works across Windows, WSL, and Docker containers, and needs ctask available in all three environments. A portability audit (see audit-report.md) confirmed that the Go code is already portable — path handling uses filepath.* consistently, config defaults are OS-aware, and shell launching branches by runtime.GOOS. There are no blocking issues.

What's missing is the distribution surface: build targets, install scripts, and binary artifact coverage. There is also one piece of dead metadata (WorkspacePath) that persists absolute Windows paths into task.yaml, creating misleading data that would confuse cross-OS workspace inspection.

This spec covers the minimal work to produce a working, installable Linux binary and clean up the one metadata issue before the next feature round builds on top of it.

Scope

Three deliverables:

  1. Linux build targets and binary artifacts
  2. POSIX install and uninstall scripts
  3. Remove dead WorkspacePath metadata

Plus a manual validation step: smoke test on WSL or a Linux container.


1. Linux Build Targets

Current state

justfile has Windows-only build targets. .gitignore covers ctask.exe but not the extension-less Linux binary.

Reference: audit-report.md Section 8 — justfile lines 11, 18, 23; .gitignore lines 12.

Changes

Add build targets to justfile, outputting to a dist/ directory to keep the project root clean:

build-linux:
    mkdir -p dist
    GOOS=linux GOARCH=amd64 go build -o dist/ctask-linux-amd64 ./

build-windows:
    mkdir -p dist
    GOOS=windows GOARCH=amd64 go build -o dist/ctask-windows-amd64.exe ./

build-all: build-windows build-linux

Update .gitignore:

ctask
ctask.exe
ctask-*
dist/

Rules

  • build-linux produces a single ctask binary for linux/amd64
  • build-all produces both Windows and Linux binaries with distinguishable names
  • No cgo. Pure Go build. If any dependency introduces cgo, set CGO_ENABLED=0 explicitly
  • No ARM64 Linux target yet. Add when a real need exists (e.g., ARM-based containers or CI runners)
  • No macOS target. Deferred per roadmap (post-v1.0)
  • No GitHub Actions release pipeline yet. That belongs in a later round when ctask is ready for distribution beyond personal use

2. Install and Uninstall Scripts

Current state

scripts/install.ps1 and scripts/uninstall.ps1 exist for Windows. No equivalent for Linux.

New files

scripts/install.sh

Behavior:

  • Default install location: ~/.local/bin/ctask
  • Check that ~/.local/bin exists; create it if not
  • Copy the binary and set executable permission
  • Install scripts/ctask-statusline.sh to the same location as the binary (so ctask doctor can find it). Mark it executable. Do not install the PowerShell statusline helper on Linux
  • Check whether ~/.local/bin is in $PATH; if not, print a warning with the appropriate shell config line to add (detect bash vs zsh by checking $SHELL)
  • Accept an optional argument to override install location: ./install.sh /usr/local/bin
  • If a ctask binary already exists at the target, overwrite it (upgrade path)

scripts/uninstall.sh

Behavior:

  • Default location: ~/.local/bin/ctask
  • Accept optional argument to override
  • Remove the binary and the ctask-statusline.sh helper from the same directory
  • Do not remove CTASK_ROOT or any workspace data — print a note that workspaces are preserved

Rules

  • Scripts should be POSIX sh, not bash-specific, for maximum container compatibility
  • Scripts mirror the install/uninstall pattern of the existing PowerShell scripts — keep the UX parallel
  • No package manager integration (apt, brew, etc.). Not in scope
  • For Docker containers, the expected install pattern is a COPY or RUN curl in the Dockerfile, not running install.sh. The script is primarily for WSL and interactive Linux environments

3. Remove WorkspacePath Metadata

Current state

internal/workspace/create.go:138 sets meta.WorkspacePath = wsDir, persisting the absolute filesystem path (e.g., C:\Users\Warren\ai-workspaces\general\2026-04-24_foo) into task.yaml as workspace_path.

The audit confirmed this field is never read by production code. It appears only in test struct initializers. The runtime workspace path is always derived fresh from the filesystem walk via QueryResult.Path.

Reference: audit-report.md Section 1 — internal/workspace/create.go:138, internal/workspace/metadata.go:29.

Changes

  • Remove WorkspacePath from the TaskMeta struct in internal/workspace/metadata.go
  • Remove the assignment in internal/workspace/create.go:138
  • Update all test fixtures and struct initializers that reference the field
  • Existing task.yaml files that contain workspace_path should be left alone — Go's YAML unmarshaling will silently ignore unknown fields. No migration needed
  • Do not add a replacement field. If a persistent workspace identifier is needed later, add a proper workspace_id with correct semantics (relative path, forward-slash normalized) at that time

Rules

  • This is a removal, not a replacement. The field is dead code with misleading output
  • Newly created workspaces will no longer have workspace_path in their task.yaml
  • Old workspaces with the field continue to work — the field is simply ignored on read
  • No schema migration command needed

4. Validation

After implementing the above, perform a manual smoke test on WSL or a Linux container.

Smoke test checklist

Run these commands on Linux and verify correct behavior:

ctask new "linux-test"
ctask list
ctask info linux-test
ctask resume linux-test       (agent launch — verify shell and env vars)
ctask archive linux-test
ctask list                    (should not show archived workspace)
ctask list --all              (should show archived workspace, if flag exists)
ctask info linux-test -a      (should show archived workspace info)
ctask delete linux-test       (clean up)
ctask doctor                  (verify all checks pass on Linux)

Verify:

  • Default CTASK_ROOT resolves to $HOME/ai-workspaces
  • Workspace directories are created with correct structure
  • task.yaml does not contain workspace_path
  • Session logs, notes.md, CLAUDE.md are created with LF line endings
  • Agent launch works (or fails gracefully if the agent binary isn't installed in the Linux environment)
  • ctask doctor reports correct OS, root path, and PATH status

Test suite

Run go test ./... on Linux. The audit states the test suite should pass without modification after the WorkspacePath removal and fixture updates. Confirm this.


Backward Compatibility

  • Existing Windows workspaces are unaffected
  • Old task.yaml files with workspace_path continue to load correctly (field ignored)
  • No changes to any existing command behavior
  • No changes to workspace layout, session logging, or agent launching

Non-Goals for v0.5.1

  • Shell completion (v0.5.2 or later)
  • New commands (restore, notes, path — covered in the next spec)
  • GitHub Actions or release automation
  • Package manager integration
  • macOS or ARM64 targets
  • Config file changes (v0.6 scope per roadmap)

Build Order

  1. Add Linux build targets to justfile (with dist/ output) and update .gitignore
  2. Add scripts/install.sh and scripts/uninstall.sh (including statusline helper install)
  3. Remove WorkspacePath from TaskMeta, create.go, and test fixtures
  4. Run test suite on Windows (confirm nothing broke)
  5. Cross-compile Linux binary
  6. Run test suite on Linux/WSL
  7. Install via install.sh on Linux/WSL, verify ctask doctor passes (including statusline helper check)
  8. Execute smoke test checklist on Linux/WSL