Commit Graph

10 Commits

Author SHA1 Message Date
typebasedio bd1cff5b26 refactor(v0.3): replace ListOpts.Projects bool with tri-state Type filter
ListOpts now exposes a Type string field (TypeAny / TypeTask /
TypeProject). TypeAny is the new way to express "both tasks and
projects" in a single ListWorkspaces call -- which the next two
commits will use to consolidate cmd/last and cmd/delete onto a
single helper, and to make 'ctask list' default to showing both
types.

Invalid Type values now return an explicit error from
ListWorkspaces (defensive against typos in callers).

cmd/list, cmd/last, and cmd/delete are migrated to the new field.
External behavior is unchanged in this commit; the cleanup of
ctask list semantics happens in a follow-up commit so the diff
stays reviewable.
2026-04-10 16:49:49 -04:00
typebasedio bfe89d830c feat(v0.3): add Projects filter to ListWorkspaces; fix last/delete
ListOpts gains a Projects bool that filters by EffectiveType.
Default behavior (Projects: false) now returns tasks only --
this is a deliberate semantic change that supports the new
'ctask list' (tasks) vs 'ctask list --projects' (projects)
spec.

The change silently regresses two cmd-level callers that scan
for "the most recently updated workspace": cmd/last.go (used by
'ctask last') and cmd/delete.go (used to print the "this was
your most recent workspace" note). Both are fixed by unioning a
tasks-scan with a projects-scan, so 'last' and 'delete' continue
to consider both types.

Test helper createTestWorkspaceTyped allows setting an explicit
type (or "" to simulate a v0.2 workspace with no type field).
2026-04-10 14:43:28 -04:00
typebasedio 6519582de6 feat(v0.3): add EnsureGitignore + RunGitInit helpers
EnsureGitignore writes a minimal .gitignore (.ctask/ +
logs/sessions.log) iff one does not already exist. This is the
file-system half of the v0.3 seed-wins rule for .gitignore: if
either the general or project seed copied a .gitignore into the
workspace, EnsureGitignore must be a no-op.

GitAvailable + RunGitInit wrap exec.LookPath("git") and `git init`
respectively, so the caller in cmd/new.go can decide whether to
print the informational note when git is missing.

Tests cover:
  - missing -> created with the minimal body
  - present -> preserved verbatim
  - integration: general seed .gitignore preserved end-to-end
  - integration: project seed .gitignore preserved end-to-end
  - integration: no seed -> minimal body created
2026-04-10 14:41:14 -04:00
typebasedio 3adfe62410 feat(v0.3): add SkipCategoryDir for CTASK_PROJECT_ROOT semantics
When SkipCategoryDir is true, Create places the workspace directly
under Root and does not append a Category subdirectory. This is the
mechanism that prevents doubled paths like
~/projects/projects/<slug> when the user sets CTASK_PROJECT_ROOT
without an explicit -c flag. The Category value is still recorded
on TaskMeta so list/info/filter still work.
2026-04-10 14:38:01 -04:00
typebasedio e09eac62d1 feat(v0.3): support project mode and layered seed overlay in Create
CreateOpts gains IsProject, SeedDir, and ProjectSeedDir. The new
seeding flow is:

  1. write built-in defaults (task or project CLAUDE.md + notes.md)
  2. apply general seed if SeedDir != "" (overlay)
  3. apply project seed if IsProject && ProjectSeedDir != "" (overlay)
  4. write task.yaml (last, so seeds can never inject metadata)

The obsolete TestCreateDoesNotOverwriteSeedFiles test is removed:
its v0.2 invariant ("don't overwrite existing files") no longer
holds because v0.3 always lays defaults onto a fresh dir and seeds
are expected to overwrite.
2026-04-10 14:37:09 -04:00
typebasedio 72be64cc1a feat(v0.3): add Type field to TaskMeta with backward-compat helper
TaskMeta now records type: task or type: project. EffectiveType
returns 'task' for missing/empty/unknown values and for nil meta,
so v0.2 workspaces continue to read as tasks without any
migration. The field is placed between Category and Mode in the
YAML output. Tests cover the round-trip and the legacy
no-type-field case.
2026-04-10 14:34:53 -04:00
typebasedio 6740c3835e feat: query resolution and workspace listing
5-step query resolution (exact dir, exact slug, substring), archived exclusion. Listing with category filter, limit, reverse-chronological sort.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 18:32:12 -04:00
typebasedio 17789e4b9f feat: workspace creation with seed files and collision handling
Create function produces full workspace layout (task.yaml, CLAUDE.md, notes.md, context/, output/, logs/). Seed files only written if missing. Collision suffixing tested.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 18:30:59 -04:00
typebasedio 7b75cb5f3d feat: slug generation and directory collision resolution
Slugify, AutoTitle, DirName, ResolveDir with -2, -3 suffixing. Full test coverage.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 18:30:06 -04:00
typebasedio 514f2d8233 feat: workspace metadata model with YAML read/write
TaskMeta struct matching task.yaml schema exactly. Tests for roundtrip, field presence, and archive state.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 18:29:26 -04:00