Skip to content

[codex] Standalone OpenSpec repos: store root parity and --store root selection#1190

Open
TabishB wants to merge 108 commits into
mainfrom
codex/store-root-parity
Open

[codex] Standalone OpenSpec repos: store root parity and --store root selection#1190
TabishB wants to merge 108 commits into
mainfrom
codex/store-root-parity

Conversation

@TabishB

@TabishB TabishB commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements Phase 1 slices 1.1 and 1.2 of the simplify-context-and-workspace-model roadmap, plus slice 1.2's pulled-forward item 2.1 (initiative-link retirement). Context stores become ordinary standalone OpenSpec roots with thin identity metadata, and normal OpenSpec commands can act on a registered store by name with --store <id>.

Slice 1.1 — store root parity

  • Added an OpenSpec root helper for inspecting, ensuring, and rolling back root-shape files.
  • context-store setup creates or preserves openspec/config.yaml, openspec/specs/, openspec/changes/, and openspec/changes/archive/ alongside .openspec-store/store.yaml.
  • context-store register requires an existing healthy OpenSpec root, with --yes for non-interactive identity creation.
  • context-store doctor --json reports openspec_root separately from metadata and git.

Slice 1.2 — --store root selection for normal commands

  • One shared root resolver (src/core/root-selection.ts) behind new change, status, instructions, list, show, validate, and archive. --store <id> resolves a registered store to its root; unknown ids list registered stores; unhealthy or identity-mismatched stores point to context-store doctor.
  • Leftover workspace view state never wins root resolution for these commands, and a no-root directory with registered stores errors with a store-selection hint instead of silently scaffolding.
  • Selected-store runs print Using OpenSpec root: <id> (<abs path>) to stderr; JSON successes carry an additive shared root block (path, source, store_id).
  • --store-path is rejected deliberately with context-store register guidance, including on show despite allowUnknownOption.
  • new change is root selection only: initiative-link creation removed, --initiative and --areas reject before any writes, --goal stays ordinary metadata. openspec set change is removed (initiative linking was its only behavior).
  • archive gains a non-interactive --json mode with machine-readable diagnostics and pure-JSON stdout; rebuilt specs are now all validated before any are written, so a late validation failure leaves every target untouched.
  • list gains minimal --specs --json support; context-store setup/register next steps show --store usage.
  • Roadmap, slice spec/plan, and decision-review evidence are recorded under openspec/work/simplify-context-and-workspace-model/; old beta initiative and workspace docs are marked as transition history.

Deprecated noun-form commands (openspec change show, openspec spec show, …) stay cwd-based and do not gain --store. Updating generated agent skills/guidance to mention --store is tracked separately.

Validation

  • pnpm run build
  • pnpm exec vitest run test/core/root-selection.test.ts test/commands/store-root-selection.test.ts test/commands/artifact-workflow.test.ts test/commands/context-store.test.ts test/commands/completion.test.ts test/core/archive.test.ts
  • pnpm test (92 files, 1717 passed)
  • Multi-agent review pass (spec compliance, code correctness, hands-on CLI QA); findings fixed in follow-up commits, including JSON stdout purity and archive spec-write atomicity.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added --store <id> flag to select registered context stores as OpenSpec roots across commands.
    • Introduced experimental /work directory structure for organizing goals, roadmaps, and slices.
  • Removed

    • Removed set change command.
    • Removed --initiative and --areas flags from new change.
  • Improvements

    • Enhanced OpenSpec root detection and validation.
    • Improved JSON output consistency with root metadata across commands.

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Too many files!

This PR contains 218 files, which is 68 over the limit of 150.

To get a review, narrow the scope:
• coderabbit review --type committed # exclude uncommitted changes
• coderabbit review --dir # limit to a subdirectory
• coderabbit review --base # compare against a closer base

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b5a351c2-6704-4386-86ef-5069f7db8ecb

📥 Commits

Reviewing files that changed from the base of the PR and between e3b053d and ded268d.

📒 Files selected for processing (218)
  • .github/workflows/ci.yml
  • docs/agent-contract.md
  • docs/cli.md
  • docs/concepts.md
  • docs/workspaces-beta/agent-cli-playbook.md
  • docs/workspaces-beta/user-guide.md
  • openspec/changes/workspace-agent-guidance/.openspec.yaml
  • openspec/changes/workspace-agent-guidance/proposal.md
  • openspec/changes/workspace-apply-repo-slice/proposal.md
  • openspec/changes/workspace-reimplementation-roadmap/HISTORICAL_DIRECTION.md
  • openspec/changes/workspace-reimplementation-roadmap/POC_REFERENCE_GUIDE.md
  • openspec/changes/workspace-reimplementation-roadmap/README.md
  • openspec/changes/workspace-reimplementation-roadmap/START_HERE.md
  • openspec/changes/workspace-reimplementation-roadmap/proposal.md
  • openspec/changes/workspace-verify-and-archive/proposal.md
  • openspec/specs/artifact-graph/spec.md
  • openspec/specs/change-creation/spec.md
  • openspec/specs/cli-artifact-workflow/spec.md
  • openspec/specs/cli-config/spec.md
  • openspec/specs/cli-update/spec.md
  • openspec/specs/openspec-conventions/spec.md
  • openspec/specs/schema-resolution/spec.md
  • openspec/specs/workspace-change-planning/spec.md
  • openspec/specs/workspace-foundation/spec.md
  • openspec/specs/workspace-links/spec.md
  • openspec/specs/workspace-open/spec.md
  • openspec/work/simplify-context-and-workspace-model/capstone/gauntlet.md
  • openspec/work/simplify-context-and-workspace-model/capstone/journeys.md
  • openspec/work/simplify-context-and-workspace-model/capstone/release-readiness.md
  • openspec/work/simplify-context-and-workspace-model/capstone/technical-audits.md
  • openspec/work/simplify-context-and-workspace-model/capstone/usability-audits.md
  • openspec/work/simplify-context-and-workspace-model/goal.md
  • openspec/work/simplify-context-and-workspace-model/roadmap.md
  • openspec/work/simplify-context-and-workspace-model/runbook.md
  • openspec/work/simplify-context-and-workspace-model/slices/assemble-working-context/plan.md
  • openspec/work/simplify-context-and-workspace-model/slices/assemble-working-context/spec.md
  • openspec/work/simplify-context-and-workspace-model/slices/declared-store-fallback/plan.md
  • openspec/work/simplify-context-and-workspace-model/slices/declared-store-fallback/spec.md
  • openspec/work/simplify-context-and-workspace-model/slices/delete-legacy-command-groups/deletion-ledger.md
  • openspec/work/simplify-context-and-workspace-model/slices/delete-legacy-command-groups/plan.md
  • openspec/work/simplify-context-and-workspace-model/slices/delete-legacy-command-groups/remainder.md
  • openspec/work/simplify-context-and-workspace-model/slices/delete-legacy-command-groups/spec.md
  • openspec/work/simplify-context-and-workspace-model/slices/personal-worksets/capstone-dogfood.md
  • openspec/work/simplify-context-and-workspace-model/slices/personal-worksets/plan.md
  • openspec/work/simplify-context-and-workspace-model/slices/personal-worksets/research.md
  • openspec/work/simplify-context-and-workspace-model/slices/personal-worksets/spec.md
  • openspec/work/simplify-context-and-workspace-model/slices/relationship-health/plan.md
  • openspec/work/simplify-context-and-workspace-model/slices/relationship-health/spec.md
  • openspec/work/simplify-context-and-workspace-model/slices/repo-map/plan.md
  • openspec/work/simplify-context-and-workspace-model/slices/repo-map/spec.md
  • openspec/work/simplify-context-and-workspace-model/slices/store-canonical-remote/plan.md
  • openspec/work/simplify-context-and-workspace-model/slices/store-canonical-remote/spec.md
  • openspec/work/simplify-context-and-workspace-model/slices/store-lifecycle-proof/plan.md
  • openspec/work/simplify-context-and-workspace-model/slices/store-lifecycle-proof/spec.md
  • openspec/work/simplify-context-and-workspace-model/slices/store-references/plan.md
  • openspec/work/simplify-context-and-workspace-model/slices/store-references/spec.md
  • openspec/work/simplify-context-and-workspace-model/slices/store-rename-and-guidance/dogfood-transcript.md
  • openspec/work/simplify-context-and-workspace-model/slices/store-rename-and-guidance/plan.md
  • openspec/work/simplify-context-and-workspace-model/slices/store-rename-and-guidance/spec.md
  • openspec/work/simplify-context-and-workspace-model/slices/store-targets/plan.md
  • openspec/work/simplify-context-and-workspace-model/slices/store-targets/spec.md
  • openspec/work/simplify-context-and-workspace-model/workset-direction.md
  • schemas/workspace-planning/schema.yaml
  • schemas/workspace-planning/templates/design.md
  • schemas/workspace-planning/templates/proposal.md
  • schemas/workspace-planning/templates/spec.md
  • schemas/workspace-planning/templates/tasks.md
  • src/cli/index.ts
  • src/commands/config.ts
  • src/commands/context-store.ts
  • src/commands/context.ts
  • src/commands/doctor.ts
  • src/commands/initiative.ts
  • src/commands/repo.ts
  • src/commands/shared-gather.ts
  • src/commands/shared-output.ts
  • src/commands/show.ts
  • src/commands/store.ts
  • src/commands/validate.ts
  • src/commands/workflow/instructions.ts
  • src/commands/workflow/new-change.ts
  • src/commands/workflow/shared.ts
  • src/commands/workflow/status.ts
  • src/commands/workset-input.ts
  • src/commands/workset-prompts.ts
  • src/commands/workset.ts
  • src/commands/workspace.ts
  • src/commands/workspace/context-status.ts
  • src/commands/workspace/open-target-selection.ts
  • src/commands/workspace/open-view.ts
  • src/commands/workspace/open.ts
  • src/commands/workspace/opener-selection.ts
  • src/commands/workspace/operations.ts
  • src/commands/workspace/prompt-theme.ts
  • src/commands/workspace/registration.ts
  • src/commands/workspace/selection.ts
  • src/commands/workspace/setup-prompts.ts
  • src/commands/workspace/types.ts
  • src/core/archive.ts
  • src/core/artifact-graph/index.ts
  • src/core/artifact-graph/instruction-loader.ts
  • src/core/change-metadata/schema.ts
  • src/core/change-status-policy.ts
  • src/core/collections/index.ts
  • src/core/collections/initiatives/collection.ts
  • src/core/collections/initiatives/index.ts
  • src/core/collections/initiatives/operations.ts
  • src/core/collections/initiatives/resolution.ts
  • src/core/collections/initiatives/schema.ts
  • src/core/collections/initiatives/templates.ts
  • src/core/collections/runtime.ts
  • src/core/completions/command-registry.ts
  • src/core/completions/generators/zsh-generator.ts
  • src/core/completions/shared-flags.ts
  • src/core/context-store/binding.ts
  • src/core/context-store/foundation.ts
  • src/core/context-store/operations.ts
  • src/core/context-store/registry.ts
  • src/core/file-state.ts
  • src/core/global-config.ts
  • src/core/id.ts
  • src/core/index.ts
  • src/core/init.ts
  • src/core/list.ts
  • src/core/openers.ts
  • src/core/openspec-root.ts
  • src/core/planning-home.ts
  • src/core/project-config.ts
  • src/core/references.ts
  • src/core/relationship-health.ts
  • src/core/root-selection.ts
  • src/core/store/errors.ts
  • src/core/store/foundation.ts
  • src/core/store/git.ts
  • src/core/store/index.ts
  • src/core/store/operations.ts
  • src/core/store/registry.ts
  • src/core/targets.ts
  • src/core/templates/workflows/apply-change.ts
  • src/core/templates/workflows/archive-change.ts
  • src/core/templates/workflows/bulk-archive-change.ts
  • src/core/templates/workflows/continue-change.ts
  • src/core/templates/workflows/explore.ts
  • src/core/templates/workflows/ff-change.ts
  • src/core/templates/workflows/new-change.ts
  • src/core/templates/workflows/onboard.ts
  • src/core/templates/workflows/propose.ts
  • src/core/templates/workflows/store-selection.ts
  • src/core/templates/workflows/sync-specs.ts
  • src/core/templates/workflows/verify-change.ts
  • src/core/working-set.ts
  • src/core/worksets.ts
  • src/core/workspace/foundation.ts
  • src/core/workspace/index.ts
  • src/core/workspace/legacy-state.ts
  • src/core/workspace/link-input.ts
  • src/core/workspace/open-surface.ts
  • src/core/workspace/openers.ts
  • src/core/workspace/registry.ts
  • src/core/workspace/skills.ts
  • src/core/workspace/state-io.ts
  • src/core/zod-issues.ts
  • src/utils/change-metadata.ts
  • src/utils/change-utils.ts
  • test/cli-e2e/capstone-journeys.test.ts
  • test/cli-e2e/store-lifecycle.test.ts
  • test/cli-e2e/workset-journey.test.ts
  • test/commands/change-initiative-link.test.ts
  • test/commands/config-profile.test.ts
  • test/commands/context.test.ts
  • test/commands/declared-store-fallback.test.ts
  • test/commands/doctor.test.ts
  • test/commands/initiative.test.ts
  • test/commands/legacy-groups-removed.test.ts
  • test/commands/repo-map.test.ts
  • test/commands/store-git.test.ts
  • test/commands/store-references.test.ts
  • test/commands/store-remote.test.ts
  • test/commands/store-root-selection.test.ts
  • test/commands/store-targets.test.ts
  • test/commands/store.test.ts
  • test/commands/workset.test.ts
  • test/commands/workspace-initiative-open.test.ts
  • test/commands/workspace-open.test.ts
  • test/commands/workspace.interactive.test.ts
  • test/commands/workspace.test.ts
  • test/core/archive.test.ts
  • test/core/collections/initiatives/operations.test.ts
  • test/core/collections/initiatives/resolution.test.ts
  • test/core/collections/initiatives/schema.test.ts
  • test/core/collections/initiatives/templates.test.ts
  • test/core/collections/runtime.test.ts
  • test/core/completions/command-registry.test.ts
  • test/core/completions/generators/zsh-generator.test.ts
  • test/core/file-state.test.ts
  • test/core/openers.test.ts
  • test/core/planning-home.test.ts
  • test/core/project-config.test.ts
  • test/core/references.test.ts
  • test/core/relationship-health.test.ts
  • test/core/root-selection.test.ts
  • test/core/store/foundation.test.ts
  • test/core/store/registry.test.ts
  • test/core/store/repo-map.test.ts
  • test/core/targets.test.ts
  • test/core/templates/skill-templates-parity.test.ts
  • test/core/working-set.test.ts
  • test/core/worksets.test.ts
  • test/core/workspace/foundation.test.ts
  • test/core/workspace/legacy-state.test.ts
  • test/core/workspace/skills.test.ts
  • test/helpers/fake-tool.ts
  • test/helpers/fs-snapshot.ts
  • test/helpers/openspec-fixtures.ts
  • test/helpers/path-env.ts
  • test/helpers/store-git.ts
  • test/utils/change-metadata.test.ts
  • test/vocabulary-sweep.test.ts

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

OpenSpec commands now resolve an explicit root context from --store, nearest repo state, or an implicit directory, and propagate that root through workflow commands and JSON output. Context-store setup, registration, and doctoring now inspect and preserve OpenSpec roots directly. Several workspace-era commands and docs were marked obsolete or removed, while new /work guidance and slice documents were added.

Changes

OpenSpec root and context-store foundation

Layer / File(s) Summary
Root helpers and selection
src/core/openspec-root.ts, src/core/root-selection.ts, src/core/index.ts, test/core/openspec-root.test.ts, test/core/root-selection.test.ts
OpenSpec root inspection, creation, rollback, and command root selection are added with store, nearest, and implicit resolution paths.
Context-store setup, register, and doctor
src/core/context-store/*, test/commands/context-store.test.ts, test/core/context-store/registry.test.ts
Context-store mutation and inspection flow now uses OpenSpec root health, richer registry status, optional identity creation, and separate root diagnostics.

CLI command root-awareness and workflow changes

Layer / File(s) Summary
CLI flags and command registry
src/cli/index.ts, src/core/completions/*, docs/cli.md, test/core/completions/command-registry.test.ts, test/commands/store-root-selection.test.ts, test/commands/artifact-workflow.test.ts, test/commands/change-initiative-link.test.ts
The top-level CLI and completion surfaces add --store, hide --store-path, remove set, and update new change flag handling and docs.
Workflow commands and outputs
src/commands/workflow/*, src/commands/show.ts, src/commands/spec.ts, src/commands/change.ts, src/commands/validate.ts, src/core/list.ts
Workflow commands resolve roots, emit banners, include root metadata in JSON, and delegate show/spec/change/validate/list behavior through the selected root.
Archive command and JSON failures
src/core/archive.ts, src/core/specs-apply.ts, test/core/archive.test.ts, test/commands/store-root-selection.test.ts
archive is refactored to resolve roots, support JSON/non-interactive flows, and emit structured blocked diagnostics and JSON results.

Documentation and roadmap reframing

Layer / File(s) Summary
CLI docs and historical roadmap updates
openspec/changes/*, openspec/initiatives/context-store-and-initiatives/*
CLI reference text, legacy workspace guidance, initiative history, and roadmap/task documents are rewritten to point at the new simplify-context-and-workspace-model direction.
/work guidance and slice artifacts
openspec/work/*
The new /work documentation, goal/roadmap, slice specs, and HTML review pages describe the simplified model and its supporting artifacts.

Sequence Diagram(s)

sequenceDiagram
  participant CLI as CLI commands
  participant Root as resolveRootForCommand
  participant Store as context-store registry
  participant OS as inspectOpenSpecRoot
  participant Ops as context-store operations

  CLI->>Root: resolve with store / nearest / implicit inputs
  Root->>Store: read registry and identity metadata
  Root->>OS: inspect candidate OpenSpec root
  Root->>CLI: return ResolvedOpenSpecRoot / diagnostic payload

  Ops->>OS: ensureOpenSpecRoot / inspectOpenSpecRoot
  Ops->>Store: commit registration state
  Ops->>Ops: rollbackCreatedPaths on failure
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~90+ minutes

Possibly related PRs

  • Fission-AI/OpenSpec#1025: This PR rewrites several workspace reimplementation roadmap and proposal documents that the current changes mark obsolete or pending deletion.
  • Fission-AI/OpenSpec#1089: This PR is directly connected because the current diff removes set change and changes new change/--areas/--initiative handling in the same command surface.
  • Fission-AI/OpenSpec#1127: This PR is related because it previously introduced workflow and initiative-link surfaces that are now being removed or replaced by the root-selection model.

Suggested reviewers

  • alfred-openspec

Poem

🐰 I hopped through roots and found the trail,
Specs now know where truth sets sail.
Work is motion, clear and bright,
With banners, roots, and JSON light.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/store-root-parity

TabishB added 8 commits June 10, 2026 02:01
Implements the store-root-selection slice (1.2, with 2.1 pulled forward):

- Add a shared OpenSpec-root resolver (src/core/root-selection.ts) behind
  new change, status, instructions, list, show, validate, and archive.
  --store <id> resolves a registered context store to an ordinary OpenSpec
  root; identity and root-health failures point to context-store doctor.
- Leftover workspace view state never wins root resolution for these
  commands, and a no-root directory with registered stores errors with a
  store-selection hint instead of scaffolding an implicit root.
- Selected-store runs print "Using OpenSpec root: <id> (<abs path>)" to
  stderr and JSON successes carry an additive shared root block.
- --store-path is rejected deliberately with context-store register
  guidance, including on show despite allowUnknownOption.
- new change is root selection only: initiative-link creation is removed,
  --initiative and --areas reject before any writes, --goal stays ordinary
  metadata. openspec set change is removed along with initiative-link.ts.
- archive gains --json: non-interactive, machine-readable diagnostics for
  blocked paths, and no prose or blank lines on stdout.
- list gains minimal --specs --json support so specs listing participates
  in the root reporting contract.
- context-store setup/register next steps show --store usage.
- archive --json: silence the REMOVED-deltas-on-new-spec warning from
  buildUpdatedSpec so the JSON payload stays pure.
- Resolver: wrap registry reads so a corrupt registry surfaces as a
  RootSelectionError; JSON mode now emits a machine-readable diagnostic
  instead of a blank stdout line.
- archive --store (human): per-spec update lines use the absolute store
  path, matching the cross-root absolute-paths contract.
- Noun-form spec show keeps its forward-slash relative not-found message
  on all platforms; root-aware show reports the absolute path.
- Tests: archive --json purity for REMOVED-delta and spec-update-failure
  paths, corrupt-registry JSON diagnostics, and running inside the
  standalone store repo without --store.
The archive spec-update phase validated and wrote each rebuilt spec in a
single loop, so a later validation failure could leave earlier specs
already modified while reporting "No files were changed". Split it into
two passes: validate every rebuilt spec first, then write only after all
pass. Regression test covers a two-spec change where one rebuilt spec
fails validation and asserts no target spec was created or modified.
Rewrites the opening sections of the old initiative and workspace
reimplementation artifacts as transition evidence and beta history, and
adds the direction-git-native-work transition note. Readers are pointed
to openspec/work/simplify-context-and-workspace-model/ for the active
direction.
Adds the slice 1.2 spec, plan, and decision-review evidence, and updates
the roadmap: 1.2 is implemented and tested on this branch, with review
follow-up and merge remaining.
@TabishB TabishB changed the title [codex] Implement context store root parity [codex] Standalone OpenSpec repos: store root parity and --store root selection Jun 10, 2026
@TabishB TabishB marked this pull request as ready for review June 10, 2026 17:21

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@openspec/work/simplify-context-and-workspace-model/slice-1.2-decision-review.html`:
- Around line 341-353: The clickable DIVs used for cards and options
(onclick="setActive('${d.id}')" on the card and
onclick="event.stopPropagation(); choose('${d.id}','${k}')" on the opt) are not
keyboard-accessible; change those interactive elements to semantic <button>
elements (or, if you must keep DIVs, add role="button", tabindex="0" and keydown
handlers that call setActive and choose on Enter/Space and stopPropagation where
needed) and ensure focus styles and ARIA labels are preserved; update the card
container (currently class "card") and option elements (class "opt") to use the
new buttons or key handlers so keyboard users can activate setActive and choose
reliably.

In `@src/commands/workflow/instructions.ts`:
- Around line 64-70: The spinner started with "const spinner = options.json ?
undefined : ora('Generating instructions...').start();" is not stopped on
early-return after calling resolveRootForCommand; update the early-return paths
in the instructions command (where resolveRootForCommand(...) returns falsy) to
call spinner?.stop() before returning, and apply the same change to the other
early-return block later in the same file (the second unresolved-root return
around lines 383-389) so the ora spinner is always stopped in interactive mode.

In `@src/commands/workflow/status.ts`:
- Line 46: The spinner started with const spinner = options.json ? undefined :
ora('Loading change status...').start() may be left running on early returns for
unresolved root; before every return in the unresolved-root branches (and any
other early return paths in this function), stop the spinner by calling
spinner?.stop() (or spinner && spinner.stop()) so non-JSON flows don't leave a
stale spinner; update the unresolved-root return sites to call spinner?.stop()
immediately before returning.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1e3f0630-136b-4989-82d5-399ef1f67035

📥 Commits

Reviewing files that changed from the base of the PR and between 1b06fdd and e3b053d.

📒 Files selected for processing (61)
  • docs/cli.md
  • openspec/changes/workspace-agent-guidance/proposal.md
  • openspec/changes/workspace-apply-repo-slice/proposal.md
  • openspec/changes/workspace-reimplementation-roadmap/HISTORICAL_DIRECTION.md
  • openspec/changes/workspace-reimplementation-roadmap/POC_REFERENCE_GUIDE.md
  • openspec/changes/workspace-reimplementation-roadmap/README.md
  • openspec/changes/workspace-reimplementation-roadmap/START_HERE.md
  • openspec/changes/workspace-reimplementation-roadmap/proposal.md
  • openspec/changes/workspace-verify-and-archive/proposal.md
  • openspec/initiatives/context-store-and-initiatives/README.md
  • openspec/initiatives/context-store-and-initiatives/decisions.md
  • openspec/initiatives/context-store-and-initiatives/direction-git-native-work.md
  • openspec/initiatives/context-store-and-initiatives/direction.md
  • openspec/initiatives/context-store-and-initiatives/roadmap.md
  • openspec/initiatives/context-store-and-initiatives/tasks.md
  • openspec/initiatives/context-store-and-initiatives/work-items/13-agent-handoff-output-and-delivery-polish/evidence.md
  • openspec/initiatives/context-store-and-initiatives/work-items/13-agent-handoff-output-and-delivery-polish/plan.md
  • openspec/initiatives/context-store-and-initiatives/work-items/13-agent-handoff-output-and-delivery-polish/tasks.md
  • openspec/work/AGENTS.md
  • openspec/work/README.md
  • openspec/work/simplify-context-and-workspace-model/goal.md
  • openspec/work/simplify-context-and-workspace-model/roadmap.md
  • openspec/work/simplify-context-and-workspace-model/slice-1.2-decision-review.html
  • openspec/work/simplify-context-and-workspace-model/slices/store-root-parity/plan.md
  • openspec/work/simplify-context-and-workspace-model/slices/store-root-parity/spec.md
  • openspec/work/simplify-context-and-workspace-model/slices/store-root-parity/user-facing-review.html
  • openspec/work/simplify-context-and-workspace-model/slices/store-root-selection/plan.md
  • openspec/work/simplify-context-and-workspace-model/slices/store-root-selection/spec.md
  • src/cli/index.ts
  • src/commands/change.ts
  • src/commands/context-store.ts
  • src/commands/show.ts
  • src/commands/spec.ts
  • src/commands/validate.ts
  • src/commands/workflow/index.ts
  • src/commands/workflow/initiative-link.ts
  • src/commands/workflow/instructions.ts
  • src/commands/workflow/new-change.ts
  • src/commands/workflow/set-change.ts
  • src/commands/workflow/shared.ts
  • src/commands/workflow/status.ts
  • src/core/archive.ts
  • src/core/completions/command-registry.ts
  • src/core/completions/shared-flags.ts
  • src/core/context-store/errors.ts
  • src/core/context-store/operations.ts
  • src/core/context-store/registry.ts
  • src/core/index.ts
  • src/core/list.ts
  • src/core/openspec-root.ts
  • src/core/root-selection.ts
  • src/core/specs-apply.ts
  • test/commands/artifact-workflow.test.ts
  • test/commands/change-initiative-link.test.ts
  • test/commands/context-store.test.ts
  • test/commands/store-root-selection.test.ts
  • test/core/archive.test.ts
  • test/core/completions/command-registry.test.ts
  • test/core/context-store/registry.test.ts
  • test/core/openspec-root.test.ts
  • test/core/root-selection.test.ts
💤 Files with no reviewable changes (3)
  • src/commands/workflow/set-change.ts
  • src/commands/workflow/initiative-link.ts
  • src/commands/workflow/index.ts

Comment on lines +341 to +353
<div class="card ${state.active===d.id?'active':''}" onclick="setActive('${d.id}')">
<div class="card-top">
<span class="dot ${chosen?'decided':''}"></span>
<span class="card-title">${d.num}. ${esc(d.title)}</span>
</div>
<div class="card-stake">${esc(d.stake)}</div>
<div class="opts">
${['a','b'].map(k => `
<div class="opt ${chosen===k?'selected':''}" onclick="event.stopPropagation(); choose('${d.id}','${k}')">
<span class="radio"></span>
<span>${esc(d.options[k].label)}</span>
${d.rec===k?'<span class="rec-badge">rec</span>':''}
</div>`).join('')}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Make interactive choices keyboard-accessible.

Line 349 and Line 372 use click-only div controls, so keyboard users cannot reliably choose options/panes. Please switch to semantic buttons (or add role="button", tabindex="0", and Enter/Space key handlers) for all actionable items.

Suggested minimal patch
- <div class="opt ${chosen===k?'selected':''}" onclick="event.stopPropagation(); choose('${d.id}','${k}')">
+ <div
+   class="opt ${chosen===k?'selected':''}"
+   role="button"
+   tabindex="0"
+   onclick="event.stopPropagation(); choose('${d.id}','${k}')"
+   onkeydown="if(event.key==='Enter'||event.key===' '){event.preventDefault();event.stopPropagation();choose('${d.id}','${k}');}"
+ >
...
- <div class="pane ${chosen===k?'selected':''}" onclick="choose('${d.id}','${k}')">
+ <div
+   class="pane ${chosen===k?'selected':''}"
+   role="button"
+   tabindex="0"
+   onclick="choose('${d.id}','${k}')"
+   onkeydown="if(event.key==='Enter'||event.key===' '){event.preventDefault();choose('${d.id}','${k}');}"
+ >

Also applies to: 372-374

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@openspec/work/simplify-context-and-workspace-model/slice-1.2-decision-review.html`
around lines 341 - 353, The clickable DIVs used for cards and options
(onclick="setActive('${d.id}')" on the card and
onclick="event.stopPropagation(); choose('${d.id}','${k}')" on the opt) are not
keyboard-accessible; change those interactive elements to semantic <button>
elements (or, if you must keep DIVs, add role="button", tabindex="0" and keydown
handlers that call setActive and choose on Enter/Space and stopPropagation where
needed) and ensure focus styles and ARIA labels are preserved; update the card
container (currently class "card") and option elements (class "opt") to use the
new buttons or key handlers so keyboard users can activate setActive and choose
reliably.

Comment thread src/commands/workflow/instructions.ts Outdated
Comment thread src/commands/workflow/status.ts
TabishB added 15 commits June 11, 2026 05:15
Spec and plan for slice 1.3 (prove the standalone repo lifecycle end to
end), with two review rounds folded in. Adds slice 1.4 to the roadmap,
parks archive browsability as L11, and records the single-branch
workflow for the whole roadmap.
Implements slice 1.3 (store-lifecycle-proof):
- Setup defaults to Git with a pathspec-limited initial commit of exactly
  the files it created, writes store.yaml before committing, anchors
  empty directories with .gitkeep, preflights commit identity via git var
  before creating anything, and requires an explicit --path (interactive
  setup prompts with a visible user path).
- Doctor reports read-only Git facts (commits, uncommitted changes,
  remote) and warns on commitless repos and clone-fragile directories.
- Register errors are terminal: one-checkout-per-id with the unregister
  escape, registration-aware id-mismatch fix text, and an empty-clone
  explanation on unhealthy roots.
- Selected-store hints carry --store, the root banner prints at
  resolution time so post-resolution failures keep it, new change names
  its next command, and status drops the workspace-era Planning home
  line.
- Adds the two-checkout journey e2e test (machine A lifecycle, machine B
  clone/register/continue) with fully isolated Git config and XDG state.
Two adversarial subagent reviews of the slice 1.3 implementation found
one spec violation and several correctness risks; all are fixed:

- Hints carry --store everywhere: validate/show non-interactive hints,
  archive blocked-path fix texts, and status JSON nextSteps now thread
  the selected store. Status JSON also drops the workspace-era
  planningHome field.
- Reruns of an already-registered store no longer git-init it (the CLI
  default is resolved against the registry via resolveSetupGitEnabled),
  keeping reruns strict no-ops.
- Failed initial commits unstage setup's files so a user repo is not
  left with a dirty index; once the commit lands, cleanup no longer
  deletes the committed files; fresh-dir cleanup is non-recursive again
  so it can never delete content setup did not create.
- Corrupt or fake .git dirs report Git facts as unknown instead of
  commitless, avoiding misleading empty-clone advice.
- The sharing next-step line only prints for actual repositories.
- Journey test: Windows-safe path assertions, telemetry opt-out, machine
  B now runs the full enumerated command set (instructions, validate),
  asserts register creates no commits, covers the banner-on-failure and
  store-carrying-hint contract, and doctor human output. Unit tests gain
  isolated git config, register error-text coverage for both mismatch
  branches, and a default-flags rerun no-op regression test.

Full suite: 93 files, 1729 tests, green.
Follow-up review findings: the invalid-report next step pointed at the
deprecated cwd-based 'openspec change show <id>' and dropped --store; it
now names the supported top-level 'openspec show <id> --json
--deltas-only' with the actual change id and the store flag. The
nothing-to-show fallback hints and the ambiguous-item advice in validate
and show no longer suggest noun-form commands when a store is selected,
since those commands cannot reach a store root; store mode gets
--type-scoped top-level equivalents instead. No-store output is
unchanged.
Code-quality review follow-up:

- The initial commit was built from the rollback ledger, which is the
  wrong concept: for a converted (existing, non-Git) root it committed
  only the new anchors and identity file, leaving config and specs
  uncommitted and clones unhealthy. When setup initializes the repo
  itself, it now commits the full store shape (openspec/ plus
  .openspec-store/), while pre-existing repos keep the
  only-what-setup-created commit that protects user history and staged
  files. Old beta files outside the store shape are never swept in.
- Identity-file creation is now owned solely by setup; registration runs
  with writeMetadataIfMissing: false and verifies instead of writing,
  removing the split ownership that made the commit plan leaky.
- Git probing, init, identity preflight, and commit mechanics moved from
  operations.ts (1204 lines) into src/core/context-store/git.ts;
  operations.ts is back to 1077 lines and owns only the lifecycles.
- Git lifecycle tests split into test/commands/context-store-git.test.ts
  with shared fixtures in test/helpers/context-store-git.ts, including a
  new conversion test that proves a clone of a converted root is
  immediately healthy.

Spec and plan updated to lock the two commit modes. Full suite: 94
files, 1730 tests, green.
Fresh-eyes review outcome, settled in discussion: the layered
PM/architect-to-dev use case (high-level requirements in a standalone
store, implementation work in the app repo's own OpenSpec root) replaced
the rejected project-to-store binding idea with declared relationships
between roots and a fixed resolution precedence — explicit --store, then
nearest local root, then a declared default only when no local root
exists, then error with hint. References never change where commands
act.

- Slice 1.4 becomes one guidance pass (absorbs old 2.2; ~13 surfaces
  from research) gated on the context-store terminology decision
  promoted from L7.
- Phase 2 is fully absorbed: 2.1 shipped in 1.2, 2.2 into 1.4, 2.3 into
  4.1 (initiative selection is hardcoded into ~5,500 lines of opening
  machinery that 4.1 rebuilds; refactoring first is wasted motion).
- Phase 3 rewritten around relationships in both directions, references
  first: repo-references-stores, declared-store fallback, canonical
  remote in store identity, then store-level target declarations, local
  repo map, and relationship health reporting.
- Phase 4 reframed as context assembly; editor opening is one consumer,
  an agent session brief is another.
- New guardrails: references are repo-level config, never per-change
  lifecycle links; one change lives in one root.
- goal.md gains the layered reference experience.
Decisions settled after parallel product-level and staff-engineer
analyses:

- Naming: the noun is 'store', defined as 'a standalone OpenSpec repo
  you've registered'. The context-store → store group rename plus the
  full machine-token rename (diagnostic codes, JSON keys, data dir) land
  first in slice 1.4; --store stays; committed store-repo formats are
  already aligned and stay. openspec repo/--repo rejected: the --repo
  prior means the code repo being operated on, colliding with target
  project repos.
- Phase 3: index-not-inline reference injection; references: and the
  fallback store: pointer both live in openspec/config.yaml (top-level
  marker rejected — .openspec.yaml is taken by change metadata); one
  typed id namespace with the kebab grammar locked for all id kinds;
  relationships are location, declaration, or citation — never managed
  per-artifact links, which is what initiative links were.
- Phase 5 criteria agreed: delete rather than hide, sequenced across
  1.4, a small command-group deletion slice, and 4.1; never auto-delete
  user data.
No pause gates: unlocked decisions are made autonomously and recorded
as 'Decided autonomously (review me)' changelog lines; Phase 5
deletions proceed without confirmation. Review phases run as parallel
multi-agent Workflows plus the /code-review skill (high effort) and
codex CLI; /simplify runs serially after correctness fixes.
Serial across slices (single branch, shared junction files, mass
rename/deletion commits make cross-track rebases the riskiest
unattended operation); Workflow fan-outs within slices for mechanical
sweeps; read-only lookahead research for the next slice's code map.
The docs position /loop as interval-based and /goal as the
condition-based counterpart: turns fire back-to-back until a verifiable
completion condition is met, with full main-loop tool and skill access
per turn and persistence across resume. That matches the queue's
semantics (next unit when the previous finishes, stop when done), so
loop.md becomes runbook.md, reframed around goal-driven turns with an
explicit per-turn status block for the goal evaluator and a declared
completion signal.
The goal condition previously checked activity (boxes ticked, suite
green); it now checks the product claim. Phase 6 / capstone 6.1: four
persona journeys including a cold-start agent dogfood, usability audits
(error catalog, vocabulary sweep, time-to-first-success), technical
audits (single-resolver invariant, dependency direction, dead code,
module sizes, agent-contract inventory, net LOC delta vs origin/main),
a whole-delta review gauntlet, and a committed release-readiness
report. Runbook gains standing per-slice quality bars: locked
vocabulary only, pasteable store-carrying errors, consistent agent
contracts, ~600-line module budget, no speculative abstractions, one
resolver.
Two parallel adversarial reviews (subagent, codex CLI) converged on the
same flaw in the first draft: exempting the legacy groups from the token
rename contradicted the locked machine-token decision. The spec now
states one rule - total mechanical token rename, surgical prose rewrite,
behavior changes limited to the two riders - and folds the corrected
45-code token inventory, the missed guidance surfaces, and a
sweep-as-test acceptance criterion.

@alfred-openspec alfred-openspec left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed root parity and the --store command paths. I do not see a blocking runtime issue: root shape checks, setup/register idempotency, rollback of created OpenSpec artifacts and metadata, existing-store compatibility, CI, and the full local test suite all look good.

Only cleanup ask before merge: I would drop or convert the generated HTML review artifacts unless we intentionally want static review prototypes under openspec/work; if they stay, please fix the accessibility nits CodeRabbit flagged.

Four green checkpoints: mechanical rename, the two riders, guidance
regeneration (three disjoint streams), and sweep/guards/dogfood. Both
parallel reviews (subagent, codex CLI) approved with fixes, all folded:
exact rider-1 deletion list with persisted path-bound views preserved,
Commander command:* error ownership, docs/concepts.md and beta-doc
runtime fixes, sweep roots excluding openspec/ history, old-data-dir
negative fixtures, pinned non-interactive dogfood init flags.
TabishB added 30 commits June 11, 2026 20:38
The working set a root's declarations describe, in one command: the
JSON agent brief (root + members with roles, absolute paths, fetch
recipes on available stores, and the existing fixes verbatim on
unavailable members), the human listing with the Not-available
section, and the --code-workspace editor view (available members only;
ref:/repo: folder prefixes; the pinned write matrix - typed
context_file_exists refusal, --force, no implicit mkdir, stderr
confirmation under --json; stale mapped paths excluded - reported, not
guessed). Assembly is presentation over the 3.6 composition through
the new shared command gather (doctor refactored onto it,
behavior-identical); fetchRecipe exported as the one recipe source.
STORE_SELECTION_GUIDANCE gains context with the parity hashes and
completions pins updated deliberately; docs add the section and the
project-context vs working-context disambiguation.

Full suite green (95 files, 1711 tests).
Three review mechanisms converged; all fixed with regression tests:
the --json + --code-workspace failure path now leaves exactly one JSON
document on stdout (the write runs before the brief is printed; both
failure modes pinned); context mirrors doctor's self-reference honesty
('Declared references all resolve to this root' instead of the false
'nothing declared'); the registry degradation is selected by
diagnostic code, never by array position (the fragile health.status[0]
coupling and the redundant boolean+diagnostic pair are gone); the
write summary names the skipped member ids instead of pointing JSON
users at a listing that is not there, with the count arithmetic in
plain form; the dead planningHome params on
buildNextSteps/buildActionContext inputs and their loader threading
are removed; the leftover binding imports in registry.test.ts and
three pieces of edit debris are swept; the ledger's Surviving-tokens
section is pruned; the doctor docs section cross-links context; and
the spec's working-set/builder unit-test bullet is fulfilled
(test/core/working-set.test.ts - the mapping table, ordering,
availability rule, by-code selection, and builder shape).

Skipped with reasoning: suppressing the resolver's both-shapes stderr
warning for context runs (codex P3) - that warning is 3.2 family
behavior for every command at resolution time; forking it per command
would fragment the one-resolver contract. Recorded for the capstone.

Full suite green (96 files, 1715 tests).
Simplify: the stale-path stat sweep moves into shared-gather as
missingDeclaredRepoPaths (doctor and context both consume it; the
header comment now tells the truth); the dead Windows-path machinery
in planning-home dies with the stale workspace-kind test that was its
only exerciser (formatChangeLocation collapses to path.relative); the
garbled vocabulary-sweep comment is repaired; doctor's dead fs import
removed; the context_output_dir_missing code recorded as a plan
amendment instead of silent drift. Skipped with reasoning: the
printEntryDiagnostics extraction (net-zero lines, couples two
surfaces' voices); the three filter passes (readability beats a
one-pass accumulator at single-digit N); PlanningHomeSummary identity
(recorded for the capstone).

Roadmap: 4.1 boxes ticked, Phase 4 complete on the branch, pointer
moved to the Phase 5 remainder.
Full suite green (96 files, 1714 tests).
Per the locked delete-don't-hide criteria, after 4.1 as queued
(decision record: slices/delete-legacy-command-groups/remainder.md):
schemas/workspace-planning/ deleted (openspec schemas still advertised
the dead workflow); the four workspace-* beta change folders deleted
(unimplemented relics - archiving would assert completion; git
preserves); L2 decided - the four wholly-workspace accepted specs
deleted (capability gone = spec gone) and the workspace requirements
excised from cli-config and cli-artifact-workflow (two requirements,
eight scenarios - bounded short of the docs rewrite the roadmap
forbids). Incidental mentions in five other specs recorded for the
capstone vocabulary audit. All 36 remaining accepted specs validate;
full suite green untouched (96 files, 1714 tests).
Journeys 2 and 3 land as standing e2e in
test/cli-e2e/capstone-journeys.test.ts - the layered PM-to-dev flow
(an app-repo agent discovers the reference from config via openspec
context, cites the upstream spec by following the fetch recipe
verbatim, and writes its design change in the app repo's own root
while the store stays read-only) and externalized planning (a code
repo with only a store: pointer runs new-change through archive with
zero --store flags and never grows planning state). Journey 1 is the
standing store-lifecycle e2e. Journey 4 ran as a live cold-start
headless dogfood: a fresh codex session given only a vague prompt and
--help output assembled the full intended topology - store setup,
targets declaration, pointer config, repo mapping, and
doctor/context/validate self-verification. Results recorded in
capstone/journeys.md.

Full suite green (97 files, 1716 tests).
Error-catalog walk: 55 wrong turns exercised live across 13 families
(human + JSON) against the actionable/store-carrying/correct-exit/
honest bar - 46 pass. The resolution-layer taxonomy held
(differentiated no-root hints, single-document JSON failures,
shell-parseable clone fixes, bidirectional namespace collisions). Nine
failures recorded and queued for the capstone fix round: 1 P1 (raw
YAML stack trace on unparseable real-root configs), 4 P2 (pathless
corrupt-registry fix that dead-ends through store doctor, instructions
dropping its Fix line, validate summaries without drill-down,
implicit scaffolding creating doctor-unhealthy roots), 4 P3.
Vocabulary sweep incl. docs/cli.md: clean except the legacy
ChangeStatus.initiative JSON passthrough (queued; the schema keeps
parsing user data). Time-to-first-success measured live: 2 commands,
2 concepts, each step printing the next command.
All nine error-catalog failures plus the vocabulary finding, with the
test pins updated deliberately:

P1 - unparseable real-root configs no longer dump a YAMLParseError
stack trace: readProjectConfig warns with one line naming the file and
the first error line only (pinned: single line, no node_modules).
P2 - the corrupt-registry fix names the actual registry file path; the
CLI's shared error wrapper (17 catch sites) now prints the diagnostic
fix line it used to drop, so instructions and every sibling carry the
pasteable next step; validate failure summaries print a drill-down
command carrying --store (derived from the resolved root); implicit
scaffolding (new change in a bare dir, non-interactive init) now
creates the complete healthy shape - specs/, changes/archive/, and a
minimal config.yaml - so doctor calls the result ok instead of
unhealthy.
P3 - the malformed-pointer warning on real roots names the file; the
declared-pointer unknown-store fix is reshaped for the actual mistake
(register the store or edit the named config - the user never passed
--store); the store-register-at-code-repo fix offers repo register;
archive not-found lists available changes like its status sibling.
Vocabulary - the legacy ChangeStatus.initiative passthrough is gone
from every surface (status JSON/human, instructions XML, apply text);
the metadata schema still PARSES stored links (user-data tolerance,
pinned by the flipped legacy tests: tolerated, not re-emitted).

Full suite green (97 files, 1716 tests).
Single-resolver invariant HOLDS: one precedence implementation, nine
command entry points through it, doctor/init extra walks verified as
post-resolution diagnostics and scaffold guards; one latent
unreachable fallback queued for deletion. Dependency direction HOLDS:
zero core->commands/cli imports. Dead-code sweep over the 213-file
delta: no P2s, five P3s queued, four notes recorded (incl. the ext::
transport status: zero occurrences, the shell-safe gate and
team-committed trust boundary hold). Module sizes bounded (largest
1,160 lines). docs/agent-contract.md committed - every JSON shape,
the diagnostic envelope, failure payloads, the exit-code contract, and
the full diagnostic-code catalog verified against emitting code, with
14 consistency findings; the gauntlet-grade one (several --json
failure paths emit no JSON document) is queued for the gauntlet fix
round. Net LOC vs origin/main: src -4,478, test -325 - net-negative
as the roadmap expected.
Four mechanisms over origin/main...HEAD: /code-review at max effort
(all 12 verified candidates CONFIRMED, most live-reproduced), a
32-agent adversarial Workflow (six lenses, refute-style verification:
25 confirmed + 7 completeness gaps), a codex whole-delta review
(FIX-FIRST), and the audits' queued items. Consolidated: 2 P1 (the
~/openspec layout turning $HOME into a phantom nearest root that
captures every lifecycle command under the home tree; status/
instructions --json errors emitting no JSON document), 13 P2 (the
JSON-failure-contract family, the --store-path seam, doctor's
up-walking origin probe, the stale registry lock, config-only
half-scaffolds, prompt-injection via verbatim hostile strings, five
more accepted specs requiring deleted behavior, stale planningHome
guidance in generated skills, a syntactically-broken zsh completion
script, store-remove delete-before-commit, the setup TOCTOU pair, the
orphaned-.git empty-clone path, the metadata rollback race), and a
triaged P3 set split into queued-cheap vs recorded-for-report. The
gauntlet box ticks only when every P1/P2 is fixed and re-verified.
P1: the nearest-root walk now skips openspec/ directories that are
neither planning-shaped nor configured - the recommended ~/openspec
store layout no longer turns $HOME into a phantom root that captures
every command under the home tree (regression test: the
registered-store hint fires instead). status/instructions/list/show/
validate --json failures all emit exactly one JSON status document
(JSON-aware shared failure helper; the stray blank stdout lines are
gone; store <unknown subcommand> --json emits a typed document; list
carries its null-shape).

P2: doctor/context gain the --store-path rejection seam; doctor's
origin probe is guarded by isGitRepositoryAtRoot (no more enclosing-
repo origins or spurious divergence notes); the registry lock steals
orphans older than 30s, names the lock path in the busy fix, and
reports permission problems as what they are; change scaffolding
completes the root shape for config-only roots and records the project
default schema, never a one-change --schema override; hostile-content
renders are sanitized at the index/render boundary (spec ids,
summaries at index time, remotes in targets and divergence messages -
control characters can no longer forge instruction lines); the five
remaining workspace-requiring accepted specs got the bounded excision
(all 36 validate); status JSON carries planningHome again (the
generated skills' published archive contract - restored rather than
rewriting eleven template references); the zsh completion generator
uses the correct quote idiom (generated script now passes zsh -n);
store remove commits the registry removal BEFORE deleting files (a
failed deletion degrades to a store_files_left_on_disk warning, never
a phantom registration); setup re-asserts directory facts at execute
(store_setup_path_changed) killing the stale-kind recursive-rm TOCTOU;
the half-made .git cleanup no longer hides behind the created-paths
ledger (no more commitless-store reruns); the metadata rollback
re-reads the registry and never deletes metadata a committed
registration depends on.

P3 (cheap set): CommonMark-correct fence tracking in purpose
extraction; the stale-target sweep requires a DIRECTORY; pretty JSON
for empty list; the declared-pointer repo-id fix names the config
file; absolute change location when the root is not the cwd; docs
fixes (affected_areas legacy wording, --remote in the setup table,
vibe in --tools, the real list output example); agent-contract.md
updated to match (planningHome restored, the failure-contract claim
now true).

Test pins updated deliberately: the store --json hint, the remove
ordering contract, the zsh escaper, the truncation corpus (summaries
now cap at index time, so the budget trips on count).

Full suite green (97 files, 1717 tests).
…d (6.1)

All 15 gauntlet P1/P2 fixes re-verified live (the JSON-contract codes
on show/validate/status/instructions/store, the --store-path seam on
doctor, the stale-lock steal, the config-only scaffold completion, the
phantom-root regression). The gauntlet ledger marks every finding
fixed. The release-readiness report lands with the five-minute
new-user story (2 commands, 2 concepts, proven cold by a headless
agent), the full audit results, the 18-entry autonomous-decision
ledger, and known gaps mapped to Later Ideas - no open P1/P2 findings
anywhere. Every queue item's roadmap boxes are ticked except Merged to
main, which this run deliberately does not perform.

Full suite green (97 files, 1717 tests); 36 accepted specs validate.
The G1 test omitted globalDataDir and never registered a store, so it
passed locally only by accident (it saw this machine's REAL registry)
and failed on the clean CI runner, where the empty registry correctly
fell through to the implicit root. The test now registers a store in
its isolated registry and passes globalDataDir, making the
no_root_with_registered_stores expectation deterministic everywhere.

Full suite green (97 files, 1717 tests).
Evidence base for the spec: the f858c19^ opener archaeology (two-style
launch split, PATH/PATHEXT scan, cross-spawn handoff mechanics, the
not-to-inherit ledger), current-tree idioms (registry lock/atomic-write,
the pure .code-workspace builder, the @InQuirer house rules, JSON
contracts), and live CLI verification of code/cursor/claude/codex flag
spellings and hazards.
A two-sided audit of the whole delta (production code and tests)
against the cross-platform rules, with every finding fixed:

Production: extractFirstPurposeLine splits on \r?\n (CRLF checkouts -
the Git-for-Windows default - previously got empty summaries for every
referenced spec); the clone-recipe fix quotes for the rendering
platform (single quotes are literal characters in cmd/PowerShell -
win32 now gets double quotes); the registry path-comparison fallback
resolves nonexistent paths instead of raw string-comparing them; the
manual-deletion fix drops its POSIX-only rm -rf; repo register expands
~ via the same expandUserPath every store command uses.

Tests: the onboarding e2e no longer depends on HOME (USERPROFILE set
alongside), declares its local remote in shell-safe forward-slash
form, pins the platform-correct quote style, and executes the fix via
argv arrays instead of split(' ') re-tokenization (paths with spaces);
the store-references normalizer matches the JSON-escaped needle
(serialized Windows paths double their backslashes); the
metadata-path assertion uses path.join; snapshot keys are
POSIX-normalized in the shared helper and both local copies.

Audited clean: registry/conflict path identity (canonicalized both
sides via realpathSync.native), cross-drive path.relative guards,
getGlobalDataDir's win32 branches, git invocations (argv arrays),
the lock and atomic-write semantics, XDG isolation, fetch-recipe
splits (no paths), and the deliberate-POSIX display literals.

CI: the OS test matrix (linux/macos/windows) previously ran ONLY on
push to main - it now also runs on workflow_dispatch so branches can
get a real Windows verification before merge.

Full suite green locally (97 files, 1717 tests).
The references.test.ts pin asserted the POSIX single-quote form; the
implementation now deliberately renders double quotes on win32 - the
one remaining windows-pwsh matrix failure. The doctor/context pins are
quote-agnostic (stringContaining on the unquoted prefix) and the
onboarding e2e was already platform-aware.
Subagent: approve-with-fixes; codex: reject (converging). The P1 -
attach-dirs argv now carries one attach pair per member, primary
included, per the locked FR2 wording. Folded: no-tool open path,
stale-saved-tool rule, signal exit contract, the hand-edit parse
contract, pinned JSON envelopes (incl. the open --json typed
rejection), derived-file locking with ENOENT-tolerant remove, the
teammate scenario, the win32 availability matrix, and opener-config
touchpoints. Research+spec roadmap box ticked; changelog entries added.
Subagent: approve-with-fixes; codex: reject (converging). The shared P1:
open now regenerates the .code-workspace under the lock BEFORE tool
resolution, so every fallback names an existing current file. Also
folded: real busy-error factory sites with new byte-shape pins (the
suite never covered the lock mechanics), withWorksetsLock, cross-spawn
import shape, the --member collector, injectable-spawn units for
SIGINT/launch-failed, in-process cancellation coverage with enumerated
capstone carve-outs, the win32 stat-seam fixture strategy, the recorded
TOCTOU, anchor drift fixes, and the spec d12 amendment dropping the
dead workset_create_cancelled code.
src/core/file-state.ts extracts writeFileAtomically and the lock-acquire
loop from store foundation (errors stay caller-owned via the injected
factory; store shapes pinned byte-identical by new tests - the suite
never covered the lock mechanics before). src/core/worksets.ts: the
saved-views file under <dataDir>/worksets/ on the registry idiom (strict
zod + version 1, hand-edit parse contract, withWorksetsLock
read-without-write, pure rebuilds, the .code-workspace builder).
src/core/openers.ts: the locked built-in table, per-field config merge
over built-ins, the PATH/PATHEXT availability scan with an injectable
stat seam, and the pure two-style launch-command builder (one attach
pair per member, never a positional). GlobalConfig gains the openers
key. 42 new unit tests; full suite green (99 files, 1759 tests).
src/commands/workset.ts: create (guided 3-step wizard / non-interactive
--member collector with name=path labels), list, open (regenerate the
.code-workspace under the lock before any tool resolution so every
fallback names a current file; cross-spawn handoff with honest
exit-code and 128+signal propagation; the Open manually: block on every
cannot-drive failure; hidden --json rejected as one typed JSON
document), remove (plan-then-confirm, --yes, ENOENT-tolerant derived
cleanup under the lock), and the command:* unknown-subcommand handler.
isPromptCancellationError extracted to shared-output (third copy).
CLI + completions registration, the docs/cli.md section and table rows,
the resurrected path-env helper, the fake-tool recorder, 34 command
tests (incl. in-process launch mechanics and interactive-cancellation
coverage via mocked prompts), and the two e2e journeys (no-footprint +
teammate isolation). Full suite green (101 files, 1795 tests).
Spec-compliance (compliant-with-fixes), /code-review seven-angle
fan-out, and codex (approve-with-fixes) converged with no P1s.
Behavioral: structural open-fallback rule (surviving members, every
post-regeneration failure except cancellation), the primary-
reassignment note, honest zero-tools message, pasteable launch-failed
alternative, post-save Ctrl-C declines instead of cancelling, parent
signal guard during launch (the 128+n contract was unreachable for tty
SIGINT), sync spawn throws wrapped, tool.cmd PATHEXT double-append
removed, bare workset --json keeps the one-document contract,
deadline-bounded lock stat failures, remove cleanup after the durable
write, early flag-member validation, lazy cross-spawn (~6ms per CLI
invocation). Structure: command layer split (workset / prompts /
input); shared homes for formatZodIssues, folderStyleNameProblem,
KEBAB_ID_FIX, pathIs*; cancellation lifted into emitFailure with
store collapsed onto it. Tests: +6 cases, controlled PATH for the
in-process interactive suite, win32 path-env key fix. Spec amended to
the shipped contracts. Full suite green (101 files, 1799 tests).
makeLockErrorFactory in file-state (both lock-error factories were
data-twins; store shapes stay byte-pinned), optsWithGlobals over the
hand-rolled group-option merge, the prompt preview ladder flattened
with one assertKnownTool spelling, asErrorMessage hoisted to
shared-output, formatMemberRows deduping three renderers, per-branch
opener resolution in open (dead branch + redundant re-scan gone),
serialize emits validated entries directly, toWorkset dedup, remove
--yes skips the duplicate pre-read, KEBAB_ID_FIX adopted, dead exports
trimmed. Skips recorded (store-group fallback convergence queued for
the next store touch). Full suite green (101 files, 1799 tests).
Scripted walk (both launch styles, exact argv incl. the no-prompt
rule, strand-test fallback, missing-member skip, safe remove,
byte-untouched members), the interactive wizard from a real pty, live
cancellation, and the cold-start headless agent reaching an opened
workset from --help alone. No product findings. Full suite green
(101 files, 1799 tests).
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.

2 participants