Skip to content

feat(boatstack): managed workspace lifecycle (fresh cut + auto cleanup) - #68

Merged
bigboateng merged 3 commits into
mainfrom
feat/boatstack-workspace-lifecycle
Jul 20, 2026
Merged

feat(boatstack): managed workspace lifecycle (fresh cut + auto cleanup)#68
bigboateng merged 3 commits into
mainfrom
feat/boatstack-workspace-lifecycle

Conversation

@bigboateng

Copy link
Copy Markdown
Contributor

Why this change

Feedback from Boatstack usage: "Could Boatstack clean up worktrees when you're done? I never remember to, and it seems to slow down updates." Today Boatstack owns no worktree/branch lifecycle — it operates on whatever branch the human already made, so people forget to cut fresh and forget to clean up, and stale worktrees block boatstack-update.

This adds an opt-in managed workspace lifecycle woven into the flow the state machine already drives — not a command users must remember.

What changed

Config — new workspace block (back-compat; enabled:false / absent = today's exact hands-off behavior):

  • enabled (master switch), mode (worktree|branch), cleanup (confirm|auto|off), cleanup_after (merge|ship). Validation is lenient — empty values resolve to defaults, so pre-existing configs stay valid.

Fresh cut (feature start)boatstack-next routes APPROVED → workspace-cut when management is on and you're still on the base branch, cutting a fresh branch/worktree from the freshly-fetched default branch. A workspace you cut yourself is respected and goes straight to build.

Cleanup (after publish)boatstack-next surfaces workspace-cleanup once a feature is published and its worktree still exists locally. It checks merge status (gh → local-ancestry fallback) and, in confirm mode, asks c to clean / k to keep. It is merge-gated, confirm-gated, and safety-gated: never removes uncommitted/unmerged work without an explicit --force, never deletes remote branches, never merges.

Both are internal operations, not user-invocable skills (deliberately excluded from claudeVisibleSkills). ResolveNext stays GitHub-free — all routing checks are local-only.

Review order

  1. runtime.go / init.go / export.go — config schema, defaults, lenient validation
  2. workspace.go — the lifecycle logic (cut, cleanup, status, gh→git merge fallback)
  3. cmd/boatstack-helper/main.go — internal workspace-cut/workspace-cleanup/workspace-status
  4. next.go — routing (gated on workspace.enabled + local state)
  5. references/workflow.md — state machine, c/k reply shortcuts, contracts
  6. workspace_test.go — 26 tests

Evidence

  • Full module suite green (go test ./... -count=1); gofmt + go vet clean
  • 26 new tests: config/validation, both isolation modes, merge gh/git paths, cleanup gating (block/confirm/force/dirty/idempotent), both routing directions, disabled guards
  • Real-binary E2E smoke (cut → status → cleanup → idempotent)
  • All pre-existing strict drift/generation tests pass; release-notes check-policy PASS

Gaps and risks

  • New behavior is opt-in; disabled projects are unaffected.
  • cleanup_after: ship (clean before merge) is supported but niche; default is merge.

Add a workspace policy config block (enabled/mode/cleanup/cleanup_after)
and the deterministic worktree/branch lifecycle it governs: fresh cut from
the up-to-date default branch at feature start, and merge-gated,
confirm-gated, safety-gated cleanup after ship. Managed unit is a git
worktree or an in-place branch; the disabled zero value preserves prior
hands-off behavior.

- runtime.go: Workspace struct + ProjectConfig field
- init.go: defaults for new installs (worktree/confirm/merge)
- export.go: lenient enum validation (empty resolves to defaults)
- workspace.go: CutFeatureWorkspace, CleanupFeatureWorkspace,
  FeatureWorkspaceStatus, gh->git merge-status fallback
- cmd: internal workspace-cut/cleanup/status subcommands
- workspace_test.go: 19 unit tests; full suite green
Surface workspace cleanup automatically instead of adding a command users
must remember: boatstack-next routes a published feature to workspace-cleanup
when management is on and its worktree still exists locally (local-only check;
merge confirmation stays inside the operation). Add the internal
workspace-cleanup operation prose and router entry (not a user-invocable
skill), the c/k reply shortcuts and post-ship state contract in the canonical
workflow, and a reader-facing release note.

- next.go: FEATURE_COMPLETE -> workspace-cleanup routing, gated on
  workspace.enabled + a live worktree
- workspace.go: workspaceEnabled helper
- export.go: workspace-cleanup operation + adapter router vocabulary
- references/workflow.md: state machine, reply shortcuts, state contract
- workspace_test.go: routing tests (cleanup / none / disabled)
- release note fragment
Route boatstack-next from an approved feature to workspace-cut before build
when workspace.enabled and the working tree is still on the default branch,
so work never starts on a stale base branch. A feature that already has its
own branch or worktree is respected and goes straight to build. Local-only
routing check; the cut itself fetches origin.

- workspace.go: needsFreshCut helper
- next.go: APPROVED -> workspace-cut routing (gated on enabled + on-base)
- export.go: workspace-cut operation prose + router vocabulary
- references/workflow.md: PLAN_APPROVED -> WORKSPACE_CUT contract + routing row
- workspace_test.go: cut-routing tests (on-base / already-cut / disabled)
@bigboateng
bigboateng merged commit e3430a3 into main Jul 20, 2026
4 checks passed
@bigboateng
bigboateng deleted the feat/boatstack-workspace-lifecycle branch July 20, 2026 07:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant