Skip to content

feat(slots): slot lifecycle rework — intent-gated switch, auto-bootstrap, reclaim, cap-choice (3.4.0) - #35

Merged
ashmitb95 merged 17 commits into
mainfrom
feat/slot-lifecycle
Jul 4, 2026
Merged

feat(slots): slot lifecycle rework — intent-gated switch, auto-bootstrap, reclaim, cap-choice (3.4.0)#35
ashmitb95 merged 17 commits into
mainfrom
feat/slot-lifecycle

Conversation

@ashmitb95

Copy link
Copy Markdown
Owner

What

Canopy 4.0 phase 4: the two-tier model becomes real. Worktrees become the workbench for PR-review changes; switch→trunk shrinks to the rare "run it full-stack" action and gets bulletproofed.

Design: ~/.claude/plans/2026-07-04-phase4-slot-lifecycle-design.md.

The reframe

Intent decides switching, not the act of returning to a feature:

  • Review changes (address PR comments) happen in the feature's worktreecontext gives the path, the enforcement gate allows commits there. No switch.
  • Running full-stack is the only reason to switch into trunk (the only place with the full env).

This evolves (doesn't break) "canonical is the only run target": trunk stays the RUN target; worktrees become the WORK target. Routing is implicit — canopy publishes the map, the agent works wherever the feature lives.

Changes

  • switch default flips to a warm-vs-cold policy: a feature vacating trunk keeps a warm slot only if it has an open PR or live WIP, else goes cold with a feature-tagged stash. --release-current/--evict/--evict-to remain explicit overrides.
  • Validate-all-then-execute preflight — all repos validated before any mutation, closing the partial-mutation class behind the two historical bricking bugs (locked in as regression scenarios).
  • Cap-full raises a choice (worktree_cap_reached with 3 runnable fix_actions: raise the cap / send vacating cold / evict a specific warm PR) — surfaced to the agent as a question instead of silently auto-evicting.
  • Auto-bootstrap on slot creation — fast steps (env, IDE, husky per-clone hooks) sync; deps install background with status (installing/ready/failed) surfaced in context; lockfile-unchanged short-circuit; --interactive/--force escapes. (Timing is provisional — see design doc.)
  • Reclaim-as-vacate (canopy reclaim + MCP): a merged PR's slot is freed (worktree → base, entry dropped) for reuse; clean-only, dirty slots surfaced as advisories; also passive on context --remote.
  • context slots carry per-repo bootstrap status; run --feature routes to a warm feature's worktree.

Risk & verification

This branch reworks switch (bricked twice historically). Mitigations: a table-driven lifecycle scenario harness with the two historical bricking bugs locked in as regressions, gating every switch change; validate-all-then-execute; and the shipped enforcement gate as a live net.

Milestone review found and fixed: non-runnable cap-choice commands (now render canopy config slots N / canopy switch <f> --release-current / --evict), and a deps-marker-in-worktree bug that would have defeated reclaim in real pnpm repos (marker moved to .canopy/state/).

Tests

1006 passed. New suites: slot_policy, slot_bootstrap, reclaim, render, lifecycle scenarios + bootstrap/switch/registry extensions.

Version

3.4.0 (CHANGELOG updated).

ashmitb95 added 17 commits July 4, 2026 16:38
…cuit

Adds a bootstrap map to slots.json ({slot: {repo: status}}) with tolerant
read/write helpers, plus a lockfile-fingerprint marker in bootstrap.py's
deps step so re-running bootstrap skips the install when the lockfile
hasn't changed since the last successful run.
_resolve_cwd only consulted the feature coordinator for feature-set
lookups, so slot-tracked features (canonical/warm without a
features.json entry) raised unknown_feature. Consult slots.json first:
warm features route to their worktree, canonical routes to its
per-repo trunk path, before falling back to the coordinator.
…ker out of worktree, reclaim/preflight cleanups
@ashmitb95
ashmitb95 merged commit aba19b8 into main Jul 4, 2026
3 checks passed
@ashmitb95
ashmitb95 deleted the feat/slot-lifecycle branch July 4, 2026 15:25
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