Compare commits

..
Author SHA1 Message Date
openspec-release-bot[bot]andgithub-actions[bot] 546224e00d Version Packages (#1248)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-28 13:02:43 +00:00
Tabish Bidiwale 96f6cacb20 chore: add changeset for stores beta and config JSON parsing (#1267)
* Add changeset for stores beta and config JSON parsing

* Remove leaked tool-wrapper lines from changeset
2026-06-28 12:44:00 +00:00
Tabish Bidiwale 737518b36f [codex] Refresh security dependency locks (#1249)
* fix: refresh security dependency locks

* fix: refresh nix pnpm dependency hash
2026-06-24 08:54:03 +00:00
zhangsan582andTabish Bidiwale f987cf3e29 Parse config JSON containers (#1216) (#1244)
Co-authored-by: Tabish Bidiwale <30385142+TabishB@users.noreply.github.com>
2026-06-24 08:06:42 +00:00
Zied JlassiandTabish Bidiwale cbf386bd68 fix(adapters): escape carriage returns in YAML frontmatter and dedupe escapeYamlValue (#1240)
escapeYamlValue detected \r as a character requiring quoting but never
escaped it, leaving a literal carriage return inside the double-quoted
scalar. A literal CR there is subject to YAML line folding/normalization
and could silently corrupt the round-tripped value (realistic with
CRLF-authored command descriptions).

- Escape \r as \r alongside the existing \, " and \n handling.
- Extract the helper, previously duplicated verbatim across five adapters
  (bob, claude, cursor, pi, windsurf), into a shared
  command-generation/yaml.ts module.
- Add unit tests covering the escaping rules and a round-trip through a
  real YAML parser.

Refs #1205, #1204

Co-authored-by: Tabish Bidiwale <30385142+TabishB@users.noreply.github.com>
2026-06-24 08:01:56 +00:00
bb1f18c483 docs: comprehensive overhaul — discoverability, explore-first, and closing recurring doc-request issues (#1237)
* docs: comprehensive documentation overhaul (home, mental model, command location, FAQ, glossary, troubleshooting, recipes)

Addresses #1228 (docs are fragmented and hard to discover). Additive,
docs-only. The single sharpest gap from the issue thread was that nobody
explains where slash commands run, hence the new "How Commands Work" page.

New docs:
- docs/README.md          documentation home / index that maps every doc
- docs/how-commands-work.md  where /opsx:* (chat) vs openspec (terminal) run; "interactive mode" answered
- docs/overview.md        core concepts at a glance, one page
- docs/faq.md             consolidated common questions
- docs/glossary.md        every term in one place
- docs/troubleshooting.md concrete fixes for concrete failures
- docs/examples.md        real changes start to finish (recipes)

Small additive edits:
- docs/getting-started.md  "where do I type this?" callout + first-five-minutes + richer Next Steps
- README.md                Docs list points at the new home and key new pages

Voice: warm, plain, bottom-line-up-front; no em-dashes in prose.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: make /opsx:explore front and center, plus general polish

Per maintainer feedback (Tabish): "the docs in general need some work,
alongside making the explore option a lot more front and center."

explore ships in the default core profile but every doc led with propose
and treated explore as a footnote for "unclear requirements." This reframes
the canonical loop as explore -> propose -> apply -> archive and gives
explore real prominence.

- docs/explore.md (new): dedicated "Explore First" guide. When to use it,
  what it does/doesn't, a full transcript, handoff to propose, tradeoffs.
- getting-started.md: explore added to the flow and first-five-minutes,
  with a featured callout and Next Steps entry.
- overview.md: explore featured in the loop and next-links.
- docs/README.md: explore in the opening, pick-your-path, 30-second
  version, and the doc map.
- how-commands-work.md: explore leads the command list with a "good rhythm"
  note and an optional step in the clean-first-run example.
- workflows.md: new first-class "Start by exploring" pattern in the default
  section (was buried under expanded mode); quick-reference row strengthened.
- commands.md / faq.md / glossary.md: explore featured as the place to start.
- examples.md: top callout pointing at the explore recipe.
- README.md: explore opens the "See it in action" demo and Quick Start,
  and is added to the Docs list.

Docs-only and additive. No em-dashes in prose; links verified.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: close recurring gaps (existing projects, editing changes, uninstall, context limits) + sync tool list

Sweep of open issues and discussions surfaced several questions good docs
should answer but didn't. This adds the missing guides and fixes a stale list.

New guides:
- docs/existing-projects.md: adopting OpenSpec on a large brownfield codebase
  without documenting everything up front (addresses #510, #1100, #176).
  Delta-first framing, first-change walkthrough, onboard, importing existing
  requirements docs, domain organization, monorepo/workspace pointers.
- docs/editing-changes.md: how to edit any artifact, update a proposal/spec
  after starting, go back after implementing, and reconcile manual code edits
  (addresses #684, #976, #355, #1188, #169, #1206).

Enhancements:
- installation.md: Updating + Uninstalling sections (addresses #308).
- faq.md: new entries for existing codebases, editing artifacts, going back,
  reconciling manual edits, context limits / long sessions, and uninstalling
  (addresses #257 among others).
- cli.md: --tools list now includes `vibe` and matches AI_TOOLS in
  src/core/config.ts, with a note pointing at the source (fixes #1213).
- Wired the new guides into the docs home, getting-started, and the README.

Docs-only and additive. No em-dashes in prose; links and section anchors verified.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: reconcile coordinate-across-repos docs with the stores model

The merge with main pulled in the stores rename (#1190), which retired the
workspaces/initiatives/context-store vocabulary and deleted docs/workspaces-beta/.
This updates the three docs still describing the old model so they match the
new stores model, fixing the vocabulary-sweep test and dead links:

- glossary.md: Workspace/Link/Context store/Initiative -> Store/Reference/
  Working context/Workset; link to stores-beta/user-guide.md
- README.md: replace deleted workspaces-beta/* links with the Stores User
  Guide and Agent Contract
- existing-projects.md: reframe the multi-repo section as stores; drop the
  dead concepts.md#coordination-workspaces anchor

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: TabishB <tabishbidiwale@gmail.com>
Co-authored-by: Tabish Bidiwale <30385142+TabishB@users.noreply.github.com>
2026-06-24 06:52:59 +00:00
Tabish Bidiwale 41ceebe2d8 fix(ci+installers): harden permission checks and guard completion/profile writes (#1247)
* fix: harden permission checks in root CI

* fix: close permission guard review gaps

* test: address coderabbit installer comments
2026-06-24 06:18:54 +00:00
Tabish Bidiwale a0decbe3fa feat(stores)!: replace workspaces and initiatives with stores (#1190)
* Implement context store root parity

* Clarify simplified model roadmap

* Add roadmap progress checklists

* Number roadmap work items

* Add --store root selection for normal commands

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.

* Fix stream-purity and message bugs found in review

- 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.

* Validate all rebuilt specs before writing any

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.

* Mark beta context-store and workspace docs as transition history

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.

* Record store-root-selection slice artifacts and roadmap progress

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.

* Record store-lifecycle-proof slice artifacts and roadmap progress

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.

* Prove the standalone store lifecycle end to end

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.

* Fix review findings in the store lifecycle slice

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.

* Keep validate and show hints inside the selected store

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.

* Derive setup's commit from the store shape and extract Git mechanics

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.

* Point the roadmap's next-item marker at slice 1.4

* Restructure the roadmap around root relationships

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.

* Lock the naming, Phase 3, and Phase 5 decisions

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.

* Add the roadmap loop runbook

* Make the roadmap loop fully autonomous with layered reviews

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.

* Add the loop's parallelism policy

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.

* Switch the roadmap run driver from /loop to /goal

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.

* Add the final acceptance capstone and standing quality bars

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.

* Bake the /goal invocation into the runbook header

* Write and review the store-rename-and-guidance slice spec

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.

* Write and review the store-rename-and-guidance plan

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.

* Rename the context-store surface to store

Mechanical, total token rename per the slice spec: command group
(context-store -> store, subcommands unchanged), 45 diagnostic codes,
dotted context_store.* targets, JSON keys (context_store/context_stores
-> store/stores everywhere, legacy groups included), the machine-local
data dir (context-stores/ -> stores/), internal modules and symbols
(src/core/context-store -> src/core/store, ContextStore* -> Store*),
and every help/error/hint string. Committed store-repo formats are
untouched (.openspec-store/store.yaml, registry.yaml). The dead
getDefaultContextStoreRoot export is deleted; its negative path
assertion is kept inline. The --store flag description now carries the
locked definition, identical in Commander and completions metadata.

Full suite green (94 files, 1730 tests).

* Land the two store-rename riders

Rider 1: workspace open loses its legacy --store/--store-path initiative
selectors (the second live meaning of --store). The unreachable guard
branch and its workspace_open_store_without_initiative diagnostic are
deleted; --initiative keeps resolving through the cross-store scan, the
qualified <store>/<id> form, and the interactive picker; persisted
path-bound views still reopen and doctor (tests now write the view-state
fixture directly). Selector-advertising fix texts in initiative
resolution name only surviving forms.

Rider 2: the store group owns its unknown-subcommand path - the error
names the real subcommands (including ls) and points lifecycle-shaped
mistakes at the normal command with --store, same stderr text for human
and --json runs, exit 1. New tests cover the hint, the no-alias
negative, and the --help listing.

Full suite green (94 files, 1735 tests).

* Regenerate guidance around stores

Templates: every generated workflow skill (and its opsx command twin)
now carries a shared store-selection block - discover ids with
'openspec store list --json', carry --store <id> on every command,
hints keep the flag. The three out-of-guard workspace-planning prose
mentions reword to schema language; the five live workspace guards are
untouched. Parity hash tables updated deliberately and the test now
asserts the store teaching in all generated skills.

Docs accuracy pass: docs/cli.md store section renamed with the locked
vocabulary, removed workspace-open selector rows and example, stale
XDG-default setup text corrected; docs/concepts.md token renames;
workspaces-beta docs renamed plus correctness fixes (--path in setup
examples, current prompt-flow prose). Every documented invocation
smoke-ran against the built binary. The workspace and initiative group
one-liners are labeled legacy beta in Commander and completions.

Note: the .codex/skills/use-openspec guidance was also rewritten around
store discovery (beta reference deleted), but that directory is
git-ignored (the L8 ignored-local-skill), so those edits live on disk
only and cannot appear in this commit.

Full suite green (94 files, 1736 tests).

* Record the git-ignored .codex discovery in the slice artifacts

* Guard the rename with sweeps, format pins, and the dogfood proof

New tests: a vocabulary sweep over src/, test/, docs/, scripts/ (and
.codex/ when present) that fails on any reintroduction of the retired
tokens; committed-format pins (.openspec-store/store.yaml literals, the
stores/ data dir, pre-rename store registration); old-data-dir negative
fixtures (valid and corrupt old registries are ignored, never read or
migrated); a --store description exact-equality walk across every
lifecycle command; and a store:setup telemetry-path assertion.

Dogfood proof committed as dogfood-transcript.md: a fresh headless agent
session, one plain prompt naming the team store in words, discovered the
registered store via --help and store list and created the change with
--store - six tool calls, zero initiative/workspace invocations, local
root untouched.

Full suite green (95 files, 1742 tests).

* Fix the post-implementation review findings

Three parallel review mechanisms (spec-compliance agent: compliant with
findings; /code-review high: 10 verified findings; codex CLI: approve
with fixes) converged on two P2s and a set of cheap P3s, all fixed:

- The store group's unknown-subcommand hint no longer emits invalid
  suggestions: 'store new <id>' without 'change' falls back to the full
  form, flag-interleaved operands (which Commander cannot attribute)
  use the generic example, the lifecycle-redirect set derives from
  COMMAND_REGISTRY, and the subcommand list derives from the live
  Commander group instead of a hardcoded string.
- Store-selection guidance names the seven commands that accept --store
  instead of claiming every command does, and is removed from the
  feedback workflow (whose only command rejects the flag); presence
  coverage extended to all 11 opsx command templates; hash tables
  re-pinned.
- Pasteable hints: 'Run store unregister' fix texts now name
  'openspec store unregister <id>'; the empty-list setup hint carries
  the mandatory --path.
- STORE_OPTION_DESCRIPTION now imports the completions description
  instead of duplicating it; the path-bound view fixture persists
  through the production writeWorkspaceViewState; the pre-rename
  register test writes old-format bytes inline; the vocabulary sweep
  file carries no retired tokens and no longer self-exempts.

Full suite green (95 files, 1745 tests).

* Apply the simplify-pass cleanups

Test guards now iterate the production registries: store-selection
presence checks run over getSkillTemplates()/getCommandContents() (new
workflows are covered automatically) and assert full-constant
containment; the --store description walk pins the exact seven command
names and ties each to the guidance prose, so a stale taught surface
fails tests. The store group one-liner derives from the completions
registry entry; the command:* flag predicate is derived, not restated;
retired-token constants are hoisted once per file; a redundant
assertion and a dynamic import are gone.

Skipped deliberately: the sweep's hand-rolled walker (measured ~48ms,
works), a cross-file retired-token helper (two files only), and
pre-existing duplications on surfaces the next slices delete.

Full suite green (95 files, 1745 tests).

* Tick slice 1.4 in the roadmap and point at the deletion slice

* Write and review the delete-legacy-command-groups slice spec

Both parallel adversarial reviews rejected the first draft on verified
grounds and every finding is folded: the config command's
workspace-profile integration (which executes a dead command) is in
scope; binding.ts stays because the planning-home carve-out depends on
it through workspace/foundation.ts; a dead-export carve-out ledger owned
by 4.1 is specified; concepts.md loses its whole Coordination Workspaces
section; the surviving 'Use initiatives' constraint rewords to read-only
compatibility language. The locked 5.1 'opening machinery' wording is
narrowed (recorded as a reviewable autonomous decision): the state model
and workspace-planning mode die in 4.1; zero-consumer opening helpers
die with the command groups.

* Write and review the delete-legacy-command-groups plan

Five deletion waves with grep-before-delete discipline. Both parallel
plan reviews folded: the planning-home mode pin (nothing asserts
actionContext.mode today) and the docs pointer grep gate are new
explicit steps; docs/cli.md dead-command references outside the cited
ranges are mapped (agent-table rows, Stores summary cell, config
section); the config.ts map gained the interface and core-preset call
sites with full test ranges; the parity test's initiative carve-out
removal is a named fourth partial edit; the spec's byte-stable clause
now permits the new removal-coverage tests.

* Delete the workspace and initiative command groups

The legacy beta command groups stop existing, and everything only they
consumed goes with them: the command layer (workspace.ts, initiative.ts,
the 11-file workspace/ command dir), the orphaned core (workspace
registry/openers/open-surface/skills/link-input and the whole
collections tree), the completions entries, the config command's
workspace-profile integration (which executed a dead command), the
update command's workspace detection, the docs that documented nothing
else (cli.md sections, concepts.md Coordination Workspaces,
docs/workspaces-beta/), and the tests of all of it.

Kept deliberately: planning-home and its state model (foundation,
state-io, legacy-state, store binding types - 4.1 owns their end),
legacy initiative metadata display, the --initiative rejection, and
every byte of user data. The 'Use initiatives' constraint rewords to
read-only compatibility language.

Ground truth recorded: workspace-planning mode has been CLI-unreachable
since slice 1.2's resolver demotion (toPlanningHome hardcodes repo
kind); the spec scenario was corrected to pin the byte-stable repo-local
behavior plus the library contract.

New removal-coverage tests (7) pin unknown-command rejection, help
cleanliness, update fall-through, user-data byte-identity, legacy
display, and the library contract. deletion-ledger.md records the 41
removed diagnostic codes and the dead-export carve-outs owned by 4.1.

Full suite green (85 files, 1614 tests). Pointer grep gate clean.

* Fix the deletion-slice review findings

Three parallel review mechanisms (spec-compliance: compliant with
findings, no P1; /code-review high: surgery residue and test-robustness
items; codex CLI: three P3s) converged on a small list, all applied:
the dead hasRepoLocalOpenSpecProject helper and its orphaned import are
deleted; the maybeWarnConfigDrift pass-through wrapper is collapsed and
its stale awaits dropped; the byte-identity test asserts the update
spawn's exit code and snapshots directories (not just files) so empty
subdirectory deletions cannot pass; the frozen-legacy-bytes fixture is
documented as deliberate; the project-apply accept path regained
coverage (lost with the deleted workspace tests); a sweep test pins the
ledger's surviving-token claim so workspace/initiative token regrowth
fails fast; the ledger records the state-io dead-export carve-outs, the
EACCES error-fidelity collateral, and the L2 pointer for the accepted
spec library that still describes deleted behavior.

Full suite green (85 files, 1616 tests).

* Apply the deletion-slice simplify pass and tick the roadmap

Simplify: the redundant hand-written store.yaml fixtures are gone
(registerStore writes identical metadata), the update action lost its
vestigial path.resolve scaffolding, and the sweep's four token spellings
collapsed to one concatenation-built regex. Skipped deliberately:
cross-suite snapshot helper extraction, state-io trimming, and barrel
removal - none pay for themselves before 4.1 deletes that code.

Roadmap: Phase 5 first tranche recorded (-12,903 net lines, ledger,
~25 fewer modules per CLI invocation), the workspace-planning
CLI-unreachability ground truth logged as a reviewable decision, and
the pointer moved to 3.1.

Full suite green (85 files, 1616 tests).

* Write and review the store-references slice spec (3.1)

Two adversarial rounds folded. The subagent's P1s were both grounding
failures: parseSpec() throws on imperfect upstream specs, so the index
extracts summaries tolerantly; and apply instructions have a real human
surface, so the index lives in both surfaces and both modes. Codex
added the async command-boundary assembly (the sync generators receive
the index as input), the 50KB shared budget with order-preserving
truncation, and registry-corruption degradation. Five warning codes
degrade instructions instead of failing them; references parse raw and
validate in the assembler; the index is one level deep by rule.

* Write and review the store-references plan (3.1)

Two checkpoints (config + assembler core; instruction surfaces + docs).
Both plan reviews approved with fixes, all folded: pure renderers live
in core beside the assembler so the 50KB budget measures real output
(truncation stops before the cap, warning line exempt); the
inspectRegisteredStore extraction is pinned narrow - metadata/health
stages only, registry lookup stays in resolveStoreRoot and its seven
error codes stay byte-identical; config is read once at the command
boundary and suppresses the generator's internal read; the Purpose-line
scanner is self-contained; the test matrix gained symmetric --store,
boundary byte-identity, no-recursion, nothing-frozen, and not-inlined
assertions.

* Add the references config field and the index assembler core

openspec/config.yaml gains references: (raw strings kept, deduplicated,
order-preserving; grammar validation is the assembler's job so bad ids
surface as diagnostics). New src/core/references.ts assembles the
referenced-store index: one registry read per call, the narrow
inspectRegisteredStore extraction shared with resolveStoreRoot (whose
seven error codes stay byte-identical, pinned by the existing
root-selection tests), tolerant first-Purpose-line summaries, five
warning diagnostic codes, self-reference omission by id and path, and
the 50KB budget with order-preserving truncation measured by the pure
renderers that the command layer will print.

Full suite green (86 files, 1630 tests).

* Wire the referenced-store index into both instruction surfaces

The command layer reads the resolved root's config once (suppressing
the generator's internal read), assembles the index, and threads it
into generateInstructions and generateApplyInstructions. Artifact human
mode prints the <referenced_stores> XML block after project context;
apply human mode prints a '### Referenced Stores' markdown section.
JSON gains an additive references field, omitted when none are
declared. docs/cli.md gains the 'Referencing stores from a project'
subsection.

Seven new surface tests pin: both surfaces both modes, live (unfrozen)
summaries, field omission, symmetric --store declarations, the
one-level rule, non-instruction byte-identity with the store untouched,
and the full PM-to-dev layered flow including the verbatim fetch.

Full suite green (87 files, 1637 tests).

* Fix the 3.1 review findings

Three review mechanisms converged on six real issues, all fixed with
regression tests: extractFirstPurposeLine is fence-aware and accepts
CommonMark closing hashes; an index emptied by self-reference omission
now omits the JSON field (omitted-not-empty contract); truncation
renders its message as a Note line instead of an orphan fix; the budget
measures the real rendering in UTF-8 bytes (problem entries and
diagnostics included; only the truncation warning exempt) with a
binary-search prefix; registry-independent checks (invalid id,
self-reference) run before the corrupt-registry branch; the assembler
catches inspection throws and degrades them; the resolveStoreRoot
switch is explicit (return fromStoreError) with an exhaustiveness
guard; generateApplyInstructions takes an options bag instead of a
fifth positional; the dead config-read catch is gone; spec files read
concurrently.

Full suite green (87 files, 1641 tests).

* Apply the 3.1 simplify pass and tick the roadmap

Simplify: the two new test suites share test/helpers/openspec-fixtures
(createOpenSpecRoot/writeSpec); the dead canonicalize wrapper is gone
(canonicalizeExistingPath never throws); the 50KB cap is single-sourced
from project-config's exported MAX_CONTEXT_SIZE; the registry-unreadable
state collapsed into one nullable variable; spread and JSDoc nits.
Skipped with reasoning: renderer branch merge, binary-search
replacement (measured: cap self-bounds the cost), cross-suite snapshot
consolidation, and the remaining ~1ms duplicate config read (the
project's own perf note rejects that trade).

Roadmap: 3.1 boxes ticked, changelog round recorded, pointer moved to
3.2. Full suite green (88 files, 1641 tests).

* Write and review the declared-store-fallback slice spec (3.2)

Both adversarial reviews converged on the same P1: the spec claimed
declared roots behave exactly like --store roots while its own UX
example printed a relative path, and the scope named only two of the
seven source-keyed consumers. The fix is one store-selected predicate
(storeId set) adopted everywhere. Also folded: init refuses to bury a
pointer under a scaffold; malformed pointers error
(invalid_store_pointer) instead of silently flipping the write target;
one-hop pointer resolution; warning-silent resolver config reads;
directory-typed shape stats; the true-prefix declaredOrigin mechanism;
and the recorded amendment relocating the both-shapes warning from the
nonexistent project doctor to resolution stderr.

* Write and review the declared-store-fallback plan (3.2)

Both plan reviews approved with fixes, folded: the eighth
source==='store' check (show.ts printNonInteractiveHint) joins the
predicate inventory with a recorded spec amendment; the init guard
anchors immediately after validate() so legacy cleanup and the
global-config migration write cannot precede the refusal; the
declaration-origin prefix is a call-site rewrap (codes preserved, fix
unprefixed) covering the fromStoreError pass-throughs; the targeted
config read is a shared exported helper; the test matrix covers all
five prefixed taxonomy codes, the malformed-pointer no-write
assertion, deterministic byte-identity, and positive config-only
assertions.

* Add the declared-store fallback to root resolution

A config-only openspec/ directory with a store: pointer now resolves
the declared store: the nearest-root arm classifies the found dir with
two directory stats, reads the pointer via the new warning-silent
readStorePointer helper (malformed pointers error with
invalid_store_pointer - never a silent local write), and resolves
through the shared resolveStoreRoot pipeline with source 'declared'
and a declaration-origin rewrap (codes and fixes untouched). A real
root with a pointer warns once on stderr and stays nearest - fallback
never override. The new isStoreSelectedRoot predicate (storeId set)
replaces all eight source==='store' checks so declared roots get
identical cross-root behavior: banner, --store hints, absolute paths,
suppressed noun-form suggestions.

Nine new resolver tests cover the pointer, precedence, the both-shapes
warning, malformed pointers, all five prefixed taxonomy codes, one-hop
resolution, and .yml origins.

Full suite green (88 files, 1650 tests).

* Add the init pointer guard, externalized-planning e2e, and docs

openspec init now refuses to scaffold a config-only pointer directory,
anchored immediately after validate() so the refusal precedes legacy
cleanup, migration writes, and prompts - the test pins that nothing
changes on disk and that removing the store: line converts cleanly.
The e2e journey runs the full lifecycle (new change through archive)
in a pointer repo without --store anywhere: work lands in the store,
the pointer repo stays byte-identical, the banner and JSON root block
report declared, nextSteps hints carry --store, and the 3.1 references
composition surfaces the store's own upstream index. docs/cli.md gains
the 'Declaring a default store' subsection.

Full suite green (89 files, 1654 tests).

* Fix the 3.2 review findings

Three review mechanisms converged; all real findings fixed with
regression tests: empty or comments-only configs in config-only dirs
are plain roots again (the documented comment-out conversion path no
longer strands every command behind invalid_store_pointer; non-mapping
scalars carry no pointer); the malformed reason splits into
unparseable vs non-string with accurate messages and fixes; the init
guard now refuses malformed pointers too and walks ancestors so a
pointer-repo subdirectory cannot grow a nested root that silently
diverts work; resolver and init share one classifyOpenSpecDir (the
classification can never diverge); readProjectConfig and
readStorePointer share one .yaml/.yml probe; the fourth copy of the
snapshot test helper is consolidated into test/helpers/fs-snapshot.ts;
the resolver header documents invalid_store_pointer; the
absolute-path warning wording is recorded as a spec amendment.

Full suite green (89 files, 1656 tests).

* Apply the 3.2 simplify pass and tick the roadmap

Simplify: isStoreSelectedRoot is a type guard (three redundant
conjuncts gone); the malformed-pointer reason strings single-source
through storePointerProblem in project-config (init's copies were
unpinned and could drift); the init guard drops its ternary for the
walk that finds projectPath in extend mode anyway. Skipped with
reasoning: directoryExistsSync consolidation (four pre-existing private
copies, out of slice), the warnings-array altitude (3.6 owns the
structured surface), the classification's module home (revisit when
3.6 consumes it).

Roadmap: 3.2 boxes ticked, changelog round recorded (including the
detached-HEAD process note), pointer moved to 3.3.
Full suite green (89 files, 1656 tests).

* Write and review the store-canonical-remote slice spec (3.3)

Two adversarial reviews converged on the contract holes, all folded:
the setup-rerun origin-erasure P1 (probe in both flows so
storeBackendsMatch stays consistent and the 1.3 rerun no-op survives);
register's write contract stated precisely (never commits, never
modifies an existing store.yaml; conversion identity stays
remote-free); the one-way strict-schema compatibility recorded as a
standing constraint for 3.4; mixed references dedup semantics
(normalize, dedup by id, first remote wins); verbatim-pasteable clone
fixes via ~/openspec/<id>; setup --remote refuses to be silently
ignored; the doctor example redrawn from the real layout; the
no-network clause pinned testably.

* Write and review the store-canonical-remote plan (3.3)

Both plan reviews approved with fixes, folded: clone fixes render
absolute home paths (tilde never expands outside a shell; agent JSON
consumers execute argv directly) with the spec amended to match;
setup's origin probe reaches both backend-resolution sites so reruns
cannot re-introduce the erasure P1, and stays out of
resolveGitStoreBackendConfig's hot read paths; the sharing-guidance
plumbing is concrete (StoreMutationResult carries canonical/observed,
JSON drops them, printMutationHuman renders the preference chain); the
setup-JSON contradiction resolved for the unchanged StoreOutput shape;
getOriginUrl trims; the --remote-vs-existing refusal fires in
prepareStoreSetup before any prompt or write; fill-if-absent dedup
pinned; registry anchors and test filenames corrected; TEST-NET
fixtures via git remote add.

* Record canonical and observed store remotes (3.3 checkpoint 1)

store.yaml gains an optional remote (strict schema retained; pre-3.3
files parse; unknown keys and empty remotes still fail). setup --remote
writes it before the initial commit, fails on empty values before
creating anything, and refuses with the hand-edit fix when store.yaml
already exists - silent flag acceptance is the forbidden outcome. Both
setup backend-resolution sites and register probe the local git origin
(gitOriginUrl, config read only) into the machine-local registry entry,
so reruns stay no-ops that preserve the record and re-register
refreshes it; conversion-created identity stays {version, id}. Doctor
surfaces metadata.remote and git.origin_url, with one human Remote line
preferring canonical. Sharing guidance names the canonical remote, then
the observed origin, then keeps today's wording - threaded through
StoreMutationResult.remotes and dropped from JSON.

15 new tests; three additive pins updated (doctor git shape x2, the
completions flag registry friction pin).

Full suite green (90 files, 1671 tests).

* Carry clone sources in reference declarations (3.3 checkpoint 2)

references: entries now accept {id, remote} maps alongside plain ids,
normalized to ReferenceDeclaration[] (dedup by id keeps the first
position; the first remote seen fills a missing one, never overrides).
The unresolved-reference fix becomes a verbatim-pasteable
git clone <remote> <home>/openspec/<id> && openspec store register ...
- absolute home path because tilde never expands outside a shell and
agent JSON consumers execute argv directly. An invalid id still wins
over any declared remote. The e2e onboarding journey executes the
printed fix verbatim (scratch HOME, local-path remote, split on the
shell &&) and continues to a resolved index - including the clone-trap
lesson that the origin must track anchor files. docs/cli.md documents
--remote, the store.yaml field, and the reference-with-remote form.

Full suite green (90 files, 1674 tests).

* Fix the 3.3 review findings

Three review mechanisms converged; all real findings fixed with
regression tests: register (and both setup sites) no longer probe the
origin of a non-repo store folder nested inside another repository -
git -C walks up, so the enclosing repo's origin could be durably
recorded and printed as sharing guidance (the shared
resolveBackendWithObservedOrigin helper guards with an at-root check
and deduplicates the triplicated probe block); the clone fix quotes
the checkout path, separates the remote with --, and renders only
shell-inert remotes (a config-committed --upload-pack or
metacharacter-bearing remote falls back to the teammate wording -
agents execute these fixes verbatim); setupPreparedStore re-asserts
the hand-edit refusal so metadata materializing between prepare and
execute cannot silently swallow --remote; a same-checkout origin
backfill now reports already_registered: true while still refreshing
the entry (the 1.3 rerun-reporting contract); the references warnings
distinguish dropped entries from dropped remotes; the dead zod union
for references is gone (the manual parser is the documented single
source); foundation's duplicate empty-remote message names its layer.

New pins: setup-rerun remote preservation, origin-backfill reporting,
the nested-repo guard, and the shell-safety gate.

Full suite green (90 files, 1678 tests).

* Apply the 3.3 simplify pass and tick the roadmap

Simplify: the duplicated store_remote_requires_hand_edit throw is one
factory (the TOCTOU re-assert can no longer drift from the prepare
guard); commitStoreRegistration restructures around a normalized
sameCheckout predicate - three near-identical returns become one, and
a symlinked-path remote refresh no longer misreports as a fresh
registration. Skipped with reasoning: the test fixture consolidation
(near the option ceiling), the checkout-location prose/computed split
and the ext:: transport hardening (both recorded as capstone notes),
doctor divergence display (spec-locked quiet form).

Roadmap: 3.3 boxes ticked, changelog round recorded, pointer moved to
3.4. Full suite green (90 files, 1678 tests).

* Write and review the store-targets slice spec (3.4)

Both adversarial reviews approved with fixes, folded: the apply
surface's indirect metadata flow (assembly runs inside
generateApplyInstructions with store targets passed through the
options bag); empty narrowing treated as undeclared; status always in
the JSON shape so agents see degradation; remote inheritance under
narrowing; the change-level grammar cliff owned explicitly;
KebabIdentifierSchema as the named validator with a neutral shared
kebab predicate replacing store-flavored naming; declared-root
sessions and the inert pointer-dir wrong turn covered.

* Write and review the store-targets plan (3.4)

Both plan reviews approved with fixes, folded: the artifact human
rendering anchored to printInstructionsText (instruction-loader
renders nothing); the unknown-store and root-resolution pins added;
validateStoreId delegates to the neutral isKebabId so one kebab regex
remains; the label-factory call corrected; the apply options bag
carries the resolved config path for fix text; inline expected strings
replace snapshot wording; the e2e gains a second non-narrowed change.

* Add the targets declaration layer (3.4 checkpoint 1)

One shared declaration-list parser now backs both references: and the
new targets: config field (identical normalization, dedup, and split
warnings - the 3.1/3.3 references pins stay green untouched).
ChangeMetadataSchema gains targets as kebab-validated ordinary
metadata, and the kebab grammar finally has one source of truth: the
exported isKebabId in change-metadata/schema, which validateStoreId
now delegates to. The pure src/core/targets.ts assembles the effective
set (change narrowing replaces the store list with remote inheritance
by id join; empty narrowing means undeclared; target_invalid_id and
target_not_declared degradation) and renders the XML block and
markdown section with pinned provenance wording.

Full suite green (91 files, 1690 tests).

* Surface effective targets in instructions (3.4 checkpoint 2)

Both instruction surfaces in both modes now carry the effective target
set: the artifact path assembles in instructionsCommand (change
context and config both in hand) and threads through
GenerateInstructionsOptions; the apply path passes storeTargets and
the resolved config path through the options bag and assembles inside
generateApplyInstructions where the change metadata loads. JSON gets
{source, repos, status} omitted-when-none; human output renders the
target_repos XML block and the Target Repos markdown section after the
referenced-stores blocks. Six surface tests cover provenance on both
surfaces, narrowing with remote inheritance beside a non-narrowed
sibling change, vocabulary warnings in JSON and human at exit 0,
omitted-when-none, pointer sessions reading the resolved root (the
pointer dir's own targets are inert), the unknown-store pin for target
ids, and non-instruction byte-identity. docs/cli.md documents the
declaration and the targets-vs-affected_areas split.

Full suite green (92 files, 1696 tests).

* Fix the 3.4 review findings

Three review mechanisms converged on polish-level findings (no P1/P2),
all folded: change-level target duplicates dedup to a set (first
occurrence wins); the non-array config warning names repo ids for
targets instead of borrowing the references noun; both instruction
surfaces now share ONE wiring shape - the artifact path passes raw
storeTargets/storeConfigPath like apply and assembly happens inside
the generator where change metadata lives (the silently-degrading
asymmetry a second caller would have tripped on); the shared
declaration type is renamed DeclarationEntry (it backs repos and
stores alike) with the stale references-only comment gone; the dead
KEBAB_ID_REGEX export is private again; METADATA_FILENAME is exported
and reused instead of two string literals; the spec's severity-cliff
wording amended to the real blast radius (instructions/status read
metadata; show/validate/archive never did). Recorded for later: the
workspace kebab-regex copy dies with 4.1; the all-invalid-store-ids
empty-repos render is distinguishable by status and stays.

Full suite green (92 files, 1696 tests).

* Apply the 3.4 simplify pass and tick the roadmap

Simplify: the conditional spreads at both command boundaries collapse
to plain optional fields (internal options, not JSON output); the
loader falls back to the self-read config's targets so library callers
omitting the option agree with the CLI wiring; cosmetic blank-line and
spec-wrap leftovers fixed. Skipped with reasoning: a shared id.ts home
for the kebab grammar (3.5's natural move), the references barrel
export note and parseJson consolidation (capstone), import-statement
merges (trivia).

Roadmap: 3.4 boxes ticked, changelog round recorded, pointer moved to
3.5. Full suite green (92 files, 1696 tests).

* Write and review the repo-map slice spec (3.5)

Both adversarial reviews approved with fixes, folded. The P1: the four
registry state-rebuild sites would silently erase the new repos:
section on the next store write - preservation is a pinned scenario
naming the sites. Also folded: repo-check precedence over both
unknown-store branches with a non-looping zero-stores fix; path AND id
cross-section uniqueness with four claimant codes; invalid_repo_id
wording with the --id hint for default folder names; the kebab
predicate's neutral id.ts home; pinned JSON contracts; the honest
one-additional-read wiring; TargetRepoEntry; the recorded Unicode
arrow and corrupt-registry silence decisions.

* Write and review the repo-map plan (3.5)

Both plan reviews approved with fixes, folded: the cross-section check
lives inside assertNoRegisteredStoreConflict (four call sites incl.
three operations preflights - hooking only the write helper would let
setup scaffold files before failing, so an early-reject pin is
planned); getRepoPath reconciled as a dumb id lookup whose 3.5 caller
is repo unregister while the enrichment uses listRepoEntries on its
own read; six missing test mappings added (store list/doctor with both
sections, empty-list verbatim, repo_not_found, mixed-registry positive
resolution, directory-untouched unregister, both-surface enrichment);
two code-map anchors corrected.

* Add typed registry sections and the repo map core (3.5 checkpoint 1)

The machine-local registry gains an optional strict repos: section
beside stores:, carried through parse, serialize, and both store write
helpers (the preservation matrix is pinned - a schema-only change
would have silently erased every repo mapping on the next store
write). Cross-section uniqueness for ids AND paths lives inside
assertNoRegisteredStoreConflict (covering the three operations
preflights) and the new assertNoRegisteredRepoConflict, with the four
claimant codes plus in-section repo_id_conflict/repo_path_conflict.
registerRepo/unregisterRepo/listRepoEntries/getRepoPath form the core
API (rerun no-op, repo_not_found, corrupt-registry null). The kebab
grammar moves to its neutral src/core/id.ts home; change-metadata
re-exports, store foundation and targets consume it, and registry key
validation produces label-accurate wording.

Full suite green (93 files, 1705 tests).

* Add the repo command group, typed rejection, and path enrichment (3.5 checkpoint 2)

openspec repo register/unregister/list manage the machine-local repo
map with the pinned JSON contracts (folder-name default ids with the
--id fix when grammar fails; repo_path_missing/not_directory;
repo_not_found; rerun no-op; unregister never touches the checkout).
--store with a registered repo id now rejects with store_id_is_repo
before BOTH unknown-store branches - including zero-stores, whose fix
suggests a different id instead of looping into the cross-section
conflict - and propagates through the 3.2 pointer with the Declared-in
prefix. Effective-target entries gain a local path when the repo map
resolves them (TargetRepoEntry; arrow and combined renders; one
additional registry read in loadRootConfigContext; corrupt registry
yields bare entries silently). Completions registry, friction pins,
and docs updated; store setup with a repo-claimed id is pinned to
create nothing.

Full suite green (94 files, 1714 tests).

* Fix the 3.5 review findings

Three review mechanisms converged; all fixed with regression tests:
the library API enforces its own invariants (registerRepo validates
path-then-id with typed repo_path_missing/not_directory and
invalid_repo_id errors; unregisterRepo validates ids - a 4.1 caller
gets input errors, not serialize-time registry-corruption noise; the
command rewraps default-folder-name grammar failures with the --id
fix); no-op reruns never take the write lock or rewrite the registry
file (mtime/format churn pinned away); the stale getRepoPath pre-read
in unregister is gone (the locked removal is authoritative); the repo
map is read unconditionally so change-only targets enrich too; a
hand-edited registry with one id in both sections now fails clearly at
parse time instead of resolving ambiguously; store_id_is_repo embeds
its action in the message (human wrappers print message only - the
recorded family precedent); the register/unregister JSON shapes split
into total types; the docs Repo map heading no longer re-parents the
default-store subsection.

getRepoPath stays exported as recorded 4.1 groundwork (unit-tested,
no production caller yet - the 3.3 persisted-remote precedent).

Full suite green (94 files, 1718 tests).

* Apply the 3.5 simplify pass and tick the roadmap

Simplify: the third copy of the JSON/failure plumbing collapses into
commands/shared-output (one definition of the failure contract, used
by store and repo); the same-mapping predicate is hoisted in
registerRepo; the kebab grammar wording single-sources through
KEBAB_ID_DESCRIPTION; an unused test import and two docs nits fixed.
Skipped with reasoning: the registry-state builder quadruplication
(settled mirror territory), validator placement, the unconditional
registry read (measure-by-reasoning verdict: the only correct gate
needs data that arrives after the read on the apply path).

Roadmap: 3.5 boxes ticked, changelog round recorded, pointer moved to
3.6. Full suite green (94 files, 1718 tests).

* Write and review the relationship-health slice spec (3.6)

Both adversarial reviews approved with fixes (two P1s each,
converging), all folded: the exit-code rule now mirrors store
doctor's REAL contract (health findings exit 0; the draft cited a
nonexistent errors-exit-1 behavior); the JSON shape gains the lock's
separate store-metadata section and the 3.4-recorded inert-pointer
deferral lands as pointer_declarations_inert; a real
includeSpecs:false assembler mode replaces the strip-after hedge; the
assembler accepts a pre-read registry so one read feeds everything;
target_unmapped suppressed under unreadable registries;
grammar-invalid targets synthesize bare entries; the both-shapes
detection mechanism and stderr duplication recorded; the
STORE_SELECTION_GUIDANCE consequence scoped; missing scenarios added.

* Write and review the relationship-health plan (3.6)

Both plan reviews converged on three P1-grade holes, all folded: the
registry-injection option inverted the established null semantics (a
fresh machine with no registry file would have been marked unreadable
- the option is now registryEntries with [] = empty and null =
unreadable, mirroring the assembler's post-read variable);
resolveRootForCommand needs an additive allowImplicitRoot
pass-through (it forwards only store/storePath today); and the
invalid-target synthesis would have required parsing ids out of
message strings (the inspector receives raw declarations and uses
isKebabId). Plus: the inert-pointer re-walk named (the declared root
is the store; findRepoPlanningRootSync(cwd) finds the pointer dir);
the human-rendering contradiction resolved in favor of the spec
transcript; truncation-never and pass-through pins mapped; the dead
status key dropped from the failure payload.

* Add the health-mode assembler options and the relationship inspector (3.6 checkpoint 1)

assembleReferenceIndex gains includeSpecs:false (skipping the
spec-file reads AND the byte budget - health entries carry no
specs/fetch keys and the content-only truncation diagnostic can never
appear) and registryEntries injection with the [] -vs- null semantics
that mirror the assembler's own post-read variable (a naive raw-read
injection would mark every fresh machine unreadable). The pure
src/core/relationship-health.ts composes the doctor command's gathered
inputs into the lock's four separated categories, synthesizing
target_unmapped (suppressed under unreadable registries), structural
target_invalid_id entries from the raw declarations (never parsed from
messages), relationship_registry_unreadable, root_pointer_ignored,
pointer_declarations_inert, and the store_remote_divergence info note.

Full suite green (95 files, 1727 tests).

* Add openspec doctor (3.6 checkpoint 2)

The root-scoped relationship-health command: resolves like every
normal command (with the new additive allowImplicitRoot pass-through
on resolveRootForCommand and the null-shape failure payload), gathers
with ONE registry read feeding references, targets, and the unreadable
signal coherently, detects the both-shapes and inert-pointer wrong
turns (the latter via the cwd re-walk, working from subdirectories),
reads store facts for explicit and declared store-backed roots, and
renders the three-heading transcript voice with (none declared)
sections and Fix lines. Health findings of any severity exit 0; only
command failures exit 1. STORE_SELECTION_GUIDANCE gains doctor and the
skill-template parity hashes update deliberately; completions and the
--store description pins extended. Eight e2e tests cover the full
matrix incl. empty-vs-unreadable registries, divergence info, and the
read-only snapshot.

Full suite green (96 files, 1735 tests).

* Fix the 3.6 review findings

Three review mechanisms converged; all fixed with regression tests:
human-mode command failures now print the taxonomy Error/Fix lines
instead of a raw stack trace (the action gained the sibling-standard
try/catch); stale repo mappings surface as target_path_missing (the
lock's 'target checkout health' now actually stats mapped paths);
self-reference-emptied reference lists render '(declared references
all resolve to this root)' instead of the false '(none declared)'; a
malformed store: pointer on a real root surfaces as
root_pointer_invalid (the resolver is silent there); the synthesized
target_invalid_id fix carries the real config path; the inspector
reuses toRootOutput; instructions' registry read now feeds the
reference assembler through the 3.6 injection point (no more torn
snapshots between repoPaths and the index); the human renderer's
duplicated section loops collapse into shared helpers; the spec's
exit-1 list gains the recorded corrupt-store.yaml amendment (store
resolution rejects before doctor runs - a doctor-only resolution path
would break the one-resolver invariant).

Full suite green (96 files, 1739 tests).

* Apply the 3.6 simplify pass and tick the roadmap - Phase 3 complete

Simplify: readRegistrySnapshot extracts the torn-snapshot invariant
into one place (doctor and instructions both consume it); doctor's
catch routes through emitFailure, fixing a --json inconsistency where
post-resolution failures printed human lines without a JSON payload;
shared asStatus duck-types the diagnostic envelope so
RootSelectionError fixes survive; the inspector reuses
storePointerProblem (the fifth phrase copy dies); the existsSync sweep
stats only declared targets; the dead toRootOutput import removed.
Skipped with reasoning: the warning-factory extraction (the fourth
copy does not fit the shape), the config-path-fallback micro-helper.

Roadmap: 3.6 boxes ticked, Phase 3 marked complete on the branch,
changelog round recorded, pointer moved to 4.1.
Full suite green (96 files, 1739 tests).

* Trim the review profile for Phase 5 deletion slices

* Write and review the assemble-working-context slice spec (4.1)

Both adversarial reviews approved with fixes, converging on the
deletion-grounding P1s: binding.ts dies whole (5.1 kept it only for
workspace/foundation's import - with workspace/ gone it would be
exactly the hidden-not-deleted state the criteria reject) and the five
workflow-template workspace-planning guards 5.1 deeded here join the
deletion list with their parity churn named. Also folded: the
change-status-policy cascade enumerated; the shared doctor/context
data gather made mandatory with context recorded as silent on wrong
turns; the member-mapping table pinned; code-workspace write semantics
pinned; getRepoPath deleted rather than re-hidden; fetchRecipe
exported; the naming paragraph recorded.

* Write and review the assemble-working-context plan (4.1)

Both plan reviews approved with fixes, folded: the spec's
code_workspace_exists diagnostic collides with the vocabulary sweep's
workspace_* ban - amended to context_file_exists; the parity test's
workspace-planning guard assertion flips to absence; the policy
tranche names ChangeStatus.affectedAreas and the artifact-graph barrel
re-export; doctor-extraction weakened to behavior-identical; the
unresolved-members-stderr e2e mapped; the sweep guardrail reworded
honestly; stale hedges resolved. Both reviewers verified the deletion
order dependency-safe and every anchor accurate.

* Delete the workspace opening machinery (4.1 checkpoint 1)

The absorbed 2.3, executed leaves-first: the ten workspace-planning
template guards (parity test flipped to a no-residue assertion); the
change-status-policy cascade (summarizeAffectedAreas,
AffectedAreasSummary, affectedAreas plumbing, workspaceName, the
workspace-planning mode member, the workspace next-steps, the
artifact-graph barrel re-export); planning-home collapsed to repo-only
(PlanningHomeKind = 'repo'; the workspace state read and
workspace-planning default schema die); src/core/workspace/ whole
(897 lines) with its barrel line and tests; store/binding.ts whole
(~300 lines - 5.1 kept it only for workspace/foundation's import)
with its barrel line and binding tests; getRepoPath (its recorded
consumers evaporated). The library pins that froze the carve-outs die
with the behavior; the six legacy-groups CLI-surface pins stay green
untouched. The deletion ledger marks the carve-outs executed and the
workspace_skills vocabulary-allowlist entry is pruned. No
.openspec-workspace reads remain anywhere in src.

Net: 27 files, -2,196 lines / +40.

Full suite green (94 files, 1706 tests).

* Add openspec context, the assembled working set (4.1 checkpoint 2)

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).

* Fix the 4.1 review findings

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).

* Apply the 4.1 simplify pass and tick the roadmap - Phase 4 complete

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).

* Execute the Phase 5 remainder - 5.1 fully closed

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).

* Capstone: all four persona journeys pass (6.1)

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).

* Capstone: usability audits done (6.1)

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.

* Fix the capstone usability-audit findings

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).

* Capstone: technical audits done (6.1)

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.

* Capstone: whole-delta gauntlet run - findings ledger (6.1)

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.

* Fix every gauntlet P1/P2 plus the cheap P3 set (6.1)

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).

* Capstone complete: gauntlet passed, release-readiness report committed (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.

* Fix the phantom-root regression test's environment dependence

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).

* Record the user-directed workset correction (post-capstone review)

* Record 4.2 personal worksets with FR1; supersede the change-anchored direction

* Record 4.2 FR2: tool opening with the two-style extensible opener pattern

* Flesh out 4.2 personal worksets as a full roadmap item with its goal run

* Renumber personal worksets to Phase 7 item 7.1

* Add the 7.1 capstone dogfood and branch-push steps to the goal run

* Add the 7.1 personal-worksets research checkpoint

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.

* Windows-compatibility pass per test/AGENTS.md

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).

* Make the clone-fix unit pin platform-aware

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.

* Write the 7.1 personal-worksets spec; fold the dual spec review

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.

* Write the 7.1 personal-worksets plan; fold the dual plan review

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.

* 7.1 CP1: worksets core, opener table, shared file-state mechanics

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).

* 7.1 CP2: the workset command group, registration, docs, and 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).

* Tick 7.1 implementation and tests boxes; record the implementation round

* 7.1 review round: fix all converged P2s from the three review mechanisms

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).

* 7.1 simplify pass: collapse the parallel mechanisms the reviews queued

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).

* 7.1 capstone dogfood passes; transcript committed, box ticked

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).

* Close 7.1: pushed-branch box ticked, glance and pointer finalized

* Fix the Linux-only CI failure in the workset launch-failure test

The fixture was a shebang-less text file: macOS posix_spawn rejects it
with ENOEXEC (the spawn error the test wants), but glibc execvp
retries ENOEXEC via /bin/sh, so on Linux the child runs and exits 127
instead of erroring. A shebang pointing at a missing interpreter fails
ENOENT on every POSIX libc with no shell fallback; a garbage
claude.exe covers the win32 matrix leg the same way. Verified in a
node:20 Linux container (old fixture reproduces exit 127; full workset
file passes with the fix) and on macOS (full suite, 1799 tests).

* Add the stores beta user guide

A problem-first guide for the new surface (stores, references,
targets, repo map, doctor, context, worksets) under docs/stores-beta/,
mirroring the old workspaces-beta layout. Built around two team
stories — one team sharing a planning repo, and requirements crossing
team lines — with every command output captured from a live walk of
the current build in isolated scratch state. Carries the beta notice
(shapes may change), the verified resolution-precedence table, known
limitations including the one-checkout-per-store-id rule and the
commands that stay cwd-based, and the real on-disk state locations.
Linked from the README, getting-started, and the cli.md stores
section, which gains the same beta note.

* Carry the beta note on the worksets section of the CLI reference

The note at the top of the Stores section names worksets but is
invisible to a reader deep-linking straight to Personal worksets.

* Fix store --json missing-subcommand output

* Disable CLI-agent workset openers by default

* Remove targets and repo map commands

* Update simplify-context docs after removing targets

* Harden store-root test isolation

* Remove generated review HTML artifacts

* Refresh PR cleanup evidence
2026-06-23 16:53:23 +00:00
openspec-release-bot[bot]andgithub-actions[bot] 1b06fddd59 Version Packages (#1166)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-03 09:31:40 +00:00
Tabish Bidiwale 0a01146c18 [codex] Fix workspace.yaml collision detection (#1165)
* Fix workspace.yaml collision detection

* Store workspace view state under metadata

* Keep top-level update out of workspace updates

* Remove unused workspace root selector

* Allow repo updates below workspace roots

* Propagate repo state probe errors

* Generalize workspace yaml collision coverage
2026-06-03 09:19:54 +00:00
openspec-release-bot[bot]andgithub-actions[bot] bc7ab26650 Version Packages (#1023)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-01 21:23:33 +00:00
Tabish Bidiwale aa16080d16 Add changeset for Mistral Vibe support and validator/completion fixes (#1154) 2026-06-01 21:14:14 +00:00
Tabish Bidiwale 055957fbca clarify changeset release tracking (#1148) 2026-06-01 05:11:50 +00:00
Tabish BidiwaleandAlfred 9e78bcaa80 [codex] Document cross-platform path assertions (#1116)
* docs: document cross-platform path assertions

* docs: mention toPosixPath in path assertion guidance

* chore: remove changeset

---------

Co-authored-by: Alfred <alfred@Alfreds-Mac-mini.local>
2026-06-01 05:05:20 +00:00
e36463074d [codex] Add Mistral Vibe support with CI fix (#1144)
* feat: add mistral vibe support

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>

* feat: add mistral vibe support

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>

* chore: archive add-mistral-vibe-support change

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>

* chore: sync delta specs from add-mistral-vibe-support change

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>

* chore: fix archive directory date to match metadata

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>

* fix: correct vibe detection paths and alphabetical ordering

- Remove detectionPaths from Mistral Vibe to prevent double-nested skills dir
- Fix lingma alphabetical position in tool IDs list

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>

* chore: remove archived mistral vibe change files

Remove archive directory per PR review feedback to keep PR minimal

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>

* chore: remove mistral vibe spec files per PR feedback

Remove new spec corpus (vibe-tool-config + Mistral Vibe scenario in ai-tool-paths)

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>

* test: add Mistral Vibe detection regression test

Add focused regression test that proves Vibe initializes and detects
skills under .vibe/skills so the path semantics do not drift.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>

* test: tolerate workspace update help wrapping

---------

Co-authored-by: Thomas Betous <4435536+tbetous@users.noreply.github.com>
Co-authored-by: Mistral Vibe <vibe@mistral.ai>
Co-authored-by: tbetous <thomas.betous@doctolib.com>
2026-05-31 14:35:52 +00:00
9aded17af7 fix(validator): hint when SHALL/MUST appears only in requirement header (#1135)
When a change delta has a requirement whose body is missing SHALL/MUST but
whose header (the text after `### Requirement:`) already contains the
keyword, the validator emitted the generic error "must contain SHALL or
MUST". Authors then re-read the spec, see SHALL right there in the header,
and have no idea what the validator wants.

Per the OpenSpec conventions the keyword has to live on the requirement
body line (the line immediately after the header). When the keyword is
present in the header only, append guidance explaining exactly where to
move it. The fix is scoped to the two `validateChangeDeltaSpecs` call
sites (ADDED + MODIFIED) so behaviour for requirements that lack the
keyword everywhere stays unchanged.

Adds three vitest cases under `test/core/validation.test.ts`:
- ADDED block with header-only SHALL → enriched hint
- MODIFIED block with header-only MUST → enriched hint
- Neither header nor body contain SHALL/MUST → generic message preserved

Verified by reproducing the spec from #356, running
`openspec validate <change>` against the rebuilt CLI, and confirming the
new diagnostic guides the author to the fix. Reverting `validator.ts`
makes the two enriched-hint cases fail, so the tests guard the
regression.

Fixes #356

Co-authored-by: Pluviobyte <Pluviobyte@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Tabish Bidiwale <30385142+TabishB@users.noreply.github.com>
2026-05-31 08:03:50 +00:00
Tabish Bidiwale 0c5f0c6c48 Improve context-store setup and cleanup UX (#1137)
* Improve context-store setup and cleanup UX

* Address CodeRabbit context-store feedback

* Canonicalize cleanup registry test assertion
2026-05-28 18:02:07 +00:00
Tabish Bidiwale 21c1805d80 [codex] Polish beta context workspace flow (#1136)
* Polish beta context workspace flow

* Allow context-only initiative workspace open

* Add workspace beta compatibility review item
2026-05-28 15:49:13 +00:00
Tabish Bidiwale 11b2690618 test: split slow workspace open CI case (#1134) 2026-05-28 06:54:51 +00:00
Tabish Bidiwale fd92ccca74 [codex] Add context stores and initiative views (#1127)
* Document initiative-led workspace direction

* Add context stores and initiative change links

* Let workspaces open initiative views

* Add workspace root bundle artifacts

* Support legacy workspace roots in planning resolution

* Remove accidental workspace root bundle artifacts

* Bundle workspace reimplementation docs into roadmap

* Preserve workspace context store bindings

* Address review feedback for context store initiatives

* test: canonicalize context store path assertions

* Refine context store and workspace core boundaries

* Avoid initiative diagnostic regex backtracking
2026-05-27 08:06:02 +00:00
Tabish Bidiwale e441287b1f test: normalize workspace change path assertion (#1117) 2026-05-23 05:45:18 +00:00
Tabish Bidiwale 7fdb177158 [codex] Fix Windows workspace path CI failure (#1111)
* fix: handle canonical workspace paths

* docs: document path canonicalization pitfalls

* docs: scope canonicalization notes to tests

* docs: improve test agent guidance

* docs: shorten test agent guidance
2026-05-23 01:38:30 +00:00
Tabish Bidiwale 79303b5210 Update recommended high-reasoning models (#1107) 2026-05-20 18:36:09 +00:00
Tabish Bidiwale 8498042fe8 [codex] Add workspace change planning workflow (#1089)
* Propose workspace change planning

* Implement workspace setup skills phase

* Implement workspace skill updates

* Handle config profile workspace apply

* Implement workspace change creation phase

* Enrich planning context for workspace changes

* Update workflow skills for planning context

* Add workspace planning verification coverage

* Fix workspace update review issues

* Fix workspace skill drift comparison

* Clean up workspace change planning artifacts

* Archive workspace change planning

* Fix archived workspace planning spec purpose

* Address workspace planning review comments
2026-05-14 16:00:56 +00:00
Howard 053d8a59d5 docs(migration-guide): fix inconsistent /opsx:sync description (#1059)
Changed description from 'Preview/spec-merge without archiving' to 'Merge delta specs into main specs' to match commands.md and workflows.md
2026-05-07 02:20:51 +00:00
Tabish Bidiwale b642398bf3 Fix Windows workspace launch arg expectation (#1057) 2026-05-06 04:33:20 +00:00
Tabish Bidiwale ff506c347a Fix Windows workspace CI tests (#1056) 2026-05-06 04:15:18 +00:00
Tabish Bidiwale 1cdf0410df [codex] Propose workspace open agent context (#1054)
* Propose workspace open agent context

* Implement workspace open surface

* Address workspace open review feedback

* Archive workspace open agent context

* Fix workspace open Windows launcher args
2026-05-06 03:53:55 +00:00
Tabish Bidiwale d5c824d4cd archive workspace create and register repos (#1052) 2026-05-06 02:30:11 +00:00
Tabish Bidiwale 849ae2a976 Fix Windows workspace path test expectations (#1055) 2026-05-06 01:54:12 +00:00
315 changed files with 42934 additions and 6856 deletions
+13 -11
View File
@@ -12,11 +12,12 @@ Follow the prompts to select version bump type and describe your changes.
## Workflow
1. **Add a changeset** — Run `pnpm changeset` locally before or after your PR
2. **Version PR** — CI opens/updates a "Version Packages" PR when changesets merge to main
3. **Release** — Merging the Version PR triggers npm publish and GitHub Release
1. **Choose the release path**: Maintainers decide whether a PR follows the normal release cadence or gets dedicated release tracking.
2. **Add dedicated release tracking**: When a maintainer asks for a changeset, run `pnpm changeset` locally before or after your PR.
3. **Version PR**: CI opens/updates a "Version Packages" PR when changesets merge to main.
4. **Release**: Merging the Version PR triggers npm publish and GitHub Release.
> **Note:** Contributors only need to run `pnpm changeset`. Versioning (`changeset version`) and publishing happen automatically in CI.
> **Note:** The default path is the normal release cadence. Add a changeset when a maintainer or release owner wants dedicated release notes and version tracking for the PR. Versioning (`changeset version`) and publishing happen automatically in CI.
## Template
@@ -54,22 +55,23 @@ Include only the sections relevant to your change.
| Type | When to use | Example |
|------|-------------|---------|
| `patch` | Bug fixes, small improvements | Fixed crash when config missing |
| `patch` | Release-tracked bug fixes, small improvements | Fixed crash when config missing |
| `minor` | New features, non-breaking additions | Added `--verbose` flag |
| `major` | Breaking changes, removed features | Renamed `init` to `setup` |
## When to Create a Changeset
**Create one for:**
- New features or commands
- Bug fixes that affect users
**Use dedicated release tracking for:**
- New features or commands selected for release
- Notable bug fixes or hotfixes requested by a maintainer/release owner
- Breaking changes or deprecations
- Performance improvements users would notice
- Performance improvements users would notice and that are planned for release
**Skip for:**
**Use the normal release cadence for:**
- Routine bug fixes that fit the normal release cadence
- Documentation-only changes
- Test additions/fixes
- Internal refactoring with no user impact
- Internal refactoring that preserves user behavior
- CI/tooling changes
## Writing Good Descriptions
-2
View File
@@ -1,2 +0,0 @@
---
---
-7
View File
@@ -1,7 +0,0 @@
---
"@fission-ai/openspec": patch
---
### Bug Fixes
- **CLI path visibility**: OpenSpec now documents editor and agent PATH mismatches, warns during global installs when the detected CLI bin directory is not on PATH, and generates workflow skills with guidance for resolving `openspec` through `OPENSPEC_BIN` or an absolute path.
-11
View File
@@ -1,11 +0,0 @@
---
"@fission-ai/openspec": minor
---
### New Features
- **Kimi CLI support** — OpenSpec can now initialize Kimi CLI as a supported skills-only tool using `.kimi/skills/`
### Other
- Added Kimi-specific docs and init coverage aligned with skill-based `/skill:openspec-*` usage
-7
View File
@@ -1,7 +0,0 @@
---
"@fission-ai/openspec": minor
---
### New Features
- Include the sync workflow in the default core profile so new installs generate `/opsx:sync` skills and commands by default.
+32 -12
View File
@@ -60,7 +60,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: '20.19.0'
cache: 'pnpm'
- name: Install dependencies
@@ -83,7 +83,7 @@ jobs:
name: Test (${{ matrix.label }})
runs-on: ${{ matrix.os }}
timeout-minutes: 15
if: github.event_name == 'push'
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
strategy:
fail-fast: false
matrix:
@@ -116,7 +116,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: '20.19.0'
cache: 'pnpm'
- name: Print environment diagnostics
@@ -155,7 +155,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: '20.19.0'
cache: 'pnpm'
- name: Install dependencies
@@ -242,7 +242,7 @@ jobs:
run: git checkout -- flake.nix || true
validate-changesets:
name: Validate Changesets
name: Validate Release Tracking
runs-on: ubuntu-latest
if: github.event_name == 'pull_request' || github.event_name == 'merge_group'
steps:
@@ -251,27 +251,47 @@ jobs:
with:
fetch-depth: 0
- name: Determine release tracking
id: changed-changesets
run: |
changed_changesets="$(git diff --name-only --diff-filter=ACMRT origin/main...HEAD -- '.changeset/*.md' ':!.changeset/README.md')"
if [[ -n "$changed_changesets" ]]; then
echo "has_changesets=true" >> "$GITHUB_OUTPUT"
{
echo "files<<EOF"
echo "$changed_changesets"
echo "EOF"
} >> "$GITHUB_OUTPUT"
else
echo "has_changesets=false" >> "$GITHUB_OUTPUT"
echo "This PR follows the normal release cadence; continuing with standard validation"
fi
- name: Setup pnpm
if: steps.changed-changesets.outputs.has_changesets == 'true'
uses: pnpm/action-setup@v4
with:
version: 9
- name: Setup Node.js
if: steps.changed-changesets.outputs.has_changesets == 'true'
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: '20.19.0'
cache: 'pnpm'
- name: Install dependencies
if: steps.changed-changesets.outputs.has_changesets == 'true'
run: pnpm install --frozen-lockfile
- name: Validate changesets
- name: Validate release-tracked changesets
if: steps.changed-changesets.outputs.has_changesets == 'true'
env:
CHANGESET_FILES: ${{ steps.changed-changesets.outputs.files }}
run: |
if command -v changeset &> /dev/null; then
pnpm exec changeset status --since=origin/main
else
echo "Changesets not configured, skipping validation"
fi
echo "Validating changed changesets:"
printf '%s\n' "$CHANGESET_FILES"
pnpm exec changeset status --since=origin/main
required-checks-pr:
name: All checks passed
+59
View File
@@ -1,5 +1,64 @@
# @fission-ai/openspec
## 1.5.0
### Minor Changes
- [#1267](https://github.com/Fission-AI/OpenSpec/pull/1267) [`96f6cac`](https://github.com/Fission-AI/OpenSpec/commit/96f6cacb206c65bee30066f6a1f4e9b855a0d783) Thanks [@TabishB](https://github.com/TabishB)! - ### New Features
- **Stores (very early beta)** — Introduces stores as a simpler way to organize specs and changes, replacing the workspace and initiative model. This feature is in very early beta — expect rough edges and breaking changes in upcoming releases.
### Bug Fixes
- **Config parsing** — Configuration values wrapped in JSON containers are now parsed correctly.
### Patch Changes
- [#1240](https://github.com/Fission-AI/OpenSpec/pull/1240) [`cbf386b`](https://github.com/Fission-AI/OpenSpec/commit/cbf386bd6888f103f8ff7d59b3eab98ce5b57998) Thanks [@zied-jlassi](https://github.com/zied-jlassi)! - fix(adapters): escape carriage returns in generated YAML frontmatter
`escapeYamlValue` flagged `\r` as a character requiring quoting but never escaped it, leaving a literal carriage return inside the double-quoted scalar where YAML line folding/normalization could silently corrupt the value (realistic with CRLF-authored command descriptions). Carriage returns are now escaped as `\r`. The helper — previously duplicated verbatim across five adapters (bob, claude, cursor, pi, windsurf) — is extracted into a shared `command-generation/yaml.ts` module so the behavior stays consistent and is fixed in one place.
## 1.4.1
### Patch Changes
- [#1165](https://github.com/Fission-AI/OpenSpec/pull/1165) [`0a01146`](https://github.com/Fission-AI/OpenSpec/commit/0a01146c181a3af8dbf645547bcbe20c0d48d615) Thanks [@TabishB](https://github.com/TabishB)! - Move beta workspace view state to `.openspec-workspace/view.yaml`, stop top-level `openspec update` from routing into workspace updates, and ignore foreign root `workspace.yaml` files so Dagster projects keep updating normally.
## 1.4.0
### Minor Changes
- [#1003](https://github.com/Fission-AI/OpenSpec/pull/1003) [`342ed43`](https://github.com/Fission-AI/OpenSpec/commit/342ed43e694abba65a3ea275f94ba3b77df85da3) Thanks [@Miss-you](https://github.com/Miss-you)! - ### New Features
- **Kimi CLI support** — OpenSpec can now initialize Kimi CLI as a supported skills-only tool using `.kimi/skills/`
### Other
- Added Kimi-specific docs and init coverage aligned with skill-based `/skill:openspec-*` usage
- [#1154](https://github.com/Fission-AI/OpenSpec/pull/1154) [`aa16080`](https://github.com/Fission-AI/OpenSpec/commit/aa16080d16b70f7b26cebd465334b2e16c0e7a43) Thanks [@TabishB](https://github.com/TabishB)! - ### New Features
- **Mistral Vibe support** — OpenSpec can now initialize Mistral Vibe as a supported skills-only tool using `.vibe/skills/`
### Bug Fixes
- **Case-insensitive requirement headers** — Requirement headers are now parsed regardless of capitalization, so specs no longer fail to parse over header casing
- **Zsh completions on oh-my-zsh** — Fixed shell completion setup so tab completion installs correctly under oh-my-zsh's `compinit`
### Other
- **Clearer validation hints** — When a requirement has SHALL/MUST only in its header, `openspec validate` now points you to move the keyword onto the requirement body line instead of showing the generic error
- [#1030](https://github.com/Fission-AI/OpenSpec/pull/1030) [`485c97e`](https://github.com/Fission-AI/OpenSpec/commit/485c97e97d766e35dd16c02370baee2044abc4f4) Thanks [@TabishB](https://github.com/TabishB)! - ### New Features
- Include the sync workflow in the default core profile so new installs generate `/opsx:sync` skills and commands by default.
### Patch Changes
- [#1111](https://github.com/Fission-AI/OpenSpec/pull/1111) [`7fdb177`](https://github.com/Fission-AI/OpenSpec/commit/7fdb1771585b1688597d73dde5a8bc906084d0de) Thanks [@TabishB](https://github.com/TabishB)! - ### Fixed
- Preserve workspace planning detection when Windows short paths or symlink aliases resolve to a canonical workspace root.
## 1.3.1
### Patch Changes
+25 -4
View File
@@ -47,6 +47,14 @@ Our philosophy:
## See it in action
```text
You: /opsx:explore
AI: What would you like to explore?
You: I want dark mode but I'm not sure how to do it cleanly.
AI: Let me look at your styling setup...
Cleanest path here: CSS variables + a small theme context,
with system-preference detection. No new dependencies. Scope it?
You: Yes, let's do it.
You: /opsx:propose add-dark-mode
AI: Created openspec/changes/add-dark-mode/
✓ proposal.md — why we're doing this, what's changing
@@ -94,9 +102,12 @@ cd your-project
openspec init
```
Now tell your AI: `/opsx:propose <what-you-want-to-build>`
Now talk to your AI:
If you want the expanded workflow (`/opsx:new`, `/opsx:continue`, `/opsx:ff`, `/opsx:verify`, `/opsx:bulk-archive`, `/opsx:onboard`), select it with `openspec config profile` and apply with `openspec update`.
- **Not sure what to build yet?** Start with `/opsx:explore`, a no-stakes thinking partner that reads your code, weighs options, and shapes a plan before anything is written. ([Explore guide](docs/explore.md))
- **Already know what you want?** Go straight to `/opsx:propose <what-you-want-to-build>`.
Both are in the default profile. If you want the expanded workflow (`/opsx:new`, `/opsx:continue`, `/opsx:ff`, `/opsx:verify`, `/opsx:bulk-archive`, `/opsx:onboard`), select it with `openspec config profile` and apply with `openspec update`.
> [!NOTE]
> Not sure if your tool is supported? [View the full list](docs/supported-tools.md) – we support 25+ tools and growing.
@@ -105,14 +116,24 @@ If you want the expanded workflow (`/opsx:new`, `/opsx:continue`, `/opsx:ff`, `/
## Docs
**Start here:** the **[Documentation Home](docs/README.md)** maps everything. New to OpenSpec? Read [Getting Started](docs/getting-started.md), then [How Commands Work](docs/how-commands-work.md) (where you actually type `/opsx:propose`).
→ **[Getting Started](docs/getting-started.md)**: first steps<br>
→ **[Explore First](docs/explore.md)**: think it through with `/opsx:explore` before you commit<br>
→ **[How Commands Work](docs/how-commands-work.md)**: where slash commands run vs the CLI<br>
→ **[Core Concepts at a Glance](docs/overview.md)**: the whole mental model, one page<br>
→ **[Examples & Recipes](docs/examples.md)**: real changes, start to finish<br>
→ **[Workflows](docs/workflows.md)**: combos and patterns<br>
→ **[Existing Projects](docs/existing-projects.md)**: adopt OpenSpec on a brownfield codebase<br>
→ **[Editing a Change](docs/editing-changes.md)**: update artifacts, go back, reconcile manual edits<br>
→ **[Commands](docs/commands.md)**: slash commands & skills<br>
→ **[CLI](docs/cli.md)**: terminal reference<br>
→ **[Stores](docs/stores-beta/user-guide.md)**: plan in a separate repo, shared across your team (beta)<br>
→ **[Supported Tools](docs/supported-tools.md)**: tool integrations & install paths<br>
→ **[Concepts](docs/concepts.md)**: how it all fits<br>
→ **[Multi-Language](docs/multi-language.md)**: multi-language support<br>
→ **[Customization](docs/customization.md)**: make it yours
→ **[Customization](docs/customization.md)**: make it yours<br>
→ **[FAQ](docs/faq.md)** · **[Troubleshooting](docs/troubleshooting.md)** · **[Glossary](docs/glossary.md)**: quick help
## Community schemas
@@ -157,7 +178,7 @@ openspec update
## Usage Notes
**Model selection**: OpenSpec works best with high-reasoning models. We recommend Opus 4.5 and GPT 5.2 for both planning and implementation.
**Model selection**: OpenSpec works best with high-reasoning models. We recommend Codex 5.5 and Opus 4.7 for both planning and implementation.
**Context hygiene**: OpenSpec benefits from a clean context window. Clear your context before starting implementation and maintain good context hygiene throughout your session.
-470
View File
@@ -1,470 +0,0 @@
# Workspace Reimplementation Direction
Date: 2026-04-30
Fresh-agent entry point: read `WORKSPACE_REIMPLEMENTATION_START_HERE.md` first, then return to this document for the full product direction.
This document captures the intended direction for reimplementing OpenSpec workspace support from scratch, based on what we learned from the workspace POC.
The reimplementation should be ordered around the path a real user takes through OpenSpec:
```text
set up workspace
-> link repos or folders
-> open workspace
-> explore across repos or folders
-> create proposal
-> apply one repo slice
-> verify
-> archive
```
The goal is not to rebuild every POC mechanism. The goal is to get one user-facing capability working at a time, in the same order a user would naturally create, implement, verify, and archive a change.
## North Star
A user should think:
```text
I have a multi-repo product goal.
I set up an OpenSpec workspace.
I open it with my agent.
The agent can see the linked repos or folders.
We explore until the scope is clear.
Then we create a proposal.
Then we implement one repo slice at a time.
```
They should not think:
```text
I need to create a change so repos become visible.
I need to materialize repo-local artifacts.
I need to understand implementation-specific workspace machinery.
I need to manage target metadata separately from proposal files.
```
The core product rule is:
```text
Workspace visibility is not change commitment.
```
Linked repos or folders are planning context. Creating a change is a planning commitment. Applying a change is an implementation workflow.
## Build Order
### 1. Workspace Setup And Links
First make workspace setup boring and solid.
User goal:
```text
Create a planning home and link the repos or folders OpenSpec should know about.
```
Expected surface:
```bash
openspec workspace setup
openspec workspace setup --no-interactive --name platform --link /path/to/api --link web=/path/to/web
openspec workspace list
openspec workspace ls
openspec workspace link /path/to/api
openspec workspace link api-service /path/to/api
openspec workspace relink api /new/path/to/api
openspec workspace doctor
```
Expected outcome:
```text
workspace-folder/
changes/
.openspec-workspace/
workspace.yaml
local.yaml
```
Product decisions:
- Use `.openspec-workspace/`, not `.openspec/`, for workspace metadata.
- Keep `changes/` visible in the workspace folder.
- Keep setup as the only public creation path for the first release; do not expose `workspace create`.
- Use `workspace link` and `workspace relink`, not POC-era `add-repo` or `update-repo`.
- Allow linked repos or folders without repo-local `openspec/` state.
- Keep stable link names in shared workspace state and local paths in machine-local state.
- Make `doctor` show link names, resolved paths, repo-local specs paths when present, and suggested fixes.
Defer:
- Agent launch and workspace open behavior.
- Preferred-agent prompts.
- Owner or handoff metadata.
- Workspace change creation or target selection.
- Branches.
- Worktrees.
- Apply.
- Archive.
- Complex target lifecycle.
Done when a user can set up a workspace, link repos or folders, list known workspaces, relink local paths, and run `doctor` to see exactly what OpenSpec can resolve.
### 2. Workspace Open
Next make the workspace openable in the way users expect.
User goal:
```text
Open this multi-repo planning context with my coding agent.
```
Expected surface:
```bash
openspec workspace open
openspec workspace open --agent codex
openspec workspace open --agent github-copilot
```
Product behavior:
- `workspace open` opens the coordination workspace plus linked repos or folders.
- Repo visibility is default.
- Change selection is optional focus, not the mechanism for repo access.
- `--agent` should be a one-session override by default. Persisting the preferred agent should require an explicit preference-setting action.
For GitHub Copilot, generate or open a `.code-workspace` file with:
```text
workspace folder
linked repo or folder A
linked repo or folder B
```
For Claude and Codex, attach the linked repo or folder directories through the agent's supported mechanism.
Defer:
- `workspace open --change`.
- In-session upgrade flows.
- Per-change attachment restrictions.
Done when opening a workspace gives the agent visibility into the coordination root and all linked repos or folders.
### 3. Agent Guidance And Explore
Then make exploration work.
User goal:
```text
Tell the agent a rough product goal and have it inspect the repos before creating a proposal.
```
Expected user prompt:
```text
Explore how we should make the OpenSpec docs available on the landing page.
Look across the linked repos or folders, but do not implement yet.
```
Agent behavior:
- Understand it is in workspace mode.
- Inspect linked repos or folders.
- Explain likely affected repos.
- Ask for clarification only when needed.
- Avoid implementation edits during explore.
Build:
- Workspace-level `AGENTS.md` guidance.
- Normal OpenSpec skills and commands in workspace sessions.
- Workspace-specific guidance layered on top of normal `/explore`, not replacing it.
Defer:
- Proposal artifact generation.
- Target confirmation commands.
- Apply context providers.
Done when a user can open a workspace and run a useful cross-repo exploration without creating a dummy change.
### 4. Proposal Creation
Only after explore works, build proposal creation.
User goal:
```text
Now that we understand the scope, capture the plan.
```
Expected user prompt:
```text
Create a proposal for this change.
Target the repos that are actually affected.
```
Preferred artifact shape:
```text
changes/integrate-docs/
proposal.md
design.md
tasks.md
specs/
openspec/
docs-conventions/spec.md
landing/
docs-routing/spec.md
```
Key workflow rule:
```text
/explore may leave targets unknown.
/propose may discover targets.
/propose must confirm targets before saying ready for apply.
```
Targets should be represented by the proposal artifacts themselves where possible. If there is `specs/landing/...`, then `landing` is in scope. Avoid a separate required `targets: [...]` metadata list as the active source of truth.
Defer:
- Repo-local materialization.
- Worktree selection.
- Multi-repo implementation.
- Archive.
Done when a user can explore, then create a workspace proposal with repo-scoped specs and tasks.
### 5. Status
Before implementation, make status excellent.
User goal:
```text
Where are we, what repos are involved, and is this ready to implement?
```
Expected surface:
```bash
openspec status
openspec status --change integrate-docs
```
Human output should answer:
```text
Change: integrate-docs
Scope: openspec, landing
Proposal: present
Design: present
Tasks: present
Ready for apply: yes/no
```
Status should also catch structural mistakes:
- Unknown repo folder under `specs/`.
- Missing tasks.
- No confirmed affected repo.
- Linked repo or folder path missing.
Done when the agent and user can trust status before applying.
### 6. Apply One Repo Slice
Only now build `/apply`.
User goal:
```text
Implement the planned slice for one repo.
```
Expected user prompt:
```text
/apply integrate-docs for landing
```
Product contract:
```text
/apply means implement.
```
It does not mean:
```text
copy planning files
materialize repo-local OpenSpec state
create the proposal files for the first time
```
Agent behavior:
1. Ask OpenSpec for apply context.
2. Read proposal, design, tasks, and relevant specs.
3. Confirm the target repo checkout.
4. Edit only that repo.
5. Update workspace tasks.
6. Run relevant checks.
This likely wants a normalized context command internally, but that is supporting machinery:
```json
{
"mode": "workspace",
"change": "integrate-docs",
"target": "landing",
"implementationRoot": "/repos/openspec-landing",
"contextFiles": [
"changes/integrate-docs/proposal.md",
"changes/integrate-docs/design.md",
"changes/integrate-docs/tasks.md",
"changes/integrate-docs/specs/landing/docs-routing/spec.md"
],
"allowedEditRoots": [
"/repos/openspec-landing"
],
"tasksFile": "changes/integrate-docs/tasks.md"
}
```
Defer:
- Applying multiple repos at once.
- Automatic branch creation.
- Worktree management.
- Repo-local OpenSpec mirroring.
Done when one repo slice can be implemented from the central workspace plan.
### 7. Verify
Then build verification.
User goal:
```text
Check whether the implemented repo slice satisfies the plan.
```
Expected prompt:
```text
/verify integrate-docs for landing
```
Behavior:
- Read the same normalized context as `/apply`.
- Inspect the implementation checkout.
- Check tasks and specs for that repo.
- Run repo validation.
- Report gaps clearly.
Default behavior should verify one repo slice. Whole-workspace verification can come later.
Done when a user can verify one implemented repo slice against the central workspace plan.
### 8. Archive
Archive comes last in the first complete loop.
User goal:
```text
The change is done. Move it out of active planning.
```
Expected prompt:
```text
/archive integrate-docs
```
Behavior:
- Require all targeted repo slices to be complete or explicitly accepted.
- Archive the workspace change.
- Do not require repo-local planning copies unless OpenSpec later decides that repo-local archival matters.
Done when a user can complete the full lifecycle:
```text
workspace setup
-> link repos or folders
-> open
-> explore
-> propose
-> apply repo A
-> apply repo B
-> verify
-> archive
```
## Implementation Discipline
Build only the next user-visible step.
The sequence should stay grounded in these questions:
```text
1. Can I set up the workspace?
2. Can I see my linked repos or folders?
3. Can my agent explore them?
4. Can we capture a proposal?
5. Can status tell us if it is ready?
6. Can the agent implement one repo slice?
7. Can we verify it?
8. Can we archive it?
```
Avoid starting with internal abstractions unless they are required for the next user-visible capability.
Do not start with:
- Target metadata machinery.
- Materialization.
- Adapter abstractions.
- Branch orchestration.
- Worktree orchestration.
- Multi-repo apply.
Those may matter later, but they should not define the first reimplementation path.
## Product Shape
The workspace should feel like OpenSpec's normal workflow stretched across multiple repos, not a second product with its own lifecycle.
The durable product model is:
```text
workspace = durable planning home
links = repos or folders visible for planning
proposal = scoped planning commitment
repo slice = one affected repo or folder in the plan
branch/worktree = implementation checkout
/apply = implement one selected repo slice
```
Keep the user journey simple:
```text
Open the workspace.
Ask the agent to explore.
Create the proposal when scope is clear.
Implement one repo slice at a time.
Verify.
Archive.
```
-67
View File
@@ -1,67 +0,0 @@
# Workspace Reimplementation Start Here
This is the grep-friendly entry point for agents working on the workspace reimplementation.
Useful search terms:
```text
workspace reimplementation
workspace poc
workspace-poc
workspace reference guide
workspace roadmap
fresh agent
start here
```
## Start Here
Read these files in order:
1. `WORKSPACE_REIMPLEMENTATION_DIRECTION.md`
2. `openspec/changes/workspace-reimplementation-roadmap/README.md`
3. `openspec/changes/workspace-reimplementation-roadmap/POC_REFERENCE_GUIDE.md`
4. The proposal for the next implementation slice
The POC reference commit is:
```text
workspace-poc @ 79a45ac043f414e63d13e08b9da83b135cb20a39
```
Use the POC as research material. Do not merge it into an implementation branch. Do not preserve its architecture unless a slice proposal or design explicitly decides to do so.
## Implementation Order
Implement these flat OpenSpec changes in order:
1. `workspace-foundation`
2. `workspace-create-and-register-repos`
3. `workspace-open-agent-context`
4. `workspace-change-planning`
5. `workspace-apply-repo-slice`
6. `workspace-verify-and-archive`
`workspace-reimplementation-roadmap` is the continuity and reference container for the plan.
## Before Editing
For the slice you are about to implement, inspect the pinned POC commit using `POC_REFERENCE_GUIDE.md`, then write down:
```text
POC findings for <slice>:
User behavior to preserve:
- ...
Tests or examples worth translating:
- ...
Implementation shortcuts to avoid:
- ...
Open design questions:
- ...
```
Capture durable findings in the relevant OpenSpec artifact so future sessions do not depend on chat history.
+3 -1
View File
@@ -1,3 +1,5 @@
#!/usr/bin/env node
import '../dist/cli/index.js';
import { runCli } from '../dist/cli/index.js';
runCli();
+107
View File
@@ -0,0 +1,107 @@
# OpenSpec Documentation
Welcome. This is the home for everything OpenSpec.
OpenSpec helps you and your AI coding assistant **agree on what to build before any code is written.** You describe the change, the AI drafts a short spec and a task list, you both look at the same plan, and then the work happens. No more discovering halfway through that the AI built the wrong thing.
If you read nothing else, read these two pages:
1. [Getting Started](getting-started.md): install, initialize, and ship your first change.
2. [How Commands Work](how-commands-work.md): where you actually type `/opsx:propose` (hint: in your AI chat, not the terminal). This trips up almost everyone once.
That second one matters more than it looks. OpenSpec has two halves: a command line tool you run in your terminal, and slash commands you give to your AI assistant. Knowing which is which saves you the most common moment of confusion.
> **The best habit to build first: when you're not sure what to build, start with `/opsx:explore`.** It's a no-stakes thinking partner that reads your code, weighs options, and sharpens a fuzzy idea into a concrete plan before any artifact or code exists. The [Explore First](explore.md) guide makes the case.
## Pick your path
**I'm brand new.** Start with [Getting Started](getting-started.md), then skim the [Core Concepts at a Glance](overview.md). When something feels mysterious, the [FAQ](faq.md) and [Glossary](glossary.md) are nearby.
**I have a problem but not a plan.** This is the common case, and it has a dedicated answer: [Explore First](explore.md). Use `/opsx:explore` to think it through with the AI before committing to anything.
**I have a big existing codebase.** You don't document all of it. [Using OpenSpec in an Existing Project](existing-projects.md) shows how to start on real, brownfield code without boiling the ocean.
**I just want to get it working.** [Install](installation.md), run `openspec init`, then read [How Commands Work](how-commands-work.md) so your first slash command lands in the right place.
**I learn by example.** The [Examples & Recipes](examples.md) page walks through real changes start to finish: a small feature, a bug fix, a refactor, an exploration.
**I'm coming from the old workflow.** The [Migration Guide](migration-guide.md) explains what changed and why, and promises your existing work is safe.
**I want to bend it to my team's process.** [Customization](customization.md) covers project config, custom schemas, and shared context.
**Something's broken.** [Troubleshooting](troubleshooting.md) collects the failures people actually hit, with fixes.
## The whole map
### Start here
| Doc | What it gives you |
|-----|-------------------|
| [Getting Started](getting-started.md) | Install, initialize, and run your first change end to end |
| [Explore First](explore.md) | Use `/opsx:explore` to think through an idea before you commit |
| [How Commands Work](how-commands-work.md) | Where slash commands run, what "interactive mode" means, terminal vs chat |
| [Core Concepts at a Glance](overview.md) | The whole mental model on one page: specs, changes, deltas, archive |
| [Installation](installation.md) | npm, pnpm, yarn, bun, Nix, and how to verify it worked |
### Use it day to day
| Doc | What it gives you |
|-----|-------------------|
| [Workflows](workflows.md) | Common patterns and when to reach for each command |
| [Examples & Recipes](examples.md) | Full walkthroughs of real changes, copy-pasteable |
| [Using OpenSpec in an Existing Project](existing-projects.md) | Adopting OpenSpec on a large brownfield codebase |
| [Editing & Iterating on a Change](editing-changes.md) | Update artifacts, go back, reconcile manual edits |
| [Commands](commands.md) | Reference for every `/opsx:*` slash command |
| [CLI](cli.md) | Reference for every `openspec` terminal command |
### Understand it deeply
| Doc | What it gives you |
|-----|-------------------|
| [Concepts](concepts.md) | The long-form explanation of specs, changes, artifacts, schemas, and archive |
| [OPSX Workflow](opsx.md) | Why the workflow is fluid instead of phase-locked, plus an architecture deep dive |
| [Glossary](glossary.md) | Every term defined in one place |
### Make it yours
| Doc | What it gives you |
|-----|-------------------|
| [Customization](customization.md) | Project config, custom schemas, shared context |
| [Multi-Language](multi-language.md) | Generate artifacts in languages other than English |
| [Supported Tools](supported-tools.md) | The 25+ AI tools OpenSpec integrates with, and where files land |
### When you need help
| Doc | What it gives you |
|-----|-------------------|
| [FAQ](faq.md) | Quick answers to the questions people ask most |
| [Troubleshooting](troubleshooting.md) | Concrete fixes for concrete failures |
| [Migration Guide](migration-guide.md) | Moving from the legacy workflow to OPSX |
### Coordinate across repos (beta)
| Doc | What it gives you |
|-----|-------------------|
| [Stores: User Guide](stores-beta/user-guide.md) | Plan in its own repo when your work spans repos or teams |
| [Agent Contract](agent-contract.md) | The machine-readable CLI surfaces agents drive |
## The thirty-second version
```text
1. Install npm install -g @fission-ai/openspec@latest
2. Initialize cd your-project && openspec init
3. Explore (in your AI chat) /opsx:explore ← optional, but a great habit
4. Propose (in your AI chat) /opsx:propose add-dark-mode
5. Build (in your AI chat) /opsx:apply
6. Archive (in your AI chat) /opsx:archive
```
Steps 1 and 2 happen in your terminal. The rest happen in your AI assistant's chat. That split is the one thing worth memorizing, and [How Commands Work](how-commands-work.md) explains exactly why. Step 3 is optional, but starting with `/opsx:explore` when you're unsure is the habit most worth forming.
## Where else to get help
- **Discord:** [discord.gg/YctCnvvshC](https://discord.gg/YctCnvvshC) for questions, ideas, and help.
- **GitHub Issues:** [github.com/Fission-AI/OpenSpec/issues](https://github.com/Fission-AI/OpenSpec/issues) for bugs and feature requests.
- **`openspec feedback "your message"`** sends feedback straight from your terminal (it opens a GitHub issue).
Found something in these docs that's wrong, stale, or confusing? That's a bug. Open an issue or a PR. Documentation improvements are some of the most valuable contributions you can make.
+137
View File
@@ -0,0 +1,137 @@
# OpenSpec Agent Contract
Machine-readable surfaces of the `openspec` CLI, verified against `src/` (capstone audit, 2026-06-11). Every shape below is documented from the emitting code.
## 1. General conventions
- **One JSON document per invocation.** In `--json` mode, stdout carries exactly one JSON document (2-space pretty-printed). Human prose, spinners, and the store banner go to stderr.
- **Store banner.** In human mode, a store-selected root prints `Using OpenSpec root: <id> (<path>)` to stderr. Never printed in JSON mode.
- **Key casing is surface-dependent** (see Known inconsistencies): store/doctor/context payloads use `snake_case`; workflow payloads (`status`, `instructions`, `new change`, `validate`, `list`) use `camelCase`, except the embedded `root` object, which always uses `store_id`.
- **Optional keys are omitted, not null**, in most payloads (e.g. `root.store_id`, `member.path`). Exceptions that use explicit `null` are called out per shape (store doctor `git.*`, failure payloads).
## 2. The diagnostic envelope
One envelope shape is shared by every machine-readable diagnostic (`StoreDiagnostic`):
```json
{
"severity": "error" | "warning" | "info",
"code": "snake_case_string",
"message": "human sentence",
"target": "dotted.surface (optional)",
"fix": "one actionable sentence/command (optional)"
}
```
Diagnostics appear in two positions: **status arrays** (`status: StoreDiagnostic[]` at top level or per entry) for health findings, and **thrown errors** converted to a single-element `status` array on command failure.
## 3. Root selection and `RootOutput`
All root-resolving commands (`list`, `show`, `validate`, `status`, `instructions`, `instructions apply`, `new change`, `archive`, `doctor`, `context`) resolve one OpenSpec root with one precedence:
1. `--store <id>` → the registered store's root (`source: "store"`).
2. Otherwise, nearest ancestor with `openspec/`: planning shape → `source: "nearest"` (a `store:` pointer is ignored with a stderr warning); config-only dir with a valid `store:` pointer → that store, `source: "declared"`.
3. No nearest root + registered stores exist → error `no_root_with_registered_stores`.
4. No root, no stores: scaffolding commands treat the cwd as `source: "implicit"`; diagnostic commands (`doctor`, `context`) fail with `no_openspec_root` instead — they inspect, never scaffold.
Successful JSON payloads embed the root:
```json
"root": { "path": "/abs/path", "source": "store" | "declared" | "nearest" | "implicit", "store_id": "id (only when store-selected)" }
```
**Root-failure contract**: in JSON mode a resolution failure prints `{ ...commandNullShape, "status": [diagnostic] }` on stdout and exits 1.
## 4. Command JSON shapes
### 4.1 `list --json`
`{ "changes": [ { "name", "completedTasks", "totalTasks", "lastModified", "status": "no-tasks"|"complete"|"in-progress" } ], "root": RootOutput }` — note the per-change `status` is a string enum here. `--specs`: `{ "specs": [ { "id", "requirementCount" } ], "root" }`.
### 4.2 `show <item> --json`
Change: `{ "id", "title", "deltaCount", "deltas": [...], "root" }`. Spec: `{ "id", "title", "overview", "requirementCount", "requirements": [...], "metadata": { "version", "format", "sourcePath"? }, "root" }`.
### 4.3 `validate --json`
`{ "items": [ { "id", "type": "change"|"spec", "valid", "issues": [ { "level", "path", "message", "line"?, "column"? } ], "durationMs" } ], "summary": { "totals": {items,passed,failed}, "byType": {...} }, "version": "1.0", "root" }`. Exit 1 when any item fails.
### 4.4 `status --json`
`{ "changeName", "schemaName", "planningHome"?: { "kind", "root", "changesDir", "defaultSchema" }, "changeRoot", "artifactPaths": { "<id>": {outputPath, resolvedOutputPath, existingOutputPaths} }, "nextSteps": ["..."], "actionContext": { "mode": "repo-local", "sourceOfTruth": "repo", "planningArtifacts", "linkedContext", "allowedEditRoots", "requiresAffectedAreaSelection", "constraints" }, "isComplete", "applyRequires", "artifacts": [ {id, outputPath, status: "done"|"ready"|"blocked", missingDeps?} ], "root" }`. No active changes: `{ "changes": [], "message", "root" }`, exit 0.
### 4.5 `instructions <artifact> --json`
`{ "changeName", "artifactId", "schemaName", "changeDir", "planningHome"?, "outputPath", "resolvedOutputPath", "existingOutputPaths", "description", "instruction"?, "context"?, "rules"?, "references"?: ReferenceIndexEntry[], "template", "dependencies": [{id,done,path,description}], "unlocks", "root" }`.
`ReferenceIndexEntry`: `{ "store_id", "root"?, "specs"?: [{id,summary}], "fetch"?, "status": [] }` — resolved entries carry root/specs/fetch; unresolved carry store_id + warning status. Index capped at 50KB (`reference_index_truncated`).
### 4.6 `instructions apply --json`
`{ "changeName", "changeDir", "schemaName", "contextFiles": { "<artifactId>": ["/abs", ...] }, "progress": {total,complete,remaining}, "tasks": [{id,description,done}], "state": "blocked"|"all_done"|"ready", "missingArtifacts"?, "instruction", "references"?, "root" }`.
### 4.7 `new change <name> --json`
Success: `{ "change": { "id", "path", "metadataPath", "schema" }, "root" }`. Failure: `{ "change": null, "status": [d] }`, exit 1.
### 4.8 `archive <name> --json`
Success: `{ "archive": { "change", "archivedAs": "YYYY-MM-DD-name", "path", "specsUpdated", "totals"? }, "root" }`. Failure: `{ "archive": null, "root"?, "status": [d] }`, exit 1. JSON mode is strictly non-interactive: every prompt point becomes an `archive_*` code.
### 4.9 `doctor --json`
`{ "root": { "path", "source", "store_id"?, "healthy", "status": [] }, "store": { "id", "metadata": {present,valid,remote?}, "origin_url"?, "status": [] } | null, "references": [...], "status": [] }`. Health findings of any severity exit 0. Failure payload: `{ "root": null, "store": null, "references": [], "status": [d] }`, exit 1.
### 4.10 `context --json`
`{ "root": { "path", "source", "store_id"?, "role": "openspec_root" }, "members": [ { "role": "referenced_store", "id", "path"?, "remote"?, "fetch"?, "status": [] } ], "status": [] }`. AVAILABLE = path present AND status empty. `--code-workspace <path>` writes `{folders:[{name,path}]}` (available referenced stores only, `ref:` prefixes); in JSON mode the write runs before printing so stdout holds exactly one document even on write failure. Failure: `{ "root": null, "members": [], "status": [d] }`, exit 1.
### 4.11 `store ... --json`
setup/register: `{ "store": {id, root, metadata_path?}, "registry": {path, registered, already_registered}, "git": {is_repository, initialized, committed}, "created_files": [], "status": [] }`. unregister/remove: `{ "store", "registry": {path, removed}, "files": {deleted, deleted_path, left_on_disk}, "status": [] }`. list: `{ "stores": [{id, root}], "status": [] }`. doctor: `{ "stores": [ { id, root, metadata_path?, openspec_root: {...healthy, status}, metadata: {present, valid, id?, remote}, git: {is_repository, has_commits, has_uncommitted_changes, has_remote, origin_url}, status } ], "status": [] }` (`null` = unknown/not probed). Health findings exit 0; failures exit 1 with the matching null-shape. Prompt cancellation exits 130.
### 4.12 `schemas --json` / `templates --json`
`schemas`: bare array `[ {name, description, artifacts, source} ]`. `templates`: keyed object `{ "<artifactId>": {path, source} }`. Both cwd-based, no root/status keys.
## 5. Exit-code contract
| Situation | Exit | Stdout |
|---|---|---|
| Success, incl. health findings (doctor/context/store doctor) | 0 | the payload |
| Command failure in `--json` mode | 1 | one JSON document with `status: [d]` and the command's null-shape |
| `validate` with failing items | 1 | full report |
| Prompt cancellation (`store` group, human mode) | 130 | stderr only |
## 6. Diagnostic code catalog
### Resolution
`no_openspec_root`, `no_root_with_registered_stores`, `no_registered_stores`, `unknown_store`, `store_identity_mismatch`, `unhealthy_store_root`, `store_path_not_supported`, `invalid_store_pointer`, `initiative_option_removed`, `areas_option_removed`; pass-through: `invalid_store_id`, `invalid_store_registry`, `invalid_store_metadata`.
### OpenSpec-root health (error, no fix)
`openspec_store_root_missing`, `openspec_root_missing`, `openspec_config_missing`, `openspec_specs_missing`, `openspec_changes_missing`, `openspec_archive_missing`, plus `_not_directory` variants of each.
### Store registry/identity/state
`invalid_store_id`, `invalid_store_registry`, `invalid_store_metadata`, `store_registry_busy`, `store_not_found`, `no_store_registry`, `store_registry_changed`, `store_metadata_missing`, `store_metadata_id_mismatch`, `store_metadata_invalid`, `store_id_conflict`, `store_path_conflict`, `store_already_registered` (info).
### Store setup/register/remove
`store_setup_id_required`, `store_setup_path_required`, `store_setup_path_not_directory`, `store_setup_inside_git_repo`, `store_setup_non_empty_directory`, `store_setup_cancelled`, `store_path_required`, `store_path_missing`, `store_path_not_directory`, `store_register_root_unhealthy`, `store_register_identity_confirmation_required`, `store_register_cancelled`, `store_remote_empty`, `store_remote_requires_hand_edit`, `store_remove_confirmation_required`, `store_remove_cancelled`, `store_remove_path_not_directory`, `store_remove_metadata_missing`, `store_root_missing` (warning in remove, error in doctor), `store_root_not_directory`.
### Store git
`store_git_init_failed`, `store_git_identity_missing`, `store_git_commit_failed`, `store_git_no_commits` (warning), `store_clone_fragile_directories` (warning), `store_remote_divergence` (info, doctor).
### References (warning)
`reference_invalid_id`, `reference_registry_unreadable`, `reference_unresolved`, `reference_root_unhealthy`, `reference_index_truncated`.
### Relationships (warning; doctor; context keeps only the registry one)
`relationship_registry_unreadable`, `root_pointer_ignored`, `root_pointer_invalid`, `pointer_declarations_inert`.
### Archive (JSON mode)
`archive_change_name_required`, `archive_change_not_found`, `archive_validation_failed`, `archive_confirmation_required`, `archive_tasks_incomplete`, `archive_spec_update_failed`, `archive_spec_validation_failed`, `archive_target_exists`, `archive_error`.
### Context writes
`context_file_exists`, `context_output_dir_missing`.
### Fallbacks
`doctor_failed`, `context_failed`, `store_error`, `change_error`, `archive_error`.
## Known inconsistencies
Recorded by the capstone audit; published-key renames are product decisions deferred past this release:
1. ~~In `--json` mode, several failure paths printed stderr only with no JSON document.~~ Fixed in the capstone gauntlet round: `show`/`validate` unknown and ambiguous items emit `{status:[{code: unknown_item | ambiguous_item, ...}]}`; thrown errors in `status`/`instructions`/`list`/`show`/`validate` route through the JSON-aware failure helper (the command's null-shape + `status`); `store <unknown subcommand> --json` emits `{status:[{code: unknown_store_subcommand}]}`; `list` carries its `{changes|specs: [], root: null}` null-shape on resolution failures.
2. `store_root_missing` is emitted with two severities (warning in remove, error in store doctor) — context-dependent, documented above.
3. snake_case (store family) vs camelCase (workflow family) key casing; `root.store_id` is snake_case everywhere.
4. Four parallel envelope type declarations exist in src; archive diagnostics never carry `target`.
5. `list --json` reuses the `status` key as a string enum per change.
6. Only `validate` output carries a `version` field.
7. `schemas`/`templates` ignore root selection (cwd-based, no `--store`).
8. Deprecated noun forms (`change`/`spec` subcommands) emit unenveloped payloads without `root`/`status`.
+206 -75
View File
@@ -7,11 +7,14 @@ The OpenSpec CLI (`openspec`) provides terminal commands for project setup, vali
| Category | Commands | Purpose |
|----------|----------|---------|
| **Setup** | `init`, `update` | Initialize and update OpenSpec in your project |
| **Workspaces (beta)** | `workspace setup`, `workspace list`, `workspace ls`, `workspace link`, `workspace relink`, `workspace doctor` | Set up planning across linked repos or folders |
| **Stores (standalone OpenSpec repos)** | `store setup`, `store register`, `store unregister`, `store remove`, `store list`, `store doctor` | Manage stores — standalone OpenSpec repos you've registered |
| **Health** | `doctor` | Report relationship health for the resolved root |
| **Working context** | `context` | Assemble the working set (root + referenced stores) |
| **Personal worksets** | `workset create`, `workset list`, `workset open`, `workset remove` | Keep and open personal, local working views in your tool |
| **Browsing** | `list`, `view`, `show` | Explore changes and specs |
| **Validation** | `validate` | Check changes and specs for issues |
| **Lifecycle** | `archive` | Finalize completed changes |
| **Workflow** | `status`, `instructions`, `templates`, `schemas` | Artifact-driven workflow support |
| **Workflow** | `new change`, `status`, `instructions`, `templates`, `schemas` | Artifact-driven workflow support |
| **Schemas** | `schema init`, `schema fork`, `schema validate`, `schema which` | Create and manage custom workflows |
| **Config** | `config` | View and modify settings |
| **Utility** | `feedback`, `completion` | Feedback and shell integration |
@@ -30,6 +33,7 @@ These commands are interactive and designed for terminal use:
|---------|---------|
| `openspec init` | Initialize project (interactive prompts) |
| `openspec view` | Interactive dashboard |
| `openspec workset open <name>` | Open a saved workset (editor window or terminal agent session) |
| `openspec config edit` | Open config in editor |
| `openspec feedback` | Submit feedback via GitHub |
| `openspec completion install` | Install shell completions |
@@ -47,11 +51,16 @@ These commands support `--json` output for programmatic use by AI agents and scr
| `openspec instructions` | Get next steps | `--json` for agent instructions |
| `openspec templates` | Find template paths | `--json` for path resolution |
| `openspec schemas` | List available schemas | `--json` for schema discovery |
| `openspec workspace setup --no-interactive` | Create a workspace with explicit inputs | `--json` for structured setup output |
| `openspec workspace list` | Browse known workspaces | `--json` for typed workspace objects |
| `openspec workspace link` | Link a repo or folder | `--json` for structured link output |
| `openspec workspace relink` | Repair a linked path | `--json` for structured link output |
| `openspec workspace doctor` | Check one workspace | `--json` for structured status output |
| `openspec store setup <id>` | Create and register a local store | `--json` with explicit inputs for structured setup output |
| `openspec store register <path>` | Register an existing store | `--json` for structured registration output |
| `openspec store unregister <id>` | Forget a local store registration | `--json` for structured cleanup output |
| `openspec store remove <id>` | Delete a registered local store folder | `--yes --json` for non-interactive deletion |
| `openspec store list` | Browse registered stores | `--json` for structured registrations |
| `openspec store doctor` | Check local store setup | `--json` for structured diagnostics |
| `openspec new change <id>` | Create repo-local change scaffolding | `--json`, plus `--store <id>` to use a registered store as the OpenSpec root |
| `openspec workset create [name]` | Compose a personal working view | `--member <path> --json` for non-interactive composition |
| `openspec workset list` | Browse saved worksets | `--json` for structured views |
| `openspec workset remove <name>` | Delete a saved view | `--yes --json` for non-interactive removal |
---
@@ -95,7 +104,9 @@ openspec init [path] [options]
`--profile custom` uses whatever workflows are currently selected in global config (`openspec config profile`).
**Supported tool IDs (`--tools`):** `amazon-q`, `antigravity`, `auggie`, `bob`, `claude`, `cline`, `codex`, `forgecode`, `codebuddy`, `continue`, `costrict`, `crush`, `cursor`, `factory`, `gemini`, `github-copilot`, `iflow`, `junie`, `kilocode`, `kimi`, `kiro`, `opencode`, `pi`, `qoder`, `lingma`, `qwen`, `roocode`, `trae`, `windsurf`
**Supported tool IDs (`--tools`):** `amazon-q`, `antigravity`, `auggie`, `bob`, `claude`, `cline`, `codex`, `forgecode`, `codebuddy`, `continue`, `costrict`, `crush`, `cursor`, `factory`, `gemini`, `github-copilot`, `iflow`, `junie`, `kilocode`, `kimi`, `kiro`, `lingma`, `vibe`, `opencode`, `pi`, `qoder`, `qwen`, `roocode`, `trae`, `windsurf`
> This list mirrors `AI_TOOLS` in `src/core/config.ts`. See [Supported Tools](supported-tools.md) for each tool's skill and command paths.
**Examples:**
@@ -165,100 +176,196 @@ openspec update
---
## Workspace Commands
## Stores (standalone OpenSpec repos)
Workspace commands are under active development and are not ready for use yet. Do not build external automation, integrations, or long-lived workflows on top of this command surface; command behavior, state files, and JSON output can change at any point.
> **Beta.** Stores and the features built on them (references, working context, worksets) are new; command names, flags, file formats, and JSON output may change shape between releases. For the problem-first walkthrough, see the [stores guide](stores-beta/user-guide.md).
Coordination workspaces are planning homes for work that spans multiple repos or folders. Workspace visibility is not change commitment: link the repos or folders OpenSpec should know about, then create changes when you are ready to plan specific work.
A store is a standalone OpenSpec repo you've registered on this machine — for example a planning repo or a contracts repo. Registering a store lets normal commands (`list`, `show`, `status`, `validate`, `new change`, `archive`, ...) act in it from anywhere by passing `--store <id>`.
### `openspec workspace setup`
### `openspec store setup`
Create a workspace in the standard OpenSpec workspace location and link at least one existing repo or folder.
Create and register a local store. With no arguments in a terminal,
OpenSpec guides the user through setup. Agents and scripts should pass explicit
inputs and use `--json`.
```bash
openspec workspace setup [options]
openspec store setup [id] [options]
```
**Options:**
| Option | Description |
|--------|-------------|
| `--name <name>` | Workspace name. Names must be kebab-case |
| `--link <path>` | Link an existing repo or folder and infer the link name from the folder name |
| `--link <name>=<path>` | Link an existing repo or folder with an explicit link name |
| `--no-interactive` | Disable prompts; requires `--name` and at least one `--link` |
| `--json` | Output JSON; requires `--no-interactive` |
**Examples:**
```bash
openspec workspace setup
openspec workspace setup --no-interactive --name platform --link /repos/api --link web=/repos/web
openspec workspace setup --no-interactive --json --name checkout --link /repos/platform/apps/checkout
```
Setup prints the workspace location, planning path, linked repos or folders, and a workspace check. It does not ask for a preferred agent or open the workspace.
### `openspec workspace list`
List known OpenSpec workspaces from the local registry.
```bash
openspec workspace list [--json]
openspec workspace ls [--json]
```
The list shows each workspace location and linked repos or folders. Stale registry records are reported but not changed.
### `openspec workspace link`
Record an existing repo or folder for one workspace.
```bash
openspec workspace link [name] <path> [options]
```
**Options:**
| Option | Description |
|--------|-------------|
| `--workspace <name>` | Select a known workspace from the local registry |
| `--path <path>` | Folder where the store should live (for example `~/openspec/<id>`) |
| `--remote <url>` | Record the canonical remote in the new store's `store.yaml` |
| `--init-git` | Initialize a Git repository with an initial commit (default) |
| `--no-init-git` | Skip every Git action: no init, no initial commit |
| `--json` | Output JSON |
| `--no-interactive` | Disable workspace picker prompts |
**Examples:**
Non-interactive runs (`--json`, scripts, agents) must pass both the store id and `--path`. In an interactive terminal, setup prompts for the location with an editable suggestion in a visible, user-owned place (for example `~/openspec/<id>`); it never defaults to OpenSpec's managed data directory.
Examples:
```bash
openspec workspace link /repos/api
openspec workspace link api-service /repos/api
openspec workspace link --workspace platform /repos/platform/apps/checkout
openspec store setup
openspec store setup team-context
openspec store setup team-context --path ~/openspec/team-context --no-init-git
openspec store setup team-context --path ~/openspec/team-context --no-init-git --json
```
The path must already exist. Relative paths are resolved against the command's current directory before OpenSpec stores the verified absolute path in machine-local workspace state. Linked paths can be full repos, packages, services, apps, or folders without repo-local `openspec/` state.
### `openspec store register`
### `openspec workspace relink`
Repair or change the local path for an existing link.
Register an existing local store folder.
```bash
openspec workspace relink <name> <path> [options]
openspec store register [path] [options]
```
The path must already exist. Relink updates only the machine-local path for the stable link name.
**Options:**
### `openspec workspace doctor`
| Option | Description |
|--------|-------------|
| `--id <id>` | Store id; defaults to store metadata or folder name |
| `--yes` | Confirm creating store identity metadata for a healthy OpenSpec root |
| `--json` | Output JSON |
Check what one workspace can resolve on the current machine.
### `openspec store unregister`
Forget a local store registration without deleting files.
```bash
openspec workspace doctor [options]
openspec store unregister <id> [--json]
```
Doctor shows the workspace location, planning path, linked repos or folders, missing paths, repo-local specs paths when present, and suggested fixes. It reports issues only; it does not repair them automatically.
Use this when a store was moved, cloned somewhere else, or should no longer be
shown by OpenSpec on this machine.
Commands that need one workspace use the current workspace when run from inside a workspace folder or subdirectory. From elsewhere, pass `--workspace <name>`, select from the picker in an interactive terminal, or rely on the only known workspace when exactly one exists. In `--json` or `--no-interactive` mode, ambiguous selection fails with a structured status error and suggests `--workspace <name>`.
### `openspec store remove`
JSON responses use typed objects plus `status` arrays. Primary data lives in `workspace`, `workspaces`, or `link`; warnings and errors live in `status`.
Forget a local store registration and delete its local folder.
```bash
openspec store remove <id> [--yes] [--json]
```
`remove` shows the exact folder before deleting in an interactive terminal.
Agents, scripts, and JSON callers must pass `--yes` to confirm deletion.
OpenSpec refuses to delete a folder that does not contain matching
store metadata.
### `openspec store list`
List locally registered stores.
```bash
openspec store list [--json]
openspec store ls [--json]
```
### `openspec store doctor`
Check local store registration, metadata, and Git presence.
```bash
openspec store doctor [id] [--json]
```
Doctor is diagnostic-only; it reports missing roots, metadata mismatches, and invalid local registry state without modifying the store.
### Referencing stores from a project
A project repo can declare which stores its work draws on in `openspec/config.yaml`:
```yaml
schema: spec-driven
references:
- team-context
```
From then on, `openspec instructions` output in that repo (both the per-artifact and `apply` surfaces, JSON and human modes) carries an index of each referenced store's specs — spec ids, a one-line summary from each spec's Purpose section, and the fetch command (`openspec show <spec-id> --type spec --store <id>`). The index is built live from the registered checkout on every run; spec content is never copied into the output.
References are read-only context. They never change where commands act: work stays in the repo's own root, and writing to a referenced store remains an explicit `--store` action. A reference that cannot be resolved (for example, a store not registered on this machine) degrades to a warning in the index with the exact fix, and instructions still generate. `openspec doctor` reports reference health in one place.
### Recording where a store is cloned from
A store can record its canonical clone source in its committed identity file, so onboarding never dead-ends at "register the store":
```bash
openspec store setup team-context --path ~/openspec/team-context \
--remote git@github.com:acme/team-context.git
```
The remote lands in `.openspec-store/store.yaml` inside the initial commit, so every clone is born knowing it. For an existing store, edit `store.yaml` by hand and commit. `store doctor` shows the recorded remote (and the checkout's observed Git origin); setup/register sharing guidance names it; and register records the checkout's origin in the machine-local registry.
A reference declaration can carry the clone source too, so a teammate who doesn't have the store yet gets a complete, pasteable fix (`git clone <remote> <path> && openspec store register <path> --id <id>`):
```yaml
references:
- { id: team-context, remote: "git@github.com:acme/team-context.git" }
```
Recording a remote is not sync: OpenSpec never clones, pulls, or pushes on its own.
### Declaring a default store
A repo whose planning is fully externalized — no local `openspec/specs/` or `openspec/changes/` — can declare its store once instead of passing `--store` on every command:
```yaml
# openspec/config.yaml (the only file under openspec/)
store: team-context
```
Normal commands then resolve to the declared store automatically; the root banner and JSON `root` block report `source: "declared"` with the store id, and printed hints still carry `--store <id>`. The declaration is a fallback, never an override: explicit `--store` always wins, and a directory with real planning folders ignores the pointer (with a warning). To convert a pointer repo into a local OpenSpec root, remove the `store:` line and run `openspec init` — init refuses to scaffold while the declaration is present.
## Doctor (relationship health)
One read-only question, one place: is the OpenSpec root healthy, and are the stores it references available on this machine?
```bash
openspec doctor [--store <id>] [--json]
```
The report separates root health, store metadata health (including a note when the recorded remote and the checkout's origin diverge), and reference health (the same diagnostics instructions show, with clone fixes for unresolved references). Health findings of any severity exit 0 — agents read the `status` arrays; only command failures (no root, unknown store) exit 1. Doctor never clones, syncs, or repairs. To get the assembled set itself rather than its health, use `openspec context`.
## Working context (the assembled set)
Everything this work relates to through OpenSpec declarations, in one working set: the OpenSpec root and the stores it references.
```bash
openspec context [--store <id>] [--json] [--code-workspace <path> [--force]]
```
The JSON brief is agent-consumable (each available referenced store carries its fetch recipe; unresolved members carry the same fixes instructions and doctor show). `--code-workspace` additionally writes a VS Code workspace file containing the root plus the available referenced stores (`ref:<id>` folders) — the one write this command performs, refused without `--force` if the file exists. Unavailable members are reported, never guessed at.
"Working context" is the assembled set; the `context:` field in `openspec/config.yaml` is project background injected into instructions — two different things. `openspec doctor` answers whether the set is healthy; `openspec context` answers what the set is.
## Personal worksets
> **Beta.** Worksets are part of the new beta surface; commands, flags, and file formats may change shape between releases. For the walkthrough, see the [stores guide](stores-beta/user-guide.md#worksets-reopen-the-folders-you-work-on-together).
A workset is a personal, named view of the folders you work on together — a planning root plus whatever else you choose — kept on your machine and reopened by name in your tool. It is purely local: never committed, never shared, never derived from declarations, and removing one never touches a member folder.
```bash
openspec workset create [name] [--member <path> | --member <name>=<path>]... [--tool <id>] [--json]
openspec workset list [--json]
openspec workset open <name> [--tool <id>]
openspec workset remove <name> [--yes] [--json]
```
`create` runs a short guided flow (or takes `--member` flags non-interactively; the first member is the primary — sessions start there). `open` launches the chosen tool: editors (VS Code, Cursor) open a window with every member and return; CLI agents (Claude Code, codex) take over this terminal as a session with every member attached and no prompt pre-filled, ending when you exit. A member folder missing at open time is skipped with a note; the rest opens. The saved tool preference is overridable per open with `--tool`.
Supporting a new tool is configuration, not code. Every tool is one of two launch styles — `workspace-file` (launched with the generated `.code-workspace`) or `attach-dirs` (one attach flag per member) — and the `openers` key in the global `config.json` (open it with `openspec config edit`) adds tools or adjusts built-ins per field:
```json
{
"openers": {
"zed": { "style": "workspace-file" },
"claude": { "attach_flag": "--dir" }
}
}
```
All workset state lives under the global data dir's `worksets/` folder (the saved views plus the generated `<name>.code-workspace` files, regenerated on every open); deleting that folder removes every trace.
---
@@ -297,9 +404,8 @@ openspec list --json
**Output (text):**
```
Active changes:
add-dark-mode UI theme switching support
fix-login-bug Session timeout handling
Changes:
add-dark-mode No tasks just now
```
---
@@ -506,6 +612,31 @@ openspec archive update-ci-config --skip-specs
These commands support the artifact-driven OPSX workflow. They're useful for both humans checking progress and agents determining next steps.
### `openspec new change`
Create a change directory and optional checked-in metadata in the resolved OpenSpec root.
```bash
openspec new change <name> [options]
```
**Options:**
| Option | Description |
|--------|-------------|
| `--description <text>` | Description to add to `README.md` |
| `--goal <text>` | Optional goal metadata to store with the change |
| `--schema <name>` | Workflow schema to use |
| `--store <id>` | Store id to use as the OpenSpec root (a store is a standalone OpenSpec repo you've registered) |
| `--json` | Output JSON |
Examples:
```bash
openspec new change add-billing-api
openspec new change add-billing-api --store team-context --json
```
### `openspec status`
Display artifact completion status for a change.
@@ -921,7 +1052,7 @@ openspec config profile core
- Keep current settings (exit)
If you keep current settings, no changes are written and no update prompt is shown.
If there are no config changes but the current project files are out of sync with your global profile/delivery, OpenSpec will show a warning and suggest running `openspec update`.
If there are no config changes but the current project files are out of sync with your global profile/delivery, OpenSpec will show a warning and suggest `openspec update`.
Pressing `Ctrl+C` also cancels the flow cleanly (no stack trace) and exits with code `130`.
In the workflow checklist, `[x]` means the workflow is selected in global config. To apply those selections to project files, run `openspec update` (or choose `Apply changes to this project now?` when prompted inside a project).
+2
View File
@@ -72,6 +72,8 @@ AI: Created openspec/changes/add-dark-mode/
### `/opsx:explore`
> **Start here when you're unsure.** Explore is a no-stakes thinking partner: it reads your codebase, compares options, and sharpens a fuzzy idea into a concrete plan before any change exists. It ships in the default profile. For the full case and more examples, see the [Explore First](explore.md) guide.
Think through ideas, investigate problems, and clarify requirements before committing to a change.
**Syntax:**
-117
View File
@@ -49,123 +49,6 @@ OpenSpec organizes your work into two main areas:
This separation is key. You can work on multiple changes in parallel without conflicts. You can review a change before it affects the main specs. And when you archive a change, its deltas merge cleanly into the source of truth.
## Coordination Workspaces
Workspace support is under active development and is not ready for use yet. Do not build external automation, integrations, or long-lived workflows on top of workspace behavior; the commands, state files, and JSON output can change at any point.
The commands below provide the first setup flow for planning across linked repos or folders.
Repo-local OpenSpec projects are the right default when one repo owns the planning, implementation, and archive flow. Some work spans several repos or folders. For that case, an OpenSpec coordination workspace is the durable planning home.
The workspace mental model is:
```text
workspace = where related cross-repo changes live
link = a stable name for a repo or folder the workspace can plan against
change = one feature, fix, project, or other planned piece of work
```
A workspace has a different shape from a repo-local project:
```text
workspace-folder/
├── changes/ # Workspace-level planning
└── .openspec-workspace/
├── workspace.yaml # Shared workspace identity and link names
└── local.yaml # This machine's local paths
```
Repo-local OpenSpec state keeps the existing shape:
```text
repo-root/
└── openspec/
├── specs/
└── changes/
```
That distinction matters. The workspace folder is a coordination surface for planning across linked repos or folders. Each repo's `openspec/` directory remains the home for repo-owned specs, repo-local changes, and implementation planning. Users do not need to run repo-local `openspec init` inside a workspace folder.
Stable link names are how workspace planning refers to repos and folders. The shared workspace state keeps names such as `api`, `web`, or `checkout`; each machine maps those names to its own local paths in `.openspec-workspace/local.yaml`.
```yaml
# .openspec-workspace/workspace.yaml
version: 1
name: platform
links:
api: {}
web: {}
```
```yaml
# .openspec-workspace/local.yaml
version: 1
paths:
api: /repos/api
web: /repos/web
```
OpenSpec-created workspaces exclude `.openspec-workspace/local.yaml` from portable collaboration state by default. `.openspec-workspace/workspace.yaml` remains portable because it stores the workspace name and stable link names, not one user's absolute checkout paths.
Linked paths can be full repos, folders inside a large monorepo, or other existing folders. They do not need repo-local `openspec/` state before they can participate in workspace planning. Later implementation, verify, or archive workflows may require more repo readiness, but planning visibility starts with the link.
```text
multi-repo:
api -> /repos/api
web -> /repos/web
large monorepo:
billing -> /repos/platform/services/billing
checkout -> /repos/platform/apps/checkout
```
Managed workspaces live under the standard OpenSpec data directory:
```text
getGlobalDataDir()/workspaces
```
That means `$XDG_DATA_HOME/openspec/workspaces` when `XDG_DATA_HOME` is set, `~/.local/share/openspec/workspaces` on Unix-style fallback, and `%LOCALAPPDATA%\openspec\workspaces` on native Windows fallback. Native Windows shells, PowerShell, and WSL2 each keep the path strings for the runtime running OpenSpec. This foundation does not translate between `D:\repo`, `/mnt/d/repo`, and UNC WSL paths.
OpenSpec also keeps a machine-local registry at:
```text
getGlobalDataDir()/workspaces/registry.yaml
```
The registry maps workspace names to workspace locations so later global commands can list or select known workspaces from anywhere. It is only an index. Each workspace folder remains authoritative for its own `.openspec-workspace/workspace.yaml` and `.openspec-workspace/local.yaml`, so stale registry records can be reported and repaired without redefining the workspace itself.
Workspace visibility is not change commitment. Set up a workspace when OpenSpec should know which repos or folders are relevant; create a change later when you are ready to plan a feature, fix, project, or other piece of work.
Useful commands:
```bash
# Guided setup
openspec workspace setup
# Automation-friendly setup
openspec workspace setup --no-interactive --name platform --link /repos/api --link web=/repos/web
# See known workspaces from the local registry
openspec workspace list
openspec workspace ls
# Add or repair links for the selected workspace
openspec workspace link /repos/api
openspec workspace link api-service /repos/api
openspec workspace relink api-service /new/path/to/api
# Check what this machine can resolve
openspec workspace doctor
openspec workspace doctor --workspace platform
```
`workspace setup` always creates the workspace in the standard workspace location, records it in the local registry, shows the workspace location, and requires at least one linked repo or folder. `workspace link` and `workspace relink` record existing folders only; they do not create, copy, move, initialize, or edit the linked repo or folder.
Workspace commands that need one workspace can run from anywhere with `--workspace <name>`. If you run them inside a workspace folder or subdirectory, OpenSpec uses that current workspace. If several known workspaces are available and you do not pass `--workspace <name>`, human commands show a picker; `--json` and `--no-interactive` fail with a structured status error instead of prompting.
Direct workspace commands support JSON output for scripts. JSON responses keep primary data in `workspace`, `workspaces`, or `link` objects and report warnings or errors in `status` arrays. Healthy objects use `status: []`.
## Specs
Specs describe your system's behavior using structured requirements and scenarios.
+90
View File
@@ -0,0 +1,90 @@
# Editing & Iterating on a Change
**Every artifact in a change is just a Markdown file you can edit at any time.** There is no locked "planning phase," no approval gate, no special edit mode to enter. Want to change the proposal after you've started building? Open `proposal.md` and change it. Realized the design is wrong mid-implementation? Fix `design.md` and keep going. That's the whole answer, and it's by design.
This page is for the moment you think "wait, can I go back and change that?" Yes. Here's how, for each common case.
## Two ways to edit anything
You always have both:
1. **Edit the file directly.** Artifacts are plain Markdown in `openspec/changes/<name>/`. Open `proposal.md`, `design.md`, `tasks.md`, or a delta spec under `specs/` in your editor and change it. Nothing else is required.
2. **Ask your AI to revise it.** In chat, just say what you want: "Update the proposal to drop the caching idea and add a rate-limit section," or "the design should use a queue, not polling." The AI edits the artifact for you, using the rest of the change as context.
Use whichever fits the moment. Small wording tweak? Edit the file. Substantive rethink? Let the AI revise with full context.
## "How do I update the proposal (or specs) after I've started?"
Just update it. Same change, refined.
If you're using the expanded commands, the natural flow is: edit the artifact, then run `/opsx:continue` to pick up from the new state, or `/opsx:apply` to keep implementing against the updated plan. If you're on the default `core` commands, edit the artifact and run `/opsx:apply`; it reads the current files, so it builds against whatever the artifacts now say.
The mental model: artifacts are the live plan, not a signed contract. The AI always works from their current contents, so editing them steers the work.
```text
You: I want to change the approach in this change.
You: [edit design.md, or tell the AI:]
Update design.md to use a background job instead of a synchronous call.
AI: Updated design.md. The task list still fits; want me to continue applying?
You: /opsx:apply
```
This answers a very common question: there's no separate "update proposal" command because you don't need one. The file is the source of truth, and editing it (by hand or via the AI) is the update.
## "How do I go back to review after implementing?"
You don't have to "go back," because you never left. The workflow is fluid: review, edit, and implementation aren't sequential phases you're trapped in.
Concretely, after some `/opsx:apply` work:
- Want to re-examine the plan? Open the artifacts and read them, or run `openspec show <change>` in your terminal for a consolidated view.
- Found something to change? Edit the artifact (or ask the AI to), then continue.
- Want a structured check that the code matches the plan? Run `/opsx:verify` (expanded command). It reports completeness, correctness, and coherence without blocking anything. See [Workflows: Verify](workflows.md#verify-check-your-work).
There's no "review phase" to return to, because review is something you can do at any point, including after implementation.
## "I edited the code by hand. How do I reconcile that with OpenSpec?"
This happens constantly and it's fine. You tweaked something in your editor, and now the code and the artifacts disagree. Bring them back in sync in whichever direction is true:
- **The code is now correct, the spec is stale.** Update the delta spec (and tasks, if relevant) to describe the behavior you actually shipped. The spec should match reality before you archive, because archiving merges the spec into your source of truth.
- **The spec is correct, the code drifted.** Keep building or fixing until the code matches the spec.
A fast way to surface mismatches is `/opsx:verify`: it reads your artifacts and your code and tells you where they diverge. Treat its output as a to-do list for reconciliation, then archive once they agree.
The principle: at archive time, your specs become the truth of record. So before you archive, make the specs honest about what the code does. Manual edits are welcome; just don't let them quietly desync the spec.
## Refining a proposal you're not happy with
If a generated proposal misses the mark, you have three good moves:
- **Iterate in place.** Tell the AI what's off ("the scope is too broad, drop the admin features") and let it revise. Cheapest and usually right.
- **Explore first, then re-propose.** If the problem is that the idea itself is unclear, step back to `/opsx:explore`, think it through, and let a sharper proposal come out of that. See [Explore First](explore.md).
- **Start fresh.** If the intent has fundamentally changed, a new change can be clearer than patching the old one.
That last move has its own decision guide, next.
## When to update vs. start a new change
Short version: **update when it's the same work refined; start new when the intent fundamentally changed or the scope exploded into different work.**
- Same goal, better approach? Update.
- Scope narrowing (ship the MVP now, more later)? Update, then archive, then a new change for phase two.
- The problem itself changed ("add dark mode" became "build a full theming system")? New change.
There's a full flowchart and worked examples in [Workflows: When to Update vs Start Fresh](workflows.md#when-to-update-vs-start-fresh) and a deeper treatment in [OPSX: When to Update vs. Start Fresh](opsx.md#when-to-update-vs-start-fresh).
## A note on tasks
`tasks.md` is a living checklist, not a frozen plan. As you implement, you can add tasks you discover, remove ones that turned out unnecessary, or reorder them. The AI checks items off as it completes them during `/opsx:apply`, and it resumes from the first unchecked task if you come back later. Editing the list mid-flight is expected.
## Where to go next
- [Workflows](workflows.md) - patterns, plus the update-vs-new decision guide
- [Explore First](explore.md) - the place to step back to when an idea needs rethinking
- [Commands](commands.md) - `/opsx:continue`, `/opsx:apply`, and `/opsx:verify` in detail
- [Concepts: Artifacts](concepts.md#artifacts) - what each artifact is for
+215
View File
@@ -0,0 +1,215 @@
# Examples & Recipes
Real changes, start to finish. Each recipe shows the commands you'd type and what you'd see back, so you can match your situation to a pattern and copy it. These use the default **core** commands (`propose`, `explore`, `apply`, `sync`, `archive`); where the expanded set helps, it's noted.
A reminder before you start: slash commands like `/opsx:propose` go in your **AI assistant's chat**, and `openspec` commands go in your **terminal**. If that's new, read [How Commands Work](how-commands-work.md) first. In the transcripts below, `You:` and `AI:` are the chat, and lines starting with `$` are the terminal.
> **Not sure what you're building yet?** Most of these recipes are sharper if you start with `/opsx:explore` to think it through first. [Recipe 3](#recipe-3-exploring-before-you-commit) shows it in action, and the [Explore First](explore.md) guide makes the full case.
## Recipe 1: A small feature, the fast path
**When to use it:** you know what you want, and it's a contained piece of work. This is the most common recipe.
The whole thing is three commands. Propose, build, archive.
```text
You: /opsx:propose add-logout-button
AI: Created openspec/changes/add-logout-button/
✓ proposal.md — why and what
✓ specs/ — the new requirement and its scenarios
✓ design.md — technical approach
✓ tasks.md — implementation checklist
Ready for implementation. Run /opsx:apply.
```
Now read the plan. Open the proposal and the delta spec. This is the moment OpenSpec is built for: catching a wrong assumption while it's still one paragraph, not 400 lines of code. Edit any artifact directly if something's off, then continue.
```text
You: /opsx:apply
AI: Working through tasks...
✓ 1.1 Add logout button to header
✓ 1.2 Clear session on click
✓ 1.3 Add confirmation dialog
All tasks complete!
You: /opsx:archive
AI: Archiving add-logout-button...
✓ Merged specs into openspec/specs/auth/spec.md
✓ Moved to openspec/changes/archive/2026-06-22-add-logout-button/
Done. Ready for the next change.
```
That's it. The logout behavior is now part of your specs, and the change is filed away with its full context.
## Recipe 2: A bug fix
**When to use it:** something is broken and you want the fix recorded as a deliberate change to behavior, not a mystery commit.
Bug fixes work exactly like features. The difference is in how you frame the proposal: describe the *correct* behavior, not just "fix the bug."
```text
You: /opsx:propose fix-login-redirect-loop
AI: Created openspec/changes/fix-login-redirect-loop/
The proposal captures the current broken behavior and the
intended behavior. The delta spec MODIFIES the redirect
requirement so it's now precise and testable.
Ready for implementation.
```
Because the fix lands as a `MODIFIED` requirement with a fresh scenario, the next person (or the next AI session) sees not just that you fixed it, but what "correct" means. Then `/opsx:apply` and `/opsx:archive` as usual.
Tip: for a fix, a good scenario is the regression test in prose. "GIVEN a logged-out user, WHEN they submit valid credentials, THEN they land on the dashboard and are not redirected again." Write that, and the implementation has a clear target.
## Recipe 3: Exploring before you commit
**When to use it:** you have a problem but not yet a plan. You're not sure what to build, or which approach is right.
Start with `/opsx:explore`. It's a thinking partner with no structure and no artifacts created. It reads your codebase and helps you decide.
```text
You: /opsx:explore
AI: What would you like to explore?
You: Page loads feel slow but I don't know where the time goes.
AI: Let me look... I found three likely culprits:
1. Large unoptimized images on the product list
2. Synchronous data fetching that blocks render
3. Re-renders triggered by context changes
Which should we tackle first?
You: The data fetching one.
You: /opsx:propose optimize-product-list-fetching
AI: Created the change, with a proposal informed by what we just
found. Ready for implementation.
```
Exploration clarifies your thinking *before* you spend a change on it. When the insight crystallizes, propose, and the AI carries the context forward.
## Recipe 4: Juggling two changes at once
**When to use it:** you're mid-feature and an urgent fix jumps the queue.
Changes are independent folders, so parallel work doesn't conflict. Start the fix, ship it, then return to the feature right where you left off.
```text
You: I'm partway through add-dark-mode, but I need to fix a login bug now.
You: /opsx:propose fix-login-redirect
AI: Created openspec/changes/fix-login-redirect/. Ready for implementation.
You: /opsx:apply
AI: Implemented the fix. All tasks complete.
You: /opsx:archive
AI: ✓ Archived fix-login-redirect.
You: Back to dark mode.
You: /opsx:apply add-dark-mode
AI: Resuming add-dark-mode. Picking up at task 2.3: Update Header...
```
Naming the change in `/opsx:apply add-dark-mode` is how you point the AI at a specific change when more than one is active. Because tasks track completion in `tasks.md`, the AI knows exactly where you stopped.
When several changes are done at once, the expanded `/opsx:bulk-archive` files them together and resolves spec conflicts by checking what's actually implemented. See [Workflows](workflows.md#parallel-changes).
## Recipe 5: A refactor with no behavior change
**When to use it:** you're restructuring code, and externally visible behavior should stay identical.
This is the interesting case, because a pure refactor has *nothing to add to your specs*. The behavior contract doesn't change; only the implementation does. So the work lives in the design and tasks, and the spec delta is empty or absent.
```text
You: /opsx:propose refactor-payment-module
AI: Created the change. The proposal states the goal (split the
payment module, no behavior change) and the design captures
the new structure. No spec changes, since behavior is identical.
Ready for implementation.
```
When you archive a change that doesn't touch specs, you can tell the terminal command to skip the spec step:
```bash
$ openspec archive refactor-payment-module --skip-specs
```
The same flag is handy for tooling, CI, and docs-only changes. The principle: specs describe behavior, so if behavior didn't change, the spec shouldn't either. See [Concepts](concepts.md#what-a-spec-is-and-is-not).
## Recipe 6: Step-by-step control (expanded commands)
**When to use it:** a complex or risky change where you want to review each artifact before moving on.
The core `/opsx:propose` drafts everything at once. When you'd rather go one step at a time, turn on the expanded commands:
```bash
$ openspec config profile # select the expanded workflows
$ openspec update # apply them to this project
```
Now you can scaffold and build incrementally:
```text
You: /opsx:new add-2fa
AI: Created openspec/changes/add-2fa/. Ready to create: proposal.
You: /opsx:continue
AI: Created proposal.md. Now available: specs, design.
You: /opsx:continue
AI: Created specs/auth/spec.md. Now available: design.
```
Review each artifact as it lands, edit freely, and continue when you're happy. When you want the rest drafted in one go, `/opsx:ff` fast-forwards through the remaining planning artifacts. Before archiving, `/opsx:verify` checks that the implementation actually matches the specs. See [Workflows](workflows.md#opsxff-vs-opsxcontinue).
## Recipe 7: Learning the whole loop hands-on
**When to use it:** you've installed OpenSpec and want to *feel* the workflow on your own code, not a toy example.
Turn on the expanded commands (see Recipe 6), then:
```text
You: /opsx:onboard
AI: Welcome to OpenSpec! I'll walk you through a complete change
using your actual codebase. Let me scan for a small, safe
improvement we can make together...
```
`/opsx:onboard` finds a real (small) improvement, creates a change for it, implements it, and archives it, narrating every step. It takes 15 to 30 minutes and leaves you with a real change you can keep or discard. It's the gentlest way to learn. See [Commands](commands.md#opsxonboard).
## Checking your work from the terminal
Any time, from your terminal, you can inspect the state of things:
```bash
$ openspec list # active changes
$ openspec show add-dark-mode # one change in detail
$ openspec validate add-dark-mode # check structure
$ openspec view # interactive dashboard
```
These are read-and-inspect tools. The proposing and building still happen through slash commands in chat. Full details in the [CLI reference](cli.md).
## Where to go next
- [Explore First](explore.md): the recommended way to start when you're unsure
- [Workflows](workflows.md): the patterns above, with decision guidance on when to use each
- [Commands](commands.md): every slash command in detail
- [Getting Started](getting-started.md): the canonical first-change walkthrough
- [Concepts](concepts.md): why the pieces fit together the way they do
+134
View File
@@ -0,0 +1,134 @@
# Using OpenSpec in an Existing Project
**You do not document your whole codebase to start. You write specs only for what you're about to change.** That's the single most important thing to know about adopting OpenSpec on an existing project, and it's why OpenSpec is built brownfield-first.
A common worry sounds like this: "My app is 80,000 lines old. Do I have to write specs for all of it before OpenSpec is useful?" No. You'd hate that, and so would we. OpenSpec grows your specs one change at a time. Your first change documents the slice it touches, the next change documents its slice, and over months your specs fill in naturally around the work you actually do.
This guide shows how to start on day one without boiling the ocean.
## The thirty-second version
```bash
$ cd your-existing-project
$ openspec init # adds openspec/ and your AI tool's commands
```
Then, in your AI chat:
```text
/opsx:explore # optional: have the AI read the area you'll touch
/opsx:propose <a real, small change you actually need>
/opsx:apply
/opsx:archive
```
Your specs now describe exactly the part of the system that change touched, and nothing more. That's correct. You're done worrying about the other 80,000 lines.
## Why delta-first is the whole trick
OpenSpec changes are written as **deltas**: `ADDED`, `MODIFIED`, `REMOVED`. A delta describes what's changing relative to current behavior, not the entire system.
This is exactly what brownfield work needs. You're rarely building from nothing. You're adding a field, fixing a redirect, tightening a timeout. A delta lets you specify that one change precisely without first writing a 40-page spec of everything around it.
So your `openspec/specs/` directory doesn't start full and complete. It starts nearly empty and accumulates. Each archived change merges its delta in. The spec for `auth/` becomes thorough only after you've made several auth changes, which is exactly when you want it thorough.
If you want the deeper mechanics, see [Concepts: Delta Specs](concepts.md#delta-specs).
## Your first change on a real codebase
Pick something small and real. Not a toy, not a rewrite. A change you were going to make this week anyway. Small first changes teach you the workflow with low stakes.
**Step 1: Let the AI read the relevant area.** This is where `/opsx:explore` earns its keep on an unfamiliar or large codebase. Point it at the part you're about to touch and let it map how things work before proposing anything.
```text
You: /opsx:explore
AI: What would you like to explore?
You: I need to add rate limiting to our public API, but I'm not sure
how requests currently flow through the middleware.
AI: Let me trace it... [reads the router, middleware stack, and config]
Requests hit Express, pass through auth middleware, then your
controllers. There's no rate-limiting layer today. The cleanest
insertion point is a middleware right after auth. Want me to scope it?
```
Notice the AI now understands your actual structure, so the proposal it writes will fit your code, not a generic template. On a big codebase, this single habit saves the most pain. See [Explore First](explore.md).
**Step 2: Propose the change.** The proposal and its delta spec capture just this change.
```text
You: /opsx:propose add-api-rate-limiting
```
**Step 3: Build and archive** with `/opsx:apply` and `/opsx:archive`, same as any change. After archiving, you have a real spec for your rate-limiting behavior, born from a change you needed anyway.
## Prefer a guided tour? Use onboard
If you'd rather watch the whole loop happen on your own code with narration, the expanded command `/opsx:onboard` does exactly that: it scans your codebase for a small, safe improvement, then walks you through proposing, building, and archiving it, explaining each step.
Turn on the expanded commands first:
```bash
$ openspec config profile # select the expanded workflows
$ openspec update # apply them to this project
```
Then in chat:
```text
/opsx:onboard
```
It's the gentlest possible introduction on a real project, and it leaves you with a genuine (small) change you can keep or discard. See [Commands: `/opsx:onboard`](commands.md#opsxonboard).
## "But I already have requirements docs"
Maybe you have a PRD, an SRS, a formal spec, even TLA+ models. Good. You don't import them wholesale, and you don't throw them away either.
Treat existing docs as **source material for exploration**, not as specs to convert. When you start a change, paste or point the AI at the relevant section, and let it shape a focused OpenSpec delta from it. The delta captures the behavior you're changing now, in OpenSpec's testable requirement-and-scenario form. Your original documents stay where they are as background.
The honest reason: OpenSpec specs are deliberately behavior-first and scoped to changes. A 40-page PRD is a different artifact with a different job. Forcing a one-time bulk conversion tends to produce a large, stale spec nobody trusts. Letting specs grow from real changes keeps them accurate.
```text
You: /opsx:explore
You: Here's the section of our PRD about checkout. I'm implementing the
"guest checkout" requirement next.
[paste the relevant requirement]
AI: [reads it, asks clarifying questions, then helps scope a change]
You: /opsx:propose add-guest-checkout
```
## Organizing specs in a big codebase
Specs live under `openspec/specs/`, grouped by **domain**: a logical area that matches how your team thinks about the system. You don't have to design the whole taxonomy up front. Create a domain folder when your first change in that area needs one.
Common ways to slice domains:
- **By feature area:** `auth/`, `payments/`, `search/`
- **By component:** `api/`, `frontend/`, `workers/`
- **By bounded context:** `ordering/`, `fulfillment/`, `inventory/`
Pick whatever makes a newcomer nod. You can refine later. See [Concepts: Specs](concepts.md#specs).
## Monorepos and work that spans repos
For a monorepo, the simplest model is one `openspec/` directory at the repo root, with domains that map to your packages or services. That covers most teams.
If your work genuinely spans **multiple repositories** (or several packages you treat as separate), OpenSpec has a beta **stores** feature: planning lives in its own standalone repo that any of your code repos can reference, so the plan does not have to live inside one repo's `openspec/` folder. It's beta, so treat its commands and state as evolving. Start with the [Stores User Guide](stores-beta/user-guide.md) for the mental model and the smallest useful path.
## A few honest cautions
- **Resist the urge to back-fill everything.** Writing specs for code you aren't changing feels productive and usually isn't. Those specs go stale, because nothing forces them to track reality. Let real changes drive your specs.
- **Keep early changes small.** Your first few changes are as much about learning the rhythm as shipping. A tight scope makes the loop fast and the lessons cheap.
- **Commit `openspec/` to git.** Your specs and archive belong in version control alongside the code they describe.
- **Give the AI context.** On a large codebase with strong conventions, fill in `openspec/config.yaml`'s `context:` so every proposal respects your stack and patterns. See [Customization](customization.md#project-configuration).
## Where to go next
- [Explore First](explore.md) - the key habit for understanding code before you change it
- [Getting Started](getting-started.md) - the full first-change walkthrough
- [Editing & Iterating on a Change](editing-changes.md) - adjusting a change as you learn
- [Concepts: Delta Specs](concepts.md#delta-specs) - why deltas make brownfield work clean
- [Customization](customization.md) - teach OpenSpec your project's conventions
+121
View File
@@ -0,0 +1,121 @@
# Explore First
**`/opsx:explore` is your thinking partner. Reach for it whenever you have a problem but not yet a plan.** It investigates your codebase, weighs options with you, and clarifies what you actually want, all before a single artifact or line of code is created. When the picture is clear, it hands off to `/opsx:propose`.
If you take one habit from these docs, take this one: **when you're not sure, explore before you propose.**
Here's why that matters. AI coding assistants are eager. Ask vaguely and they'll confidently build *something*, just maybe not the thing you needed. Explore is the cure. It's a no-stakes conversation where you and the AI figure out the right move together, so that by the time you propose, you're proposing the right thing.
## When to explore
Explore is the right first step more often than people expect. Use it when any of these is true:
- You know the *problem* but not the *solution*. ("Pages feel slow." "Auth is a mess." "We keep getting duplicate orders.")
- You're choosing between approaches and want the tradeoffs laid out against your actual code.
- You're new to a codebase and need to understand how something works before you change it.
- The requirements are fuzzy and you want to sharpen them before committing.
- You suspect the work is bigger or smaller than it looks and want to scope it honestly.
Skip explore only when you already know exactly what you want and how. In that case go straight to [`/opsx:propose`](commands.md#opsxpropose).
## What it does (and doesn't)
Explore is a **conversation**, not a generator.
**It does:**
- Read and search your codebase to answer real questions.
- Compare options and name the tradeoffs of each.
- Draw diagrams to make a design legible.
- Help you narrow a vague idea into a concrete, buildable scope.
- Transition to `/opsx:propose` when you're ready.
**It does not:**
- Create a change folder.
- Write any artifacts (no proposal, specs, design, or tasks).
- Write or modify code.
That's the point. Exploring costs you nothing and commits you to nothing. You can explore three dead ends, learn something from each, and only then propose the path that survived.
## It's already installed
Good news: `/opsx:explore` ships in the default **core** profile, right alongside `propose`, `apply`, `sync`, and `archive`. You don't need to enable anything. If OpenSpec is set up in your project, explore is ready in your AI chat. (As with all `/opsx:*` commands, you type it in your assistant's chat, not the terminal. See [How Commands Work](how-commands-work.md).)
## A full example
Watch how a vague worry becomes a sharp, buildable change.
```text
You: /opsx:explore
AI: What would you like to explore?
You: Our checkout sometimes creates duplicate orders. I don't know why
and I don't know how to fix it safely.
AI: Let me dig into the checkout path...
[reads the order service, the payment webhook handler, and the
client submit logic]
Here's what I found. There are two ways a duplicate can happen:
1. The client can submit twice (double-click, retry on slow network).
Nothing debounces it.
2. The payment webhook can fire more than once, and the handler
creates an order each time. There's no idempotency key.
Cause #2 is the dangerous one: it can charge and fulfill twice.
Three ways to fix it, roughly in order of robustness:
- Idempotency key on the order-creation endpoint (handles both causes)
- Dedup on the webhook by payment-intent id (handles #2 only)
- Client-side debounce (handles #1 only, papers over the real bug)
Given your code already stores the payment-intent id, the
idempotency-key approach is a small change with the biggest payoff.
Want me to scope that?
You: Yes, let's do the idempotency key.
You: /opsx:propose add-order-idempotency-key
AI: Created openspec/changes/add-order-idempotency-key/, with a proposal
and delta spec grounded in what we just found. Ready for implementation.
```
Notice what happened. The starting point was "something is wrong and I'm scared to touch it." Twenty seconds of exploration turned that into a named root cause, three ranked options, a recommendation tied to the existing code, and a precise change. The proposal that follows is sharp because the thinking happened first.
## Handing off to propose
Explore doesn't archive into anything. When you're ready, you simply start a change, and the AI carries the context from your conversation into the artifacts.
```text
explore ──► propose ──► apply ──► archive
(think) (agree) (build) (record)
```
You can say it in plain language ("let's turn this into a change") or run `/opsx:propose <name>` directly. Either way, the exploration you just did becomes the foundation of the proposal, not throwaway chat.
If you use the expanded command set, explore can hand off to `/opsx:new` instead, for step-by-step artifact creation. See [Workflows](workflows.md).
## Tips for a good exploration
- **Bring the problem, not the solution.** "Logins feel slow" gives the AI room to investigate. "Add a Redis cache" pre-commits you to an answer you haven't tested yet.
- **Ask for the tradeoffs out loud.** "What are the downsides of each option?" gets you a more honest comparison.
- **Let it read first.** The best explorations start with the AI actually looking at your code, not guessing. Point it at the relevant area if it helps.
- **It's okay to bail.** If exploration reveals the idea isn't worth it, that's a win. You learned it cheaply.
- **Explore again mid-change.** Stuck during `/opsx:apply`? You can step back and explore a sub-problem, then return.
## The honest tradeoffs
**What you gain:** explore catches wrong turns at the cheapest possible moment, before any artifact exists. It's especially powerful in unfamiliar code, where the AI's ability to read and summarize the system saves you an afternoon of spelunking.
**What it costs:** a little patience. Explore is a conversation, so it's slower than firing off `/opsx:propose` and hoping. For work you genuinely understand already, that extra step is pure overhead, and you should skip it.
The rule of thumb: the fuzzier the task, the more explore pays off. The clearer the task, the more you can skip straight to proposing.
## Where to go next
- [Commands: `/opsx:explore`](commands.md#opsxexplore): the precise reference
- [Workflows](workflows.md): explore as part of the everyday loop
- [Examples & Recipes](examples.md#recipe-3-exploring-before-you-commit): explore in a full walkthrough
- [Getting Started](getting-started.md): the first-change guide, exploration included
+155
View File
@@ -0,0 +1,155 @@
# FAQ
Quick answers to the questions people ask most. If your question is really a "something is broken" question, [Troubleshooting](troubleshooting.md) is the better page. If you want a term defined, see the [Glossary](glossary.md).
## The basics
### What is OpenSpec, in one sentence?
A lightweight layer that gets you and your AI coding assistant to agree on what to build, in writing, before any code is written.
### Why would I want that?
Because AI assistants are confident even when they're wrong. When the requirements live only in a chat thread, the AI fills gaps with guesses, and you find out after the code exists. OpenSpec moves the agreement earlier, where mistakes are cheap to fix. See [Core Concepts at a Glance](overview.md) for the full case.
### Do I have to use it for everything?
No. Use it where agreement matters, which is most non-trivial work. For a one-character typo fix, the ceremony probably isn't worth it, and that's fine.
### Can I use it on a big existing codebase, or only new projects?
Existing codebases are the main event. OpenSpec is brownfield-first: you do not document your whole app up front. You write specs only for what each change touches, and your specs fill in over time around the work you actually do. There's a dedicated guide: [Using OpenSpec in an Existing Project](existing-projects.md).
### Is it tied to one AI tool?
No. OpenSpec works with 25+ assistants, including Claude Code, Cursor, Windsurf, GitHub Copilot, Gemini CLI, Codex, and more. The full list and per-tool details are in [Supported Tools](supported-tools.md).
## Running commands
### Where do I type `/opsx:propose`?
In your AI assistant's chat, not your terminal. This is the single most common point of confusion, so it has its own page: [How Commands Work](how-commands-work.md). Short version: `openspec ...` runs in the terminal, `/opsx:...` runs in chat.
### How do I "start interactive mode"?
There isn't a separate mode to start. You open your AI assistant like normal and type a slash command into its chat. The slash command is how you "enter" OpenSpec. (The one genuinely interactive terminal feature is `openspec view`, a dashboard for browsing specs and changes.) Full explanation in [How Commands Work](how-commands-work.md).
### I typed a slash command and nothing happened. Why?
Most likely you typed it in the terminal instead of your AI chat, or the commands aren't installed yet. Run `openspec update` in your project, restart your assistant, then try typing `/opsx` in chat and watch for autocomplete. [Troubleshooting](troubleshooting.md#commands-dont-show-up) has the full checklist.
### Why is the syntax `/opsx:propose` in one tool and `/opsx-propose` in another?
Each AI tool surfaces custom commands a little differently. The intent is identical; only the punctuation changes. Type a slash in your chat and the autocomplete shows you the form your tool expects. The per-tool table is in [How Commands Work](how-commands-work.md#slash-command-syntax-by-tool).
### What's the difference between a skill and a command?
Both are files OpenSpec writes so your assistant can run the workflow. Skills (`.../skills/openspec-*/SKILL.md`) are the newer cross-tool standard; commands (`.../commands/opsx-*`) are the older per-tool slash files. You don't need to pick. You just type the slash command, and OpenSpec installs whichever your tool uses.
## The workflow
### Where should I start if I'm not sure what to build?
With `/opsx:explore`. It's a no-stakes thinking partner that reads your codebase, lays out options, and turns a fuzzy problem into a concrete plan, all before any change or code exists. It's in the default profile, so it's always available. When the plan is clear, it hands off to `/opsx:propose`. This is the single best habit to form, because it stops an eager AI from confidently building the wrong thing. See [Explore First](explore.md).
### What's the simplest possible flow?
```text
/opsx:explore (optional) then /opsx:propose <what you want> then /opsx:apply then /opsx:archive
```
Explore to think it through, propose to draft the plan, apply to build it, archive to file it away. Skip explore when you already know exactly what you want.
### What's the difference between `/opsx:propose` and `/opsx:new`?
`/opsx:propose` is the default one-step command: it creates the change and drafts all the planning artifacts at once. `/opsx:new` is part of the expanded command set and only scaffolds an empty change, leaving you to create artifacts one at a time with `/opsx:continue` (or all at once with `/opsx:ff`). Use propose unless you want step-by-step control. See [Commands](commands.md).
### What are `core` and expanded profiles?
A profile decides which slash commands get installed. **Core** (the default) gives you `propose`, `explore`, `apply`, `sync`, `archive`. The **expanded** set adds `new`, `continue`, `ff`, `verify`, `bulk-archive`, and `onboard` for finer control. Switch with `openspec config profile`, then apply with `openspec update`.
### Do I need to run `/opsx:sync`?
Usually not. Sync merges a change's delta specs into your main specs, and `/opsx:archive` will offer to do it for you. Run sync manually only when you want the specs merged before archiving, for example on a long-running change. See [Commands](commands.md#opsxsync).
### How do I edit a proposal, spec, or task after I've started?
Just edit the file. Every artifact is plain Markdown in `openspec/changes/<name>/`, and there's no locked phase or special edit mode. Change it by hand, or ask your AI to revise it ("update the design to use a queue"), then keep going. The AI always works from the current file contents. Full guide: [Editing & Iterating on a Change](editing-changes.md).
### Can I go back and change the plan after implementing some of it?
Yes, at any time. The workflow is fluid, so review and editing aren't phases you get locked out of. Edit the artifact, then continue. If you want a structured check that the code still matches the plan, run `/opsx:verify`. See [Editing & Iterating on a Change](editing-changes.md#how-do-i-go-back-to-review-after-implementing).
### I edited the code by hand. How do I reconcile it with the spec?
Bring them back in sync before you archive, since archiving makes your specs the record of truth. If the code is now correct, update the delta spec to match what you shipped; if the spec is correct, keep building until the code agrees. `/opsx:verify` surfaces the mismatches. See [Editing & Iterating on a Change](editing-changes.md#i-edited-the-code-by-hand-how-do-i-reconcile-that-with-openspec).
### When should I update an existing change versus start a new one?
Update when it's the same work, refined. Start fresh when the intent fundamentally changed or the scope exploded into different work. There's a decision flowchart and examples in [Workflows](workflows.md#when-to-update-vs-start-fresh).
### What if my session runs out of context, or requirements change mid-implementation?
This is where specs earn their keep. Because the plan lives in files (not only in chat history), you can clear your context, start a fresh AI session, and pick up with `/opsx:apply`; it reads the artifacts and resumes from the first unchecked task. If requirements change, edit the artifacts to match the new reality and continue. Keeping a clean context window also produces better results; clear it before implementation.
### Should I commit the `openspec/` folder to git?
Yes. Your specs, active changes, and archive are part of your project's history. Commit them like any other source. The archive in particular becomes a durable record of why your system works the way it does.
## Specs and changes
### What goes in a spec versus a design?
A spec describes observable behavior: what the system does, its inputs, outputs, and error conditions. A design describes how you'll build it: the technical approach, architecture decisions, file changes. If implementation could change without changing externally visible behavior, it belongs in the design, not the spec. [Concepts](concepts.md#what-a-spec-is-and-is-not) goes deeper.
### What's a delta spec?
A spec that describes only what's changing, using `ADDED`, `MODIFIED`, and `REMOVED` sections, rather than restating the whole spec. It's how OpenSpec handles edits to existing systems cleanly. See [Concepts](concepts.md#delta-specs).
### Where do archived changes go?
To `openspec/changes/archive/YYYY-MM-DD-<name>/`, with all artifacts preserved. Nothing is deleted; the change just moves out of your active list.
## Configuration and customization
### How do I tell the AI about my tech stack?
Put it in `openspec/config.yaml` under `context:`. That text is injected into every planning request, so the AI always knows your stack and conventions. See [Customization](customization.md#project-configuration).
### Can I generate specs in a language other than English?
Yes. Add a language instruction to your config's `context:`. [Multi-Language](multi-language.md) has copy-paste snippets for several languages.
### Can I change the workflow itself?
Yes, with custom schemas. A schema defines which artifacts exist and how they depend on each other. Fork the default with `openspec schema fork spec-driven my-workflow`, then edit it. See [Customization](customization.md#custom-schemas).
## Models, privacy, and upgrades
### Which AI model should I use?
OpenSpec works best with high-reasoning models. The README recommends models like Codex 5.5 and Opus 4.7 for both planning and implementation. Also keep your context window clean: clear it before implementation for best results.
### Does OpenSpec collect data?
It collects anonymous usage stats: command names and version only. No arguments, paths, content, or personal data, and it's off automatically in CI. Opt out with `export OPENSPEC_TELEMETRY=0` or `export DO_NOT_TRACK=1`.
### How do I upgrade?
Two steps. Upgrade the package (`npm install -g @fission-ai/openspec@latest`), then run `openspec update` inside each project to refresh the generated skills and commands.
### How do I uninstall OpenSpec?
There's no uninstall command, because it's just a global package plus files in your project. Remove the package (`npm uninstall -g @fission-ai/openspec`), and optionally delete the `openspec/` directory and the generated tool files. Step-by-step, including what's safe to keep, is in [Installation: Uninstalling](installation.md#uninstalling).
## Getting help
### Where do I ask questions or report bugs?
- **Discord:** [discord.gg/YctCnvvshC](https://discord.gg/YctCnvvshC)
- **GitHub Issues:** [github.com/Fission-AI/OpenSpec/issues](https://github.com/Fission-AI/OpenSpec/issues)
- **From your terminal:** `openspec feedback "your message"` opens a GitHub issue for you.
### These docs are wrong or confusing. What do I do?
Tell us, or fix it. Documentation PRs are welcome and valued. Open an issue or send a pull request.
+36 -2
View File
@@ -1,6 +1,30 @@
# Getting Started
This guide explains how OpenSpec works after you've installed and initialized it. For installation instructions, see the [main README](../README.md#quick-start).
This guide explains how OpenSpec works after you've installed and initialized it. For installation instructions, see the [main README](../README.md#quick-start) or the [Installation guide](installation.md). New to the whole docs set? The [documentation home](README.md) maps everything.
> **Where do I type these commands?** Two places, and mixing them up is the most common early stumble.
>
> - `openspec ...` commands (like `openspec init`) run in your **terminal**.
> - `/opsx:...` commands (like `/opsx:propose`) run in your **AI assistant's chat**, the same box where you'd ask it to write code.
>
> There's no separate "interactive mode" to start. You just type the slash command in chat and your assistant takes it from there. Full explanation: [How Commands Work](how-commands-work.md).
## Your First Five Minutes
The whole loop, with each step labeled by where it happens:
```text
TERMINAL $ npm install -g @fission-ai/openspec@latest
TERMINAL $ cd your-project && openspec init
AI CHAT /opsx:explore (optional: think it through first)
AI CHAT /opsx:propose add-dark-mode (AI drafts the plan; you review it)
AI CHAT /opsx:apply (AI builds it)
AI CHAT /opsx:archive (specs updated, change filed away)
```
Two terminal steps to set up, then you live in chat. The rest of this guide unpacks what each step does and what you'll see.
> **Not sure what to build yet? Start with `/opsx:explore`.** It's a no-stakes thinking partner that reads your codebase, weighs options, and sharpens a fuzzy idea into a concrete plan, all before any artifact or code exists. When the picture is clear, it hands off to `/opsx:propose`. This is the single best habit for working with an AI that will otherwise confidently build the wrong thing. See the [Explore guide](explore.md).
## How It Works
@@ -9,9 +33,12 @@ OpenSpec helps you and your AI coding assistant agree on what to build before an
**Default quick path (core profile):**
```text
/opsx:propose ──► /opsx:apply ──► /opsx:sync ──► /opsx:archive
/opsx:explore ──► /opsx:propose ──► /opsx:apply ──► /opsx:sync ──► /opsx:archive
(optional)
```
Start with `/opsx:explore` when you're figuring out what to do, or jump straight to `/opsx:propose` when you already know. Explore is in the default profile, so it's always there when you want it.
**Expanded path (custom workflow selection):**
```text
@@ -247,7 +274,14 @@ openspec view
## Next Steps
- [Explore First](explore.md) - Use `/opsx:explore` to think through an idea before you commit
- [Using OpenSpec in an Existing Project](existing-projects.md) - Start on a large brownfield codebase
- [Editing & Iterating on a Change](editing-changes.md) - Update artifacts, go back, reconcile manual edits
- [Core Concepts at a Glance](overview.md) - The whole mental model on one page
- [Examples & Recipes](examples.md) - Real changes, start to finish
- [Workflows](workflows.md) - Common patterns and when to use each command
- [Commands](commands.md) - Full reference for all slash commands
- [Concepts](concepts.md) - Deeper understanding of specs, changes, and schemas
- [Customization](customization.md) - Make OpenSpec work your way
- [Stores](stores-beta/user-guide.md) - Planning that spans repos or teams? Keep it in its own repo (beta)
- [FAQ](faq.md) and [Troubleshooting](troubleshooting.md) - When you get stuck
+91
View File
@@ -0,0 +1,91 @@
# Glossary
Every OpenSpec term in one place, defined in plain language. Skim it once and the rest of the docs read faster.
Terms are grouped by topic, then alphabetized within each group.
## The core nouns
**Spec.** A document describing how part of your system behaves. Specs live in `openspec/specs/`, are organized by domain, and are made of requirements and scenarios. The spec is the agreed-upon answer to "what does this software do?" See [Concepts](concepts.md#specs).
**Source of truth.** The `openspec/specs/` directory as a whole. It holds the current, agreed-upon behavior of your system. Changes propose edits to it; archiving applies them.
**Change.** One unit of work, packaged as a folder under `openspec/changes/<name>/`. A change holds everything about that work: its proposal, design, tasks, and the spec edits it introduces. One change, one feature or fix.
**Artifact.** A document inside a change. The standard artifacts are the proposal, the delta specs, the design, and the tasks. They're created in dependency order and feed into each other.
**Delta spec.** A spec inside a change that describes only what's changing, using `ADDED`, `MODIFIED`, and `REMOVED` sections, rather than restating the entire spec. This is what lets OpenSpec edit existing systems cleanly. See [Concepts](concepts.md#delta-specs).
**Domain.** A logical grouping for specs, like `auth/`, `payments/`, or `ui/`. You choose domains that match how you think about your system.
## Inside a spec
**Requirement.** A single behavior the system must have, usually written with an RFC 2119 keyword: "The system SHALL expire sessions after 30 minutes." Requirements state the *what*, not the *how*.
**Scenario.** A concrete, testable example of a requirement in action, typically in Given/When/Then form. Scenarios make a requirement verifiable: you could write an automated test from one.
**RFC 2119 keywords.** The words MUST, SHALL, SHOULD, and MAY, which carry standardized meaning about how strict a requirement is. MUST and SHALL are absolute. SHOULD is recommended with room for exceptions. MAY is optional. The name comes from the internet standards document that defined them.
## The artifacts
**Proposal (`proposal.md`).** The *why* and *what* of a change: its intent, scope, and high-level approach. The first artifact you create.
**Design (`design.md`).** The *how*: technical approach, architecture decisions, and the files you expect to touch. Optional for simple changes.
**Tasks (`tasks.md`).** The implementation checklist, with checkboxes. The AI works through it during `/opsx:apply` and checks items off as it goes.
## The lifecycle
**Archive.** The act of finishing a change. Its delta specs merge into the main specs, and the change folder moves to `openspec/changes/archive/YYYY-MM-DD-<name>/`. After archiving, your specs describe the new reality. See [Concepts](concepts.md#archive).
**Sync.** Merging a change's delta specs into the main specs *without* archiving the change. Usually automatic (archive offers to do it), but available on its own as `/opsx:sync` for long-running changes. See [Commands](commands.md#opsxsync).
## Workflow and commands
**OPSX.** The current standard OpenSpec workflow, built around fluid actions instead of rigid phases. Its slash commands all start with `/opsx:`. See [OPSX Workflow](opsx.md).
**Slash command.** A command you type into your AI assistant's chat, like `/opsx:propose`. Slash commands drive the workflow. They are not terminal commands. See [How Commands Work](how-commands-work.md).
**Explore (`/opsx:explore`).** The thinking-partner command. It reads your codebase, compares options, and clarifies a fuzzy idea into a concrete plan, creating no artifacts and writing no code. The recommended starting point whenever you have a problem but not yet a plan. See [Explore First](explore.md).
**CLI.** The `openspec` program you run in your terminal. It sets up projects, lists and validates changes, opens the dashboard, and archives. The terminal half of OpenSpec. See [CLI](cli.md).
**Skill.** A folder of instructions (`.../skills/openspec-*/SKILL.md`) that your AI assistant auto-detects and follows. Skills are the emerging cross-tool standard for delivering the OpenSpec workflow to your assistant.
**Command file.** A per-tool slash command file (`.../commands/opsx-*`). The older delivery mechanism, still supported alongside skills. You rarely touch these directly.
**Profile.** The set of slash commands installed in your project. **Core** (the default) is `propose`, `explore`, `apply`, `sync`, `archive`. The **expanded** set adds `new`, `continue`, `ff`, `verify`, `bulk-archive`, `onboard`. Change it with `openspec config profile`.
**Delivery.** Whether OpenSpec installs skills, command files, or both for your tools. Configured globally and applied with `openspec update`.
## Customization
**Schema.** The definition of which artifacts a workflow has and how they depend on one another. The built-in default is `spec-driven` (proposal → specs → design → tasks). You can fork it or write your own. See [Customization](customization.md#custom-schemas).
**Template.** A Markdown file inside a schema that shapes what the AI generates for a given artifact. Editing a template changes the AI's output immediately, with no rebuild.
**Project config (`openspec/config.yaml`).** Per-project settings: the default schema, the `context:` injected into every planning request, and per-artifact `rules:`. The easiest way to teach OpenSpec about your stack and conventions. See [Customization](customization.md#project-configuration).
**Context injection.** Putting project background in `config.yaml`'s `context:` field so it's automatically added to every artifact the AI generates. More reliable than hoping the AI reads a separate file.
**Dependency graph.** The directed graph formed by artifact `requires:` relationships. It's a DAG (directed acyclic graph: arrows only point forward, never in a loop), and OpenSpec uses it to know what you can create next.
**Enablers, not gates.** The principle that artifact dependencies show what becomes *possible* next, not what's *required* next. You can revisit and edit any artifact at any time. See [Core Concepts at a Glance](overview.md#enablers-not-gates).
## Coordination across repos (beta)
These terms apply only if your planning spans more than one repo. They're in beta. Most users can ignore them. See the [Stores User Guide](stores-beta/user-guide.md).
**Store.** A standalone repo whose whole job is planning. It has the same `openspec/` shape you already know (specs and changes) plus a small identity file. You register it on your machine once, by name, and then any OpenSpec command can work in it from anywhere.
**Reference.** A declaration, in a code repo's `openspec/config.yaml`, of a store that repo draws on. References are read-only: the repo keeps its own root, and `openspec instructions` gains an index of the referenced store's specs, each with the exact command to fetch it.
**Working context.** What `openspec context` assembles for the current repo: its OpenSpec root plus every store it references, each with how to fetch it. The answer to "what am I working with?"
**Workset.** A personal, machine-local set of folders you open together (a store alongside the code repos you work on). Created explicitly with `openspec workset create`; nothing about those local paths is committed to the shared planning repo.
## See also
- [Core Concepts at a Glance](overview.md): the five ideas, on one page
- [Concepts](concepts.md): the long-form explanation
- [How Commands Work](how-commands-work.md): slash commands versus the CLI
+159
View File
@@ -0,0 +1,159 @@
# How Commands Work
**The one thing to know: OpenSpec has two kinds of commands, and they run in two different places.**
- `openspec ...` commands run in your **terminal**. (Example: `openspec init`.)
- `/opsx:...` commands run in your **AI assistant's chat**. (Example: `/opsx:propose`.)
If you ever type `/opsx:propose` into your terminal and nothing happens, this page is why. You are talking to the wrong half of OpenSpec. Slash commands are not terminal commands. They are instructions you give to your AI coding assistant, in the same chat box where you'd normally type "add a login form."
That single distinction is the most common stumbling block for new users, so let's make it crystal clear.
## The two halves
OpenSpec is one project wearing two hats.
**The CLI (terminal half).** A program named `openspec` that you install and run from your shell. It sets up your project, lists and validates changes, shows a dashboard, and archives finished work. You type these into iTerm, the VS Code terminal, PowerShell, anywhere you'd run `git` or `npm`.
```bash
openspec init # set up OpenSpec in this project
openspec list # see active changes
openspec view # open the interactive dashboard
```
**The slash commands (chat half).** Short commands like `/opsx:propose` and `/opsx:apply` that you type into your AI assistant. These tell the AI to follow the OpenSpec workflow: draft a proposal, write specs, build from the task list, archive when done. You type these into Claude Code, Cursor, Windsurf, Copilot, or whichever assistant you use.
```text
/opsx:propose add-dark-mode (typed in your AI chat)
/opsx:apply (typed in your AI chat)
/opsx:archive (typed in your AI chat)
```
Here's the mental model in one picture:
```text
YOUR TERMINAL YOUR AI ASSISTANT'S CHAT
┌──────────────────────┐ ┌──────────────────────────────┐
│ $ openspec init │ installs │ /opsx:propose add-dark-mode │
│ $ openspec list │ ──────────► │ /opsx:apply │
│ $ openspec view │ commands │ /opsx:archive │
└──────────────────────┘ & skills └──────────────────────────────┘
run openspec here run /opsx:* here
```
Notice the arrow. Running `openspec init` in your terminal is what *installs* the slash commands into your AI tool. The terminal half sets up the chat half. After that, day-to-day driving mostly happens in chat.
## "How do I start interactive mode?"
**There is no separate interactive mode to start.** This question comes up a lot, so it deserves a plain answer.
You don't enter a special OpenSpec mode. You just open your AI coding assistant like you always do, and type a slash command into the chat. The slash command *is* how you "enter" OpenSpec. Your assistant recognizes it, loads the matching OpenSpec skill, and starts following the workflow.
So the real instructions are:
1. Open your AI coding assistant (Claude Code, Cursor, Windsurf, and so on) in your project.
2. Type `/opsx:propose` in its chat, the same place you type any other request.
3. Watch the autocomplete: if OpenSpec is installed, you'll see `/opsx:propose`, `/opsx:apply`, and friends appear as you type the slash.
That's it. No mode to toggle, no daemon to launch, no separate window.
One thing that *is* genuinely interactive lives in the terminal: `openspec view`. It opens a dashboard for browsing your specs and changes. But that's a viewer, not the thing you propose and build with. The building happens through slash commands in chat.
## Why this split exists
It's worth understanding, because it explains why OpenSpec works with 25+ different AI tools.
The CLI is the **engine**. It knows the rules: what a change folder looks like, which artifacts depend on which, how to merge a delta spec into your source of truth. It's the same everywhere.
The slash commands are the **steering wheel**, and every AI tool has a slightly different one. Claude Code calls them commands. Cursor and Windsurf have their own formats. Some tools call them skills. When you run `openspec init`, OpenSpec generates the right kind of file for each tool you selected, so the same `/opsx:propose` intent works no matter which assistant you prefer.
The strength of this design: you learn the workflow once and carry it across tools. The tradeoff: the exact syntax of a command can differ slightly between tools, which is the next section.
## Slash command syntax by tool
The intent is identical everywhere. The punctuation differs. Use the form that matches your assistant.
| Tool | How you type it |
|------|-----------------|
| Claude Code | `/opsx:propose`, `/opsx:apply` |
| Cursor | `/opsx-propose`, `/opsx-apply` |
| Windsurf | `/opsx-propose`, `/opsx-apply` |
| GitHub Copilot (IDE) | `/opsx-propose`, `/opsx-apply` |
| Kimi CLI | skill-style, e.g. `/skill:openspec-propose` |
| Trae | skill-style, e.g. `/openspec-propose` |
Most tools use either the colon form (`/opsx:propose`) or the dash form (`/opsx-propose`). A few tools surface OpenSpec as named skills instead of slash commands; for those you invoke the skill by name. The full per-tool list, including exactly which files get written where, lives in [Supported Tools](supported-tools.md).
When in doubt, type a slash in your AI chat and look at the autocomplete. Your tool will show you the form it expects.
## How the commands got there: skills and commands
When you run `openspec init` (or `openspec update`), OpenSpec writes small files into your project so your AI tool can find the workflow. Depending on your tool and settings, these are **skills**, **commands**, or both.
- **Skills** live in places like `.claude/skills/openspec-*/SKILL.md`. They're the emerging cross-tool standard: a folder of instructions your assistant auto-detects.
- **Commands** live in places like `.claude/commands/opsx/<id>.md`. They're the older per-tool slash command files.
You don't have to care which one your tool uses. You just type the slash command and it works. But knowing these files exist helps when something goes wrong: if your commands vanish, it usually means these files are missing or stale, and `openspec update` regenerates them.
See [Supported Tools](supported-tools.md) for the exact paths per tool, and [Migration Guide](migration-guide.md) for how skills replaced the older command-only approach.
## Confirming it's installed
Quick checks, fastest first:
1. **Type a slash in your AI chat.** Start typing `/opsx` and watch for autocomplete suggestions. If they appear, you're set.
2. **Look for the files.** For Claude Code, check that `.claude/skills/` contains `openspec-*` folders. Other tools use their own directories ([Supported Tools](supported-tools.md) lists them).
3. **Re-run setup.** From your project root, run `openspec update`. This regenerates the skill and command files for whatever tools you configured.
4. **Restart your assistant.** Many tools scan for skills and commands at startup, so a fresh window can be the missing step.
## Which commands do I even have?
By default, OpenSpec installs the **core** set of slash commands:
- `/opsx:explore`: think through an idea with the AI before committing to a change (great first step when you're unsure)
- `/opsx:propose`: create a change and draft all its planning artifacts in one step
- `/opsx:apply`: build the change by working through its task list
- `/opsx:sync`: merge a change's spec updates into your main specs (usually automatic)
- `/opsx:archive`: finish a change and file it away
A good default rhythm: `explore` when you're figuring out what to do, then `propose`, `apply`, `archive`. The [Explore First](explore.md) guide explains why that opening step pays off.
There's also an **expanded** set for people who want finer control (`/opsx:new`, `/opsx:continue`, `/opsx:ff`, `/opsx:verify`, `/opsx:bulk-archive`, `/opsx:onboard`). You turn it on with `openspec config profile`, then apply it with `openspec update`.
New to all of this? `/opsx:onboard` (in the expanded set) walks you through a complete change on your own codebase, narrating each step. It's the friendliest possible introduction.
For what each command does in detail, see [Commands](commands.md). For when to reach for which, see [Workflows](workflows.md).
## A clean first run
Putting it together, here is the whole sequence with each step labeled by where it happens.
```text
TERMINAL $ npm install -g @fission-ai/openspec@latest
TERMINAL $ cd your-project
TERMINAL $ openspec init
(installs slash commands into your AI tool)
AI CHAT /opsx:explore
(optional: think the idea through with the AI first)
AI CHAT /opsx:propose add-dark-mode
(AI drafts proposal, specs, design, tasks)
AI CHAT /opsx:apply
(AI builds it, checking off tasks)
AI CHAT /opsx:archive
(change is merged into your specs and filed away)
```
Two terminal steps to set up. Then you live in chat. That's the rhythm.
## Related
- [Getting Started](getting-started.md): the full first-change walkthrough
- [Commands](commands.md): every slash command in detail
- [CLI](cli.md): every terminal command in detail
- [Supported Tools](supported-tools.md): per-tool syntax and file locations
- [FAQ](faq.md): more quick answers
- [Troubleshooting](troubleshooting.md): fixes when commands don't show up
+23 -28
View File
@@ -70,44 +70,39 @@ Or add to your development environment in `flake.nix`:
openspec --version
```
## Troubleshooting PATH Visibility
## Updating
If `openspec --version` works in one terminal but fails in an editor, AI agent,
GUI app, or automation, OpenSpec is usually installed correctly but that process
started with a different `PATH`.
Global package managers create an executable shim in a bin directory, then your
shell or launcher must put that directory on `PATH`. Common ways to inspect the
directory are:
Upgrade the package, then refresh each project's generated files:
```bash
# npm
printf '%s/bin\n' "$(npm prefix -g)"
# pnpm
pnpm bin -g
# bun
bun pm bin -g
# current shell
command -v openspec
npm install -g @fission-ai/openspec@latest # or pnpm/yarn/bun equivalent
openspec update # run inside each project
```
Make sure the environment that launches your editor, agent, GUI app, or
automation includes the package-manager bin directory. For shell startup files,
keep this to a minimal `PATH` export in a file that the target environment
actually reads. Do not move interactive setup such as prompts, themes,
completions, or commands that can block into always-loaded startup files.
`openspec update` regenerates the skill and command files for the tools you've configured, so your slash commands stay current with the installed version.
To bypass global bin discovery while debugging, run OpenSpec through a package
manager:
## Uninstalling
There's no `openspec uninstall` command, because OpenSpec is just a global package plus some files in your project. Removing it is a few manual steps, and nothing here touches your source code.
**1. Remove the global package:**
```bash
npx -y @fission-ai/openspec@latest --version
pnpm dlx @fission-ai/openspec@latest --version
npm uninstall -g @fission-ai/openspec # or: pnpm rm -g / yarn global remove / bun rm -g
```
**2. Remove OpenSpec from a project (optional).** Delete the `openspec/` directory if you no longer want its specs and changes:
```bash
rm -rf openspec/
```
Think before you do this: `openspec/specs/` and `openspec/changes/archive/` are your record of how the system behaves and why it changed. If you might want that history, keep the folder (or keep it in git) even after uninstalling.
**3. Remove generated AI tool files (optional).** OpenSpec writes skill and command files into per-tool directories like `.claude/skills/openspec-*/`, `.cursor/commands/opsx-*`, and so on. Delete the `openspec-*` skills and `opsx-*` commands for whichever tools you configured. The exact paths per tool are listed in [Supported Tools](supported-tools.md).
If you also have OpenSpec marker blocks in files like `CLAUDE.md` or `AGENTS.md`, remove those blocks by hand; your own content in those files is yours to keep.
## Next Steps
After installing, initialize OpenSpec in your project:
+1 -1
View File
@@ -297,7 +297,7 @@ Command availability is profile-dependent:
| `/opsx:continue` | Create the next artifact (one at a time) |
| `/opsx:ff` | Fast-forward—create planning artifacts at once |
| `/opsx:verify` | Validate implementation matches specs |
| `/opsx:sync` | Preview/spec-merge without archiving |
| `/opsx:sync` | Merge delta specs into main specs |
| `/opsx:bulk-archive` | Archive multiple changes at once |
| `/opsx:onboard` | Guided end-to-end onboarding workflow |
+91
View File
@@ -0,0 +1,91 @@
# Core Concepts at a Glance
**OpenSpec is a lightweight agreement layer between you and your AI.** You write down what a change should do, the AI drafts the details, you both look at the same plan, and only then does code get written. This page is the whole mental model on one screen. When you want the long version, [Concepts](concepts.md) has it.
Here's the entire idea in five words: **agree first, then build confidently.**
## The five ideas
Everything in OpenSpec is built from five concepts. Learn these and the rest is detail.
**1. Specs are the truth.** A spec describes how your system behaves *right now*. It lives in `openspec/specs/`, organized by domain (`auth/`, `payments/`, `ui/`). Specs are made of requirements ("the system SHALL expire sessions after 30 minutes") and scenarios (concrete given/when/then examples). Think of specs as the single agreed-upon answer to "what does this software do?"
**2. A change is one unit of work.** When you want to add, modify, or remove behavior, you create a change: a folder in `openspec/changes/` holding everything about that work in one place. A proposal, a design, a task list, and the spec edits. One change, one folder, one feature.
**3. Delta specs describe what's changing, not the whole world.** Inside a change, you don't rewrite the entire spec. You write a small delta: `ADDED` this requirement, `MODIFIED` that one, `REMOVED` this other one. This is the trick that makes OpenSpec good at editing existing systems, not just green-field ones. You describe the diff, not the destination.
**4. Artifacts build on each other.** A change contains a few documents, created in a natural order, each feeding the next:
```text
proposal ──► specs ──► design ──► tasks ──► implement
why what how steps do it
```
You can revisit any of them at any time. They're enablers, not gates. (More on that below.)
**5. Archiving folds the change back into the truth.** When the work is done, you archive the change. Its delta specs merge into your main specs, and the change folder moves to `changes/archive/` with a date stamp. Now your specs describe the new reality, and you're ready for the next change. The cycle closes.
## The picture
```text
┌─────────────────────────────────────────────────────────────────┐
│ openspec/ │
│ │
│ ┌──────────────────┐ ┌──────────────────────────┐ │
│ │ specs/ │ │ changes/ │ │
│ │ │ ◄───── │ │ │
│ │ source of truth │ merge │ one folder per change │ │
│ │ how things work │ on │ proposal · design · │ │
│ │ today │ archive │ tasks · delta specs │ │
│ └──────────────────┘ └──────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
Two folders. `specs/` is what's true. `changes/` is what you're proposing. Archiving moves a proposal into truth.
## The loop you'll actually run
In the default setup, your day looks like this. Optionally think it through first; then one command drafts the plan, you read it, the next builds it, and the last files it away.
```text
/opsx:explore → (optional) think it through with the AI first
/opsx:propose add-dark-mode → AI drafts proposal, specs, design, tasks
(you read and adjust the plan)
/opsx:apply → AI builds it, checking off tasks
/opsx:archive → specs updated, change archived
```
**When in doubt, start by exploring.** `/opsx:explore` is a no-stakes thinking partner: it reads your code, lays out options, and turns a fuzzy idea into a concrete plan before any artifact exists. It's the best antidote to an AI that will otherwise build *something* from a vague prompt. Already know exactly what you want? Skip straight to `/opsx:propose`. Either way, explore ships in the default profile, so it's always there. See the [Explore guide](explore.md).
Those are slash commands, typed in your AI assistant's chat. Setup (`openspec init`) happens in your terminal. If that split is new to you, read [How Commands Work](how-commands-work.md) first; it's the most common point of confusion.
## "Enablers, not gates"
This phrase shows up everywhere in OpenSpec, so here's what it means in plain terms.
Old-school spec processes are waterfalls: finish planning, *then* you're allowed to implement, and going back is painful. OpenSpec refuses that. The order `proposal → specs → design → tasks` shows what becomes *possible* next, not what you're *forced* to do next.
Discover during implementation that the design was wrong? Edit `design.md` and keep going. Realize the scope should shrink? Update the proposal. Nothing locks. The dependencies exist only so the AI has the context it needs (you can't write good tasks without specs to base them on), not to box you in.
The strength here is honesty: real work is messy and iterative, and OpenSpec lets it be. The tradeoff is discipline: because nothing forces you forward, it's on you to keep a change focused rather than letting it sprawl. The [Workflows](workflows.md) guide has good habits for that.
## Why this is worth the small overhead
Plain truth: OpenSpec adds a step. You write a short plan before building. So what do you get for it?
- **You catch wrong turns before they cost you.** Fixing a misunderstanding in a one-paragraph proposal is free. Fixing it after the AI wrote 400 lines is not.
- **The plan and the code stay in the same repo.** Six months later, the spec tells you (and the next AI session) why the system works the way it does.
- **Changes are reviewable.** A change folder is a tidy package: read the proposal, skim the deltas, check the tasks. No archaeology through chat history.
- **It fits existing codebases.** Deltas mean you can specify a change to a 50,000-line app without first documenting the whole thing.
And the honest tradeoff: for a truly trivial one-line fix, the ceremony may not pay off, and that's fine. OpenSpec is designed to be lightweight, but it isn't free. Use it where agreement matters, which turns out to be most of the time once you're working with an AI that will confidently build whatever you vaguely asked for.
## Where to go next
- New here? [Getting Started](getting-started.md) walks the first change in full.
- Not sure what to build yet? [Explore First](explore.md) is the place to start.
- Confused about where commands run? [How Commands Work](how-commands-work.md).
- Want the deep version of everything above? [Concepts](concepts.md).
- Learn by example? [Examples & Recipes](examples.md).
- Need a term defined? [Glossary](glossary.md).
+341
View File
@@ -0,0 +1,341 @@
# Stores: Plan in Its Own Repo
> **Beta.** Stores, references, working context, and worksets are
> new. Command names, flags, file formats, and JSON output may still change
> shape between releases. Every walkthrough below was run against the
> current build, but re-read this guide after upgrading.
## The problem this solves
OpenSpec normally lives inside one code repo: an `openspec/` folder next to
your code, holding specs and changes for that repo.
That stops fitting the moment your planning is bigger than one repo:
- Your work spans several repos — one feature touches the API server, the
web app, and a shared library. Whose `openspec/` folder does the plan
live in?
- Your team plans before code exists, or plans things that never become
code in *this* repo.
- Requirements are owned by one team and consumed by others. The wiki
version drifts, and your coding agent can't read it anyway.
A **store** is the answer: a standalone repo whose whole job is planning.
It has the same `openspec/` shape you already know — specs and changes —
plus a small identity file. You register it on your machine once, by name,
and then every normal OpenSpec command can work in it from anywhere.
## The shape
```
team-plans (a store: planning in its own repo)
├── .openspec-store/store.yaml identity: "I am team-plans"
└── openspec/
├── specs/ what is true
└── changes/ what is in motion
▲
│ registered on each machine by name;
│ shared by pushing/cloning like any repo
┌─────────────┼─────────────┐
│ │ │
web-app api-server mobile-app
(code repo) (code repo) (code repo)
```
Two rules keep this simple:
1. **A store is just a git repo.** You commit, push, pull, and review it
yourself. OpenSpec never clones, syncs, or pushes anything on its own.
2. **Declarations, not machinery.** Repos can *declare* how they relate to
stores (shown below). Declarations change what OpenSpec can tell you —
never where your commands act.
## Five minutes to your first store
Two commands take you from nothing to a working, store-scoped change:
```bash
openspec store setup team-plans --path ~/openspec/team-plans
```
```
Store ready: team-plans
Location: /Users/you/openspec/team-plans
OpenSpec root: ready
Registry: registered
Next: run normal OpenSpec commands against this store, for example:
openspec new change <change-id> --store team-plans
Share this store by committing and pushing it like any Git repo.
```
```bash
openspec new change add-login --store team-plans
```
```
Using OpenSpec root: team-plans (/Users/you/openspec/team-plans)
Created change 'add-login' at /Users/you/openspec/team-plans/openspec/changes/add-login/
Schema: spec-driven
Next: openspec status --change add-login --store team-plans
```
That's the whole model. From here the lifecycle is exactly what you know —
`status`, `instructions`, `validate`, `archive` — with `--store team-plans`
on each command, and every printed hint carries the flag for you. The
`Using OpenSpec root:` line always tells you where a command is acting.
## Story: one team, one planning repo
A team keeps its specs and changes in `team-plans` instead of scattering
them across code repos.
**Day one (whoever sets it up):**
```bash
openspec store setup team-plans --path ~/openspec/team-plans \
--remote git@github.com:acme/team-plans.git
git -C ~/openspec/team-plans push -u origin main
```
Passing `--remote` records the clone URL inside the store's own identity
file (`.openspec-store/store.yaml`), in the initial commit. Every future
clone is born knowing where it came from, so health checks and error
messages can print a complete, pasteable fix for teammates who don't have
it yet.
**Every teammate (once per machine):**
```bash
git clone git@github.com:acme/team-plans.git ~/openspec/team-plans
openspec store register ~/openspec/team-plans
```
From then on, everyone works in the same planning repo by name:
```bash
openspec status --store team-plans --change add-login
openspec show add-login --store team-plans
```
**Sharing work is git, on purpose.** A change you create exists only in
your checkout until you commit and push it — same as code. Plans get
branches, pull requests, and review for free, because a store is an
ordinary repo.
**Connecting the team's code repos.** A code repo whose planning is fully
externalized needs exactly one line, in `openspec/config.yaml`:
```yaml
# web-app/openspec/config.yaml
store: team-plans
```
Now every OpenSpec command run inside `web-app` acts on `team-plans` with
no flags at all:
```bash
cd ~/src/web-app
openspec status --change add-login
```
```
Using OpenSpec root: team-plans (/Users/you/openspec/team-plans)
...
```
The pointer is a fallback, never an override: an explicit `--store` always
wins, and if the repo grows real planning folders of its own, those win
(with a warning to remove the stale pointer).
## Story: requirements that cross team lines
A platform team owns the requirements. Product teams build against them,
in their own repos, with their own designs. A reference describes that
relationship without moving anyone's work.
```
platform-reqs (store) api-server (code repo)
owned by the platform team owned by a product team
┌──────────────────────────┐ ┌──────────────────────────┐
│ openspec/specs/ │ ◀────────│ openspec/config.yaml │
│ payments/spec.md │ reads │ references: │
│ auth/spec.md │ │ - platform-reqs │
│ │ │ openspec/specs/ │
│ openspec/changes/ │ │ (their own designs) │
│ platform work │ │ openspec/changes/ │
│ │ │ (their own work) │
│ │ └──────────────────────────┘
└──────────────────────────┘
```
**The product team declares what it draws on** in its repo's
`openspec/config.yaml`:
```yaml
references:
- platform-reqs
```
References are read-only context. The repo keeps its own `openspec/` root;
work stays there. What changes: `openspec instructions` in that repo now
includes an index of the referenced store's specs — each with a one-line
summary and the exact fetch command (`openspec show <spec-id> --type spec
--store platform-reqs`). An agent working in `api-server` can find the
upstream payment requirements, cite them, and write its low-level design in
the repo's own root — without anyone pasting context around.
A reference can carry its clone source, so teammates who don't have the
store yet get a complete fix instead of a dead end:
```yaml
references:
- { id: platform-reqs, remote: "git@github.com:acme/platform-reqs.git" }
```
**When you want the plan and code open together, make a workset.** This is
personal and explicit: each person chooses the folders they actually work
with on their machine. Nothing about those local checkout paths is
committed to the shared planning repo.
```bash
openspec workset create platform \
--member ~/openspec/platform-reqs \
--member ~/src/api-server \
--member ~/src/web-app
```
## Two questions you can always ask
**"Is my setup healthy?"** — `openspec doctor` checks the current root and
its referenced stores, read-only, with a pasteable fix per finding:
```
Doctor
Root
Location: /Users/you/src/api-server
OpenSpec root: ok
References
- platform-reqs: ok (/Users/you/openspec/platform-reqs)
- design-system: Referenced store 'design-system' is not registered on this machine.
Fix: git clone -- git@github.com:acme/design-system.git '/Users/you/openspec/design-system' && openspec store register '/Users/you/openspec/design-system' --id design-system
```
**"What am I working with?"** — `openspec context` assembles the working
set from OpenSpec declarations: the root and the stores it references.
```
Working context for api-server (/Users/you/src/api-server)
OpenSpec root
api-server /Users/you/src/api-server
Referenced stores
platform-reqs /Users/you/openspec/platform-reqs
Fetch: openspec show <spec-id> --type spec --store platform-reqs
```
Both support `--json` for agents. `openspec context --code-workspace
<path>` additionally writes a VS Code workspace file containing the whole
set — the only write this command performs.
## Worksets: reopen the folders you work on together
Separate from all of the above: most people open the same few folders
together every session — the planning repo plus two or three code repos.
A **workset** is a personal, named view of exactly that, reopened with one
command in your tool of choice.
```
workset "platform" openspec workset open platform
├── team-plans ~/openspec/team-plans │
├── api-server ~/src/api-server ▼
└── web-app ~/src/web-app all three open in your tool
```
```bash
openspec workset create platform \
--member ~/openspec/team-plans --member ~/src/api-server \
--tool code
openspec workset list
```
```
platform (opens in VS Code)
team-plans /Users/you/openspec/team-plans
api-server /Users/you/src/api-server
```
`openspec workset open platform` then launches the saved tool: editors
(VS Code, Cursor) open one window with every member and return. The first
member is the primary. Override the tool any time with `--tool <id>`.
Worksets are deliberately *not* shared state. They live on your machine,
are never committed, and make no claims about the work — they only record
what you like open together. Removing one never touches the member
folders. New tools are configuration, not code: anything launched via a
workspace file or per-folder attach flags can be added under the `openers`
key in the global config (`openspec config edit`).
## How commands decide where to act
Every normal command resolves its root the same way, in this order:
```
1. --store <id> you said so explicitly → that store
2. nearest openspec/ a real planning root here → this repo
(walking up from cwd)
3. store: pointer config.yaml declares a store → that store
4. none of the above stores registered on this → error with a
machine? selection hint
no stores registered? → the current
directory
(classic behavior)
```
The `Using OpenSpec root:` line (and the `root` block in `--json` output)
tells you which case you're in.
## Known limitations
- **Beta shape.** Everything on this page may change between releases —
names, flags, file formats, JSON keys.
- **One checkout per store id per machine.** Registering a second checkout
under the same id fails with a hint to `store unregister` first.
- **No sync, ever — by design.** OpenSpec never clones, pulls, or pushes.
A stale checkout shows stale specs until *you* pull; references are
indexed live from whatever is on disk.
- **Some commands stay where they are.** `view`, `templates`, `schemas`,
and the deprecated noun forms (`openspec change show`, ...) act on the
current directory only — no `--store`.
- **Per-machine state is per-machine.** The store registry and worksets
are local settings. Nothing about your machine's layout is
ever committed to shared planning.
- **Two launch styles for worksets.** A tool that can't be launched with a
workspace file or per-folder attach flags can't be added as an opener.
- **Agent JSON has a known casing split** (store-family keys are
snake_case, workflow-family camelCase). Documented in the
[agent contract](../agent-contract.md); unifying it is deferred to a
versioned release.
## Where things live
| What | Where | Shared? |
|---|---|---|
| A store's planning | `<store>/openspec/` (specs, changes) | Yes — commit and push it |
| A store's identity | `<store>/.openspec-store/store.yaml` | Yes — committed with the store |
| The store registry | `<data dir>/openspec/stores/registry.yaml` | No — this machine only |
| Worksets | `<data dir>/openspec/worksets/` | No — this machine only |
`<data dir>` is `~/.local/share/openspec` on macOS and Linux (or
`$XDG_DATA_HOME/openspec` when set), and `%LOCALAPPDATA%\openspec` on
Windows.
## Reference
Exact flags and JSON shapes for every command on this page:
[CLI reference](../cli.md) (Stores, Doctor, Working context, Personal
worksets) and the [agent contract](../agent-contract.md).
+2 -1
View File
@@ -44,6 +44,7 @@ You can enable expanded workflows (`new`, `continue`, `ff`, `verify`, `bulk-arch
| Kimi CLI (`kimi`) | `.kimi/skills/openspec-*/SKILL.md` | Not generated (no command adapter; use skill-based `/skill:openspec-*` invocations) |
| Kiro (`kiro`) | `.kiro/skills/openspec-*/SKILL.md` | `.kiro/prompts/opsx-<id>.prompt.md` |
| Lingma (`lingma`) | `.lingma/skills/openspec-*/SKILL.md` | `.lingma/commands/opsx/<id>.md` |
| Mistral Vibe (`vibe`) | `.vibe/skills/openspec-*/SKILL.md` | Not generated (no command adapter; use skill-based `/openspec-*` invocations) |
| OpenCode (`opencode`) | `.opencode/skills/openspec-*/SKILL.md` | `.opencode/commands/opsx-<id>.md` |
| Pi (`pi`) | `.pi/skills/openspec-*/SKILL.md` | `.pi/prompts/opsx-<id>.md` |
| Qoder (`qoder`) | `.qoder/skills/openspec-*/SKILL.md` | `.qoder/commands/opsx/<id>.md` |
@@ -74,7 +75,7 @@ openspec init --tools none
openspec init --profile core
```
**Available tool IDs (`--tools`):** `amazon-q`, `antigravity`, `auggie`, `bob`, `claude`, `cline`, `codex`, `forgecode`, `codebuddy`, `continue`, `costrict`, `crush`, `cursor`, `factory`, `gemini`, `github-copilot`, `iflow`, `junie`, `kilocode`, `kimi`, `kiro`, `opencode`, `pi`, `qoder`, `lingma`, `qwen`, `roocode`, `trae`, `windsurf`
**Available tool IDs (`--tools`):** `amazon-q`, `antigravity`, `auggie`, `bob`, `claude`, `cline`, `codex`, `forgecode`, `codebuddy`, `continue`, `costrict`, `crush`, `cursor`, `factory`, `gemini`, `github-copilot`, `iflow`, `junie`, `kilocode`, `kimi`, `kiro`, `lingma`, `opencode`, `pi`, `qoder`, `qwen`, `roocode`, `trae`, `vibe`, `windsurf`
## Workflow-Dependent Installation
+166
View File
@@ -0,0 +1,166 @@
# Troubleshooting
Concrete fixes for concrete problems. Each entry names a symptom, explains the likely cause in a sentence, and gives you the fix. If you don't see your issue here, the [FAQ](faq.md) may help, and the [Discord](https://discord.gg/YctCnvvshC) definitely will.
## Installation and setup
### `openspec: command not found`
The CLI isn't installed, or your shell can't find it. Install it globally and check:
```bash
npm install -g @fission-ai/openspec@latest
openspec --version
```
If it installed but still isn't found, your global npm bin directory probably isn't on your `PATH`. Run `npm bin -g` to see where global binaries live, and make sure that path is in your shell profile.
### "Requires Node.js 20.19.0 or higher"
OpenSpec runs on Node 20.19.0+. Check your version and upgrade if needed:
```bash
node --version
```
If you use bun to install OpenSpec, note that OpenSpec still *runs* on Node, so you need Node 20.19.0+ available on your `PATH` regardless. See [Installation](installation.md).
### `openspec init` didn't configure my AI tool
Init asks which tools to set up. If you skipped your tool or want to add another, just run it again, or use the non-interactive form:
```bash
openspec init --tools claude,cursor
```
The full list of tool IDs is in [Supported Tools](supported-tools.md). Use `--tools all` for everything, `--tools none` to skip tool setup.
## Commands don't show up
If `/opsx:propose` (or your tool's equivalent) doesn't appear or doesn't do anything, work down this list. They're ordered fastest-to-check first.
1. **You may be in the wrong place.** Slash commands go in your AI assistant's chat, not your terminal. If you typed `/opsx:propose` into your shell, that's the issue. See [How Commands Work](how-commands-work.md).
2. **Regenerate the files.** From your project root:
```bash
openspec update
```
This rewrites the skill and command files for every tool you've configured.
3. **Restart your assistant.** Most tools scan for skills and commands at startup. A fresh window often does it.
4. **Confirm the files exist.** For Claude Code, check that `.claude/skills/` contains `openspec-*` folders. Other tools use their own directories, all listed in [Supported Tools](supported-tools.md).
5. **Check you initialized this project.** Skills are written per project. If you cloned a repo or switched folders, run `openspec init` (or `openspec update`) there.
6. **Confirm your tool supports command files.** A few tools (Kimi CLI, Trae, ForgeCode, Mistral Vibe) don't get generated `opsx-*` command files; they use skill-based invocations instead. The forms differ per tool: see [Supported Tools](supported-tools.md) and [How Commands Work](how-commands-work.md#slash-command-syntax-by-tool).
## Working with changes
### "Change not found"
The command couldn't tell which change you meant. Name it explicitly, or check what exists:
```bash
openspec list # see active changes
/opsx:apply add-dark-mode # name the change in chat
```
Also confirm you're in the right project directory.
### "No artifacts ready"
Every artifact is either already created or blocked waiting on a dependency. See what's blocking:
```bash
openspec status --change <name>
```
Then create the missing dependency first. Remember the order: proposal enables specs and design; specs and design together enable tasks.
### `openspec validate` reports warnings or errors
Validation checks your specs and changes for structural problems. Read the message: it names the file and the issue.
```bash
openspec validate <name> # validate one item
openspec validate --all # validate everything
openspec validate --all --strict # stricter checks, good for CI
```
Common causes are a missing required section (like a spec with no scenarios) or a malformed delta header. Fix the file and re-run. The [CLI reference](cli.md#openspec-validate) documents the output format.
### The AI created incomplete or wrong artifacts
The AI didn't have enough context. A few levers help:
- Add project context in `openspec/config.yaml` so your stack and conventions are injected into every request. See [Customization](customization.md#project-configuration).
- Add per-artifact `rules:` for guidance that only applies to, say, specs.
- Give a more detailed description when you propose.
- Use the expanded `/opsx:continue` to create one artifact at a time and review each, instead of `/opsx:ff` doing them all at once.
### Archive won't finish, or warns about incomplete tasks
Archive won't *block* on incomplete tasks, but it warns you, because archiving usually means the work is done. If tasks remain on purpose (you're filing a partial change), proceed. Otherwise finish the tasks first. Archive will also offer to sync your delta specs into the main specs if you haven't synced yet; say yes unless you have a reason not to.
## Configuration
### My `config.yaml` isn't being applied
Three usual suspects:
1. **Wrong filename.** It must be `openspec/config.yaml`, not `.yml`.
2. **Invalid YAML.** Run it through any YAML validator; the CLI also reports syntax errors with line numbers.
3. **You expected a restart.** You don't need one. Config changes take effect immediately.
### "Unknown artifact ID in rules: X"
A key under `rules:` doesn't match any artifact in your schema. For the default `spec-driven` schema the valid IDs are `proposal`, `specs`, `design`, `tasks`. To see the IDs for any schema:
```bash
openspec schemas --json
```
### "Context too large"
The `context:` field is capped at 50KB, on purpose, because it's injected into every request. Summarize it, or link out to longer docs instead of pasting them. Lean context also produces better, faster results.
### "Schema not found"
The schema name you referenced doesn't exist. List what's available and check spelling:
```bash
openspec schemas # list available schemas
openspec schema which <name> # see where a schema resolves from
openspec schema init <name> # create a custom one
```
See [Customization](customization.md#custom-schemas).
## Migration from the legacy workflow
### "Legacy files detected in non-interactive mode"
You're in CI or a non-interactive shell, and OpenSpec found old files to clean up but can't prompt you. Approve automatically:
```bash
openspec init --force
```
### Commands didn't appear after migrating
Restart your IDE. Skills are detected at startup. If they still don't appear, run `openspec update` and check the file locations in [Supported Tools](supported-tools.md).
### My old `project.md` wasn't migrated
That's intentional. OpenSpec never deletes `project.md` automatically because it may hold context you wrote. Move the useful parts into `config.yaml`'s `context:` section, then delete it yourself. The [Migration Guide](migration-guide.md#migrating-projectmd-to-configyaml) walks through this, including a prompt you can hand to your AI to do the distilling.
## Still stuck?
- **Discord:** [discord.gg/YctCnvvshC](https://discord.gg/YctCnvvshC)
- **GitHub Issues:** [github.com/Fission-AI/OpenSpec/issues](https://github.com/Fission-AI/OpenSpec/issues)
- **From your terminal:** `openspec feedback "what went wrong"` opens an issue for you.
When you report a problem, include your OpenSpec version (`openspec --version`), your Node version (`node --version`), your AI tool, and the exact command and output. It makes help much faster.
+30 -3
View File
@@ -33,8 +33,8 @@ OPSX (fluid actions):
### Default Quick Path (`core` profile)
New installs default to `core`, which provides:
- `/opsx:propose`
- `/opsx:explore`
- `/opsx:propose`
- `/opsx:apply`
- `/opsx:sync`
- `/opsx:archive`
@@ -42,9 +42,36 @@ New installs default to `core`, which provides:
Typical flow:
```text
/opsx:propose ──► /opsx:apply ──► /opsx:sync ──► /opsx:archive
/opsx:explore ──► /opsx:propose ──► /opsx:apply ──► /opsx:sync ──► /opsx:archive
(optional)
```
#### Start by exploring (the habit worth forming)
`/opsx:explore` is part of the default profile, not an advanced add-on. It's the move to make whenever you have a problem but not yet a plan, which, with an AI assistant, is most of the time.
```text
You: /opsx:explore
AI: What would you like to explore?
You: Our search results feel stale. I'm not sure if it's caching,
indexing, or the query itself.
AI: Let me look... [reads the search service and cache layer]
It's the index: it only rebuilds nightly, so edits don't show
up until the next day. Two options: rebuild on write (simple,
more load) or a short-TTL cache invalidation (more moving parts,
less load). Given your write volume is low, rebuild-on-write is
the cleaner fix. Want to scope it?
You: Yes.
You: /opsx:propose rebuild-search-index-on-write
```
Explore creates no artifacts and writes no code. It's a free, no-stakes conversation that turns a vague worry into a precise change, so the proposal that follows is sharp. Already know exactly what you want? Skip it and go straight to `/opsx:propose`. Full guide: [Explore First](explore.md).
### Expanded/Full Workflow (custom selection)
If you want explicit scaffold-and-build commands (`/opsx:new`, `/opsx:continue`, `/opsx:ff`, `/opsx:verify`, `/opsx:bulk-archive`, `/opsx:onboard`), enable them with:
@@ -435,7 +462,7 @@ For full command details and options, see [Commands](commands.md).
| Command | Purpose | When to Use |
|---------|---------|-------------|
| `/opsx:propose` | Create change + planning artifacts | Fast default path (`core` profile) |
| `/opsx:explore` | Think through ideas | Unclear requirements, investigation |
| `/opsx:explore` | Think through ideas with the AI | Start here when unsure: unclear requirements, investigation, comparing options |
| `/opsx:new` | Start a change scaffold | Expanded mode, explicit artifact control |
| `/opsx:continue` | Create next artifact | Expanded mode, step-by-step artifact creation |
| `/opsx:ff` | Create all planning artifacts | Expanded mode, clear scope |
+1 -1
View File
@@ -51,7 +51,7 @@
inherit (finalAttrs) pname version src;
pnpm = pkgs.pnpm_9;
fetcherVersion = 3;
hash = "sha256-9s2kdvd7svK4hofnD66HkDc86WTQeayfF5y7L2dmjNg=";
hash = "sha256-cFY6phUPK4IOthG/aOtMenyQlLYCCilcOIG+G+v/q04=";
};
nativeBuildInputs = with pkgs; [
@@ -0,0 +1,266 @@
## Product Shape
`workspace open` should feel like opening a multi-root working set.
The user model is:
```text
workspace setup = create the planning home and choose the default opener
workspace links = the repos or folders OpenSpec can plan across
workspace open = open that linked working set
--agent = use a different agent for this one session
--editor = open the working set as an editor workspace
```
Repo or folder visibility supports exploration and planning. Opening a workspace gives the agent or editor access to linked paths, and implementation starts through an explicit later workflow.
## Command Surface
Supported v1 forms:
```bash
openspec workspace open
openspec workspace open platform
openspec workspace open --agent codex
openspec workspace open platform --agent github-copilot
openspec workspace open --editor
```
The positional workspace name is the primary explicit selection surface for `open`. User-facing docs should prefer the positional form because a flag such as `--workspace <name>` repeats the noun.
For consistency with other workspace commands and scripts, `workspace open` may also support `--workspace <name>` as an alias for the positional name:
```bash
openspec workspace open platform
openspec workspace open --workspace platform
```
User-facing docs should prefer the positional form. If both are provided and they differ, OpenSpec should fail with a clear conflict error.
`--prepare-only` should not be included. The POC used it to build and print launch surfaces without starting the external tool, but that does not map cleanly to a user-facing intent.
`--json` should not be included in this slice. If a future integration needs a machine-readable resolved-open context, design that as a separate context/query surface instead of overloading the launching command.
`--change` should be deferred. Change-scoped open depends on workspace change planning and target semantics that this slice should not invent.
## Workspace Selection
Selection should follow this order:
1. If a positional workspace name is provided, open that known workspace.
2. Otherwise, if the command runs from inside a workspace, open the current workspace.
3. Otherwise, if exactly one workspace is known locally, open it.
4. Otherwise, if multiple workspaces are known and the terminal is interactive, present a picker.
5. Otherwise, fail with a clear message that names the known workspaces and asks the user to pass the workspace name.
This keeps the common cases direct while still supporting global use.
## Preferred Opener
Workspace setup should ask which opener the user wants by default. The answer is machine-local state because different machines may have different installed agents or editors.
`workspace open` uses the saved opener when no override is passed.
`--agent <tool>` is a one-session override that leaves the saved preference unchanged. Persisting a changed default should require an explicit preference/config action in a later slice if users need it.
This slice should not add global workspace opener config. OpenSpec already has a global config system, and workspace-level defaults can be added there later if repeated setup makes the local prompt feel noisy.
The local preference should be shaped so a future global default can fit underneath it with smooth migration. The intended precedence is:
```text
command override
-> workspace-local preferred opener
-> future global workspace default opener
-> interactive prompt or built-in fallback
```
In future config terms, that global default might look like `workspace.defaultOpener`; this slice documents the precedence for later implementation.
Store the preferred opener as a structured object in `.openspec-workspace/local.yaml`:
```yaml
preferred_opener:
kind: agent
id: codex
```
```yaml
preferred_opener:
kind: editor
id: vscode
```
Allowed initial values:
```text
kind: agent, id: codex
kind: agent, id: claude
kind: agent, id: github-copilot
kind: editor, id: vscode
```
The structure keeps the agent/editor distinction clear and leaves room for future opener variants without changing the local-state shape.
Interactive setup should show all supported opener choices, but it should order detected/available openers first. Unavailable choices should still be visible with a note such as `not found on PATH`.
Setup should prefer the plain editor option over an agent when a fallback default is needed for an interactive picker.
Non-interactive setup stores a preferred opener when the caller explicitly passes an opener option. Otherwise, it leaves opener selection for a later interactive `workspace open` prompt or a non-interactive error that explains how to choose an opener.
The setup-time flag should be:
```bash
openspec workspace setup --no-interactive --name platform --link /repo --opener codex
openspec workspace setup --no-interactive --name platform --link /repo --opener editor
```
`--opener <id>` sets the stored preference. It is different from `workspace open --agent <id>` and `workspace open --editor`, which are one-session runtime overrides.
Initial opener detection should stay simple and executable-based:
```text
VS Code editor: code
Codex: codex
Claude: claude
GitHub Copilot in VS Code: code
```
Keep initial detection scoped to executable availability in this slice.
Supported agent values for the initial open surface should be limited to tools with a real launch or attachment mechanism:
```text
claude
codex
github-copilot
```
Plain editor open should be represented by `--editor` with an explicit editor kind.
For this slice, `--editor` means VS Code editor. The `.code-workspace` format is VS Code-specific, so prompts and errors should call this `VS Code editor` rather than implying generic editor support.
`github-copilot` means the VS Code Copilot experience. It should open the maintained `.code-workspace` in VS Code because that is the product surface where this Copilot mode is available.
If OpenSpec later supports a Copilot CLI agent, it should use a distinct value such as `github-copilot-cli` and launch the CLI agent directly. VS Code Copilot and a CLI agent have different opener mechanics, so they should remain distinct opener values.
## Opener Availability
`workspace open` should fail with a clear error when the selected opener is unavailable on the current machine.
The selected opener remains required because it represents user intent, whether it came from local preference or a command-line override.
Errors should name the missing executable or unavailable opener and suggest a concrete next step. For editor-based open, the error should include the `.code-workspace` path so the user can open it manually if needed.
When no preferred opener is stored and no command-line override is provided, `workspace open` should prompt in interactive mode. In non-interactive mode, it should fail and tell the user to pass either an agent override or the editor option.
## Editor Open
`--editor` opens the workspace root plus every linked repo or folder with a valid local path.
For VS Code-style editor support, OpenSpec should create and maintain a `.code-workspace` file as part of the workspace setup/link/relink lifecycle. `workspace open` should launch against existing workspace state.
Expected local workspace shape:
```text
workspace-root/
changes/
<workspace-name>.code-workspace
.openspec-workspace/
workspace.yaml
local.yaml
```
The `.code-workspace` file should include the workspace root and each linked repo or folder with a valid local path. Because linked paths come from machine-local workspace state, OpenSpec-created workspaces should ignore the maintained `.code-workspace` file by default.
The ignore rule should target the specific maintained file and leave other `*.code-workspace` files available for user-authored tracking:
```text
<workspace-name>.code-workspace
```
This lets teams add a separate user-authored portable `.code-workspace` later if they have a shared relative-path layout.
`workspace setup`, `workspace link`, and `workspace relink` should all run the same open-surface sync after mutating workspace state. That sync owns:
- `AGENTS.md`
- `<workspace-name>.code-workspace`
- workspace ignore rules for machine-local files
Even when a command only changes local state, such as `workspace relink`, it should refresh the full openable workspace surface so user-facing files do not drift.
`--agent github-copilot` may use the same editor workspace mechanics, but it also needs Copilot prompt context. Plain `--editor` keeps a normal editor-workspace intent.
`--agent github-copilot` should still open VS Code. The distinction from `--editor` is intent: `--editor` opens the workspace as a normal editor workspace, while `--agent github-copilot` opens the same editor workspace for the user to work with the VS Code Copilot agent experience.
## Workspace Guidance
Workspace setup should install stable guidance in the workspace root, preferably `AGENTS.md`.
The guidance should explain durable workspace rules:
- the workspace root is the planning home
- `changes/` contains workspace-level planning
- linked repos and folders are available for exploration and planning
- visibility supports exploration and planning
- implementation edits start after the user explicitly asks for implementation work
The managed `AGENTS.md` text should stay short and durable, covering stable workspace guidance while runtime details remain discoverable from workspace state. A starting shape:
```markdown
# OpenSpec Workspace Guidance
This directory is an OpenSpec workspace for planning across linked repos or folders.
- Use `changes/` for workspace-level planning.
- Linked repos and folders are available for exploration and planning.
- Repo or folder visibility supports exploration and planning.
- Make implementation edits after the user explicitly asks for implementation work.
- Treat linked repos and folders as the implementation homes for their owned code.
- Use OpenSpec workspace commands instead of hand-editing `.openspec-workspace/*.yaml`.
```
`workspace open` is a launching feature. It should launch the selected opener against existing workspace files.
For Claude and Codex, `workspace open` may still need to pass workspace and linked directory arguments to the agent process at launch because those tools do not consume `.code-workspace` directly. If an opener requires an initial prompt argument, it should be minimal, such as `Open this OpenSpec workspace.`
Dynamic workspace facts should normally be discoverable from existing files:
- linked paths: `.openspec-workspace/local.yaml`
- stable link names: `.openspec-workspace/workspace.yaml`
- active workspace changes: `changes/`
- editor working set: `<workspace-name>.code-workspace`
Report a command file or prompt file path only when the file is actually written and used.
OpenSpec should own a marked workspace-guidance block inside `AGENTS.md`:
```markdown
<!-- OPENSPEC:WORKSPACE-GUIDANCE:START -->
# OpenSpec Workspace Guidance
...
<!-- OPENSPEC:WORKSPACE-GUIDANCE:END -->
```
`workspace setup`, `workspace link`, and `workspace relink` may rewrite that marked block during open-surface sync. Content outside the marked block should be preserved so users can keep their own workspace notes in the same file.
If `AGENTS.md` is missing, OpenSpec should recreate it. If `AGENTS.md` exists and the markers are absent, OpenSpec should append the managed block while preserving existing content.
## Linked Paths
Root workspace open should attach every linked repo or folder with a valid local path.
Broken links are skipped during workspace open. OpenSpec should surface clear status in human output, with `openspec workspace doctor` as the repair path.
Links with repo-local `openspec/` state absent remain valid for workspace open. Missing repo-local OpenSpec state can matter later for implementation readiness while still allowing visibility for exploration and planning.
## Safety Boundary
The opening prompt or editor guidance should say:
```text
Linked repos and folders are visible for exploration and planning.
Make implementation edits after the user explicitly asks for implementation work.
```
Prompt guidance is acceptable for this slice because apply/verify/archive sit outside the open surface. Later implementation workflows should enforce mode and scope through explicit context providers as well as prompt wording.
@@ -0,0 +1,65 @@
## Why
After a user creates a workspace and links repos or folders, they need to open that workspace with their preferred agent or editor and have the working set available immediately.
The workspace should provide repo and folder locations, link names, and the context that distinguishes planning from implementation.
## What Changes
Add the workspace-open experience:
```text
Open this workspace.
Use my preferred opener by default and honor explicit opener overrides.
The opener sees the workspace location, linked repos or folders, current changes, and relevant instructions.
```
Links are the planning context. The local registry serves as a workspace-discovery index for finding known workspaces on the current machine.
Expected user surface:
```bash
openspec workspace open
openspec workspace open platform
openspec workspace open --agent codex
openspec workspace open platform --agent github-copilot
openspec workspace open --editor
```
`workspace open` should open the current workspace when run from inside one, auto-select the only known workspace when run outside a workspace, and present an interactive picker when multiple known workspaces are available. Users can pass a workspace name as the positional argument when they want to choose explicitly.
Workspace setup should ask for and store a preferred opener in machine-local workspace state. `workspace open` uses that preference by default. `--agent <tool>` is a one-session override that leaves the saved preference unchanged.
`--editor` opens the workspace as an editor workspace. This is related to, but distinct from, `--agent github-copilot`: GitHub Copilot needs editor workspace support plus agent prompt context, while plain editor open should focus on opening the linked working set.
Workspace guidance should live in durable workspace files where possible:
- stable behavior belongs in workspace-level `AGENTS.md`
- opener-specific launch prompts stay minimal when required
- linked repos or folders are visible for exploration and planning before a change exists
This slice supports root workspace launching through the documented opener forms. Public preview (`--prepare-only`) and machine-readable context (`--json`) surfaces belong in a future context/query design if a clear user need appears.
This slice focuses on root workspace open behavior. Change-scoped sessions need the target model from workspace change planning before they can be specified cleanly.
Planning dependency:
- Depends on `workspace-create-and-register-repos`.
## Capabilities
### New Capabilities
- `workspace-open`: Opens a workspace through a preferred agent or VS Code editor with linked repos or folders available for exploration and planning.
### Modified Capabilities
- `workspace-foundation`: Extends machine-local workspace state and setup/link/relink behavior with a preferred opener and maintained openable workspace surface.
## Impact
- `openspec workspace open`
- Workspace setup preferred opener prompt and local preference storage.
- Workspace prompt, editor workspace, and agent-launch context.
- Generated or committed agent guidance for workspace mode.
- Tests for opening inside a workspace, auto-selecting one known workspace, picking among multiple known workspaces, opening by workspace name, one-session agent overrides, and editor open.
@@ -0,0 +1,76 @@
## ADDED Requirements
### Requirement: Workspace Preferred Opener State
OpenSpec SHALL store a workspace's preferred opener in machine-local workspace state when the user explicitly chooses one.
#### Scenario: Recording an interactive setup opener choice
- **WHEN** an interactive user chooses a preferred opener during `openspec workspace setup`
- **THEN** OpenSpec SHALL record the opener in `.openspec-workspace/local.yaml`
- **AND** the stored value SHALL use a structured `preferred_opener` object with `kind` and `id`
#### Scenario: Recording a non-interactive setup opener choice
- **WHEN** a non-interactive user runs `openspec workspace setup --no-interactive --opener codex`
- **THEN** OpenSpec SHALL record `preferred_opener.kind` as `agent`
- **AND** it SHALL record `preferred_opener.id` as `codex`
#### Scenario: Leaving opener unset during non-interactive setup
- **WHEN** a non-interactive user runs `openspec workspace setup --no-interactive` with opener selection omitted
- **THEN** OpenSpec SHALL leave the workspace preferred opener unset
- **AND** the unset state SHALL allow `workspace open` to prompt later
#### Scenario: Supported preferred opener values
- **WHEN** OpenSpec accepts a preferred opener value
- **THEN** it SHALL accept `codex`, `claude`, `github-copilot`, and `editor`
- **AND** it SHALL map `editor` to `kind: editor` and `id: vscode`
- **AND** it SHALL map agent values to `kind: agent` and the matching agent `id`
#### Scenario: Ordering setup opener choices
- **WHEN** interactive setup displays opener choices
- **THEN** OpenSpec SHALL show all supported openers
- **AND** it SHALL order openers with detected executables before unavailable openers
- **AND** unavailable openers SHALL remain visible with an availability note
### Requirement: Maintained Workspace Open Surface
OpenSpec SHALL maintain files that make a workspace directly openable after setup and link changes.
#### Scenario: Creating the open surface during setup
- **WHEN** `openspec workspace setup` creates a workspace
- **THEN** OpenSpec SHALL create or refresh `AGENTS.md`
- **AND** it SHALL create or refresh `<workspace-name>.code-workspace`
- **AND** it SHALL create or refresh workspace ignore rules for machine-local open files
#### Scenario: Refreshing the open surface after linking
- **WHEN** `openspec workspace link` succeeds
- **THEN** OpenSpec SHALL refresh `AGENTS.md`
- **AND** it SHALL refresh `<workspace-name>.code-workspace`
- **AND** it SHALL refresh workspace ignore rules for machine-local open files
#### Scenario: Refreshing the open surface after relinking
- **WHEN** `openspec workspace relink` succeeds
- **THEN** OpenSpec SHALL refresh `AGENTS.md`
- **AND** it SHALL refresh `<workspace-name>.code-workspace`
- **AND** it SHALL refresh workspace ignore rules for machine-local open files
#### Scenario: Building the VS Code workspace file
- **WHEN** OpenSpec refreshes `<workspace-name>.code-workspace`
- **THEN** the file SHALL include the workspace root
- **AND** the workspace root folder entry SHALL use the root path without a synthetic display name
- **AND** it SHALL include every linked repo or folder with a valid local path
- **AND** it SHALL omit linked repos or folders whose local paths are missing or invalid
#### Scenario: Ignoring the maintained VS Code workspace file
- **WHEN** OpenSpec refreshes workspace ignore rules
- **THEN** it SHALL ignore the specific maintained `<workspace-name>.code-workspace` file
- **AND** user-authored `*.code-workspace` files SHALL remain eligible for tracking
#### Scenario: Preserving user-authored AGENTS content
- **GIVEN** `AGENTS.md` contains content outside the OpenSpec workspace guidance markers
- **WHEN** OpenSpec refreshes workspace guidance
- **THEN** it SHALL replace only the marked OpenSpec workspace guidance block
- **AND** it SHALL preserve content outside the markers
#### Scenario: Appending AGENTS guidance when markers are missing
- **GIVEN** `AGENTS.md` exists and OpenSpec workspace guidance markers are absent
- **WHEN** OpenSpec refreshes workspace guidance
- **THEN** it SHALL append the marked OpenSpec workspace guidance block
- **AND** it SHALL preserve the existing file content
@@ -0,0 +1,199 @@
## ADDED Requirements
### Requirement: Workspace Open Command
OpenSpec SHALL provide a `workspace open` command that opens an OpenSpec workspace working set through an agent or VS Code editor.
#### Scenario: Opening the current workspace
- **GIVEN** the command runs from inside an OpenSpec workspace
- **WHEN** the user runs `openspec workspace open`
- **THEN** OpenSpec SHALL open that current workspace
- **AND** it SHALL use the selected opener for that workspace
#### Scenario: Opening a named workspace
- **GIVEN** a workspace named `platform` is known locally
- **WHEN** the user runs `openspec workspace open platform`
- **THEN** OpenSpec SHALL open the `platform` workspace
#### Scenario: Opening a named workspace with the selection flag
- **GIVEN** a workspace named `platform` is known locally
- **WHEN** the user runs `openspec workspace open --workspace platform`
- **THEN** OpenSpec SHALL open the `platform` workspace
#### Scenario: Conflicting workspace selectors
- **GIVEN** workspaces named `platform` and `checkout` are known locally
- **WHEN** the user runs `openspec workspace open platform --workspace checkout`
- **THEN** OpenSpec SHALL fail with a clear conflict error
- **AND** the error SHALL name both conflicting selectors
#### Scenario: Handling unsupported preview and JSON flags
- **WHEN** the user runs `openspec workspace open` with `--prepare-only` or `--json`
- **THEN** OpenSpec SHALL fail with a clear error that the root workspace open surface supports launching through a selected opener
- **AND** the error SHALL direct preview or machine-readable context needs to a future context/query surface
#### Scenario: Handling change-scoped open before workspace planning
- **WHEN** the user runs `openspec workspace open --change <id>`
- **THEN** OpenSpec SHALL fail with a clear error that this slice supports root workspace open
- **AND** the error SHALL direct change-scoped open behavior to future workspace change planning
### Requirement: Workspace Selection For Open
OpenSpec SHALL resolve the workspace to open using current workspace context, local registry state, and interactive selection.
#### Scenario: Current workspace wins
- **GIVEN** the command runs from a workspace folder or one of its subdirectories
- **AND** no workspace name is provided
- **WHEN** the user runs `openspec workspace open`
- **THEN** OpenSpec SHALL open the current workspace
#### Scenario: Auto-selecting the only known workspace
- **GIVEN** the command runs outside a workspace
- **AND** exactly one workspace is known locally
- **WHEN** the user runs `openspec workspace open`
- **THEN** OpenSpec SHALL open that known workspace directly
#### Scenario: Picking from multiple workspaces
- **GIVEN** the command runs outside a workspace
- **AND** multiple workspaces are known locally
- **AND** the terminal is interactive
- **WHEN** the user runs `openspec workspace open`
- **THEN** OpenSpec SHALL present a picker with workspace names and locations
- **AND** it SHALL open the workspace the user selects
#### Scenario: Non-interactive ambiguous selection
- **GIVEN** the command runs outside a workspace
- **AND** multiple workspaces are known locally
- **AND** the terminal is non-interactive
- **WHEN** the user runs `openspec workspace open`
- **THEN** OpenSpec SHALL fail with a clear message listing the known workspace names
- **AND** it SHALL ask the user to pass a workspace name
#### Scenario: No known workspace
- **GIVEN** the command runs outside a workspace
- **AND** no workspaces are known locally
- **WHEN** the user runs `openspec workspace open`
- **THEN** OpenSpec SHALL fail with a clear message
- **AND** it SHALL suggest running `openspec workspace setup`
### Requirement: Opener Resolution
OpenSpec SHALL resolve the opener from command overrides, workspace-local preference, or an interactive prompt.
#### Scenario: Conflicting opener overrides
- **WHEN** the user runs `openspec workspace open --agent codex --editor`
- **THEN** OpenSpec SHALL fail with a clear conflict error naming `--agent` and `--editor`
- **AND** it SHALL avoid launching any opener
- **AND** it SHALL leave the stored preferred opener unchanged
#### Scenario: Using the stored preferred opener
- **GIVEN** the workspace has a machine-local preferred opener
- **WHEN** the user runs `openspec workspace open` using default opener resolution
- **THEN** OpenSpec SHALL use the stored preferred opener
#### Scenario: Overriding with an agent for one session
- **GIVEN** the workspace has a stored preferred opener
- **WHEN** the user runs `openspec workspace open --agent codex`
- **THEN** OpenSpec SHALL use Codex for that open command
- **AND** it SHALL leave the stored preferred opener unchanged
#### Scenario: Overriding with VS Code editor for one session
- **GIVEN** the workspace has a stored preferred opener
- **WHEN** the user runs `openspec workspace open --editor`
- **THEN** OpenSpec SHALL open the workspace in VS Code editor mode
- **AND** it SHALL leave the stored preferred opener unchanged
#### Scenario: Prompting when no opener is stored
- **GIVEN** the workspace has no stored preferred opener
- **AND** the terminal is interactive
- **WHEN** the user runs `openspec workspace open` using default opener resolution
- **THEN** OpenSpec SHALL prompt the user to choose an opener
- **AND** it SHALL only offer openers with detected executables
#### Scenario: Failing when no opener can be prompted
- **GIVEN** the workspace has no stored preferred opener
- **AND** the terminal is interactive
- **AND** no supported opener executable is available on `PATH`
- **WHEN** the user runs `openspec workspace open` using default opener resolution
- **THEN** OpenSpec SHALL fail with a clear message that no supported opener is available
- **AND** it SHALL avoid prompting with unlaunchable choices
#### Scenario: Failing when no opener is stored in non-interactive mode
- **GIVEN** the workspace has no stored preferred opener
- **AND** the terminal is non-interactive
- **WHEN** the user runs `openspec workspace open` using default opener resolution
- **THEN** OpenSpec SHALL fail with a clear message
- **AND** it SHALL ask the user to pass `--agent <tool>` or `--editor`
### Requirement: Opener Launch Behavior
OpenSpec SHALL launch the selected opener using existing workspace files and linked path state.
#### Scenario: Opening VS Code editor
- **GIVEN** the user selected the VS Code editor opener
- **WHEN** `code` is available on `PATH`
- **THEN** OpenSpec SHALL open the workspace's maintained `.code-workspace` file with VS Code
#### Scenario: Opening GitHub Copilot in VS Code
- **GIVEN** the user selected `--agent github-copilot`
- **WHEN** `code` is available on `PATH`
- **THEN** OpenSpec SHALL open the workspace's maintained `.code-workspace` file with VS Code
- **AND** it SHALL treat this as the VS Code Copilot experience
#### Scenario: Opening Codex
- **GIVEN** the user selected `--agent codex`
- **WHEN** `codex` is available on `PATH`
- **THEN** OpenSpec SHALL launch Codex from the workspace root
- **AND** it SHALL attach every linked repo or folder with a valid local path using Codex's supported directory attachment mechanism
#### Scenario: Opening Claude
- **GIVEN** the user selected `--agent claude`
- **WHEN** `claude` is available on `PATH`
- **THEN** OpenSpec SHALL launch Claude from the workspace root
- **AND** it SHALL attach every linked repo or folder with a valid local path using Claude's supported directory attachment mechanism
#### Scenario: Missing opener executable
- **GIVEN** the selected opener requires an executable that is not available on `PATH`
- **WHEN** the user runs `openspec workspace open`
- **THEN** OpenSpec SHALL fail with a clear error naming the missing executable
- **AND** it SHALL keep the selected opener as the required opener
#### Scenario: Missing VS Code executable
- **GIVEN** the selected opener is VS Code editor or GitHub Copilot in VS Code
- **AND** `code` is not available on `PATH`
- **WHEN** the user runs `openspec workspace open`
- **THEN** OpenSpec SHALL fail with a clear error naming `code`
- **AND** it SHALL include the maintained `.code-workspace` path so the user can open it manually
### Requirement: Linked Working Set Visibility
OpenSpec SHALL make linked repos and folders visible for workspace exploration and planning before change creation.
#### Scenario: Attaching valid linked paths
- **GIVEN** a workspace has linked repos or folders with valid local paths
- **WHEN** the user opens the workspace through an opener that supports linked directory attachment
- **THEN** OpenSpec SHALL include every valid linked path in the opened working set
- **AND** it SHALL support opening before a workspace change exists
#### Scenario: Skipping broken linked paths
- **GIVEN** a workspace has at least one linked path that is missing or not recorded locally
- **WHEN** the user opens the workspace
- **THEN** OpenSpec SHALL skip the broken linked path
- **AND** it SHALL report that the path was skipped with `openspec workspace doctor` as the repair path
- **AND** it SHALL continue opening the workspace when the selected opener itself is available
#### Scenario: Opening links with repo-local OpenSpec state absent
- **GIVEN** a linked repo or folder has a valid local path and repo-local `openspec/` state is absent
- **WHEN** the user opens the workspace
- **THEN** OpenSpec SHALL include that link when its local path is valid
- **AND** it SHALL treat missing repo-local OpenSpec state as an implementation-readiness concern for later workflows while continuing open
### Requirement: Workspace Open Guidance
OpenSpec SHALL use durable workspace guidance as the primary context source for root workspace open.
#### Scenario: Launching with existing workspace guidance
- **GIVEN** the workspace has OpenSpec-managed guidance in `AGENTS.md`
- **WHEN** the user opens the workspace
- **THEN** OpenSpec SHALL refresh the maintained `.code-workspace` from current linked path state
- **AND** it SHALL launch the selected opener against refreshed workspace files
- **AND** it SHALL use durable workspace files as the primary workspace-open artifact
#### Scenario: Minimal required launch prompt
- **GIVEN** an opener requires an initial prompt argument
- **WHEN** OpenSpec launches that opener
- **THEN** OpenSpec SHALL use a minimal prompt such as `Open this OpenSpec workspace.`
- **AND** durable workspace rules SHALL remain in workspace files
@@ -0,0 +1,89 @@
## 1. Preferred Opener State
- [x] 1.1 Add structured `preferred_opener` support to workspace local state parsing and serialization
- [x] 1.2 Support backward-compatible parsing for existing local workspace files while adding `preferred_opener`
- [x] 1.3 Validate supported opener values: `codex`, `claude`, `github-copilot`, and `editor`
- [x] 1.4 Map `editor` to `kind: editor, id: vscode`
- [x] 1.5 Map agent opener values to `kind: agent` with the matching `id`
- [x] 1.6 Add simple executable detection for `code`, `codex`, and `claude`
- [x] 1.7 Add unit tests for preferred opener parsing, serialization, and invalid opener values
## 2. Setup Opener Selection
- [x] 2.1 Add interactive setup prompt for the preferred opener
- [x] 2.2 Show all supported opener choices with detected openers ordered first
- [x] 2.3 Mark unavailable opener choices with a clear availability note
- [x] 2.4 Prefer the plain editor option for setup fallback selection when a fallback is needed
- [x] 2.5 Add `workspace setup --opener <id>` for non-interactive setup
- [x] 2.6 Store a preferred opener during non-interactive setup when `--opener` is provided
- [x] 2.7 Add tests for interactive opener selection and non-interactive `--opener`
- [x] 2.8 Add tests that non-interactive setup with omitted `--opener` leaves opener unset
## 3. Open Surface Sync
- [x] 3.1 Add a shared open-surface sync helper used by setup, link, and relink
- [x] 3.2 Create or refresh root `AGENTS.md` with an OpenSpec-managed workspace guidance block
- [x] 3.3 Preserve user-authored `AGENTS.md` content outside the managed block
- [x] 3.4 Append the managed block to unmarked existing `AGENTS.md` files
- [x] 3.5 Create or refresh `<workspace-name>.code-workspace` at the workspace root
- [x] 3.6 Include the workspace root and every linked repo or folder with a valid local path in the `.code-workspace`
- [x] 3.7 Omit linked repos or folders with missing or invalid local paths from the `.code-workspace`
- [x] 3.8 Refresh `.gitignore` with the specific maintained `<workspace-name>.code-workspace` entry
- [x] 3.9 Scope ignore updates to the maintained `<workspace-name>.code-workspace` file
- [x] 3.10 Add cross-platform tests for `.code-workspace` path construction and Windows-style paths where practical
## 4. Workspace Open Selection
- [x] 4.1 Add `openspec workspace open [name]`
- [x] 4.2 Support `openspec workspace open --workspace <name>` as an alias for the positional name
- [x] 4.3 Fail clearly when positional name and `--workspace` are both provided with different values
- [x] 4.4 Open the current workspace when run from a workspace folder or subdirectory
- [x] 4.5 Auto-select the only known workspace when run outside a workspace
- [x] 4.6 Present an interactive picker when multiple workspaces are known
- [x] 4.7 Report ambiguous workspace selection in non-interactive mode and list known workspace names
- [x] 4.8 Report unresolved workspace selection clearly and suggest `openspec workspace setup`
- [x] 4.9 Handle unsupported `--prepare-only`, `--json`, and `--change` flags with clear errors
- [x] 4.10 Add command integration tests for selection, conflict, unsupported flags, and no-workspace cases
## 5. Opener Resolution
- [x] 5.1 Resolve command-line opener overrides before workspace-local preferences
- [x] 5.2 Implement `workspace open --agent codex`
- [x] 5.3 Implement `workspace open --agent claude`
- [x] 5.4 Implement `workspace open --agent github-copilot`
- [x] 5.5 Implement `workspace open --editor`
- [x] 5.6 Keep the stored preferred opener unchanged for `--agent` and `--editor` overrides
- [x] 5.7 Prompt interactively to choose an opener when the opener preference is unset
- [x] 5.8 Report unset opener preference in non-interactive mode with override guidance
- [x] 5.9 Add tests for opener precedence, prompting, non-interactive failure, and unchanged preference behavior
## 6. Opener Launchers
- [x] 6.1 Launch VS Code editor by opening the maintained `.code-workspace` file with `code`
- [x] 6.2 Launch GitHub Copilot by opening the maintained `.code-workspace` file with VS Code
- [x] 6.3 Launch Codex from the workspace root with valid linked paths attached
- [x] 6.4 Launch Claude from the workspace root with valid linked paths attached
- [x] 6.5 Use a minimal launch prompt when an agent CLI requires an initial prompt argument
- [x] 6.6 Report skipped broken links with `openspec workspace doctor` as the repair path
- [x] 6.7 Fail clearly when the selected opener executable is unavailable
- [x] 6.8 Include the `.code-workspace` path in VS Code opener availability errors
- [x] 6.9 Keep the selected opener as required when launching
- [x] 6.10 Add unit tests for launcher command construction using test doubles for external tools
## 7. Documentation And Command Metadata
- [x] 7.1 Update workspace command help for setup `--opener`, open positional name, `--workspace`, `--agent`, and `--editor`
- [x] 7.2 Update command registry and shell completion metadata for the new workspace open surface
- [x] 7.3 Update workspace documentation to describe preferred openers, editor open, agent open, and `.code-workspace` behavior
- [x] 7.4 Document that `.code-workspace` is machine-local and ignored by default
- [x] 7.5 Document that root workspace open supports exploration and planning, with implementation started by explicit user request
## 8. Verification
- [x] 8.1 Run `node bin/openspec.js validate workspace-open-agent-context --strict`
- [x] 8.2 Run targeted workspace command tests
- [x] 8.3 Run targeted workspace foundation tests
- [x] 8.4 Run command-generation or launcher tests that cover Codex, Claude, GitHub Copilot, and VS Code editor paths
- [x] 8.5 Run cross-platform path-focused tests for workspace open surfaces
- [x] 8.6 Run the relevant TypeScript test suite
- [x] 8.7 Run `pnpm run build`
@@ -0,0 +1,242 @@
## Context
Workspace setup already creates a planning home, records linked repos or folders, stores a preferred opener, and maintains the root open surface. For workspace change planning to work in practice, the opened agent also needs OpenSpec workflow skills available from that workspace root.
Repo-local `openspec init` and `openspec update` already provide the user model for choosing agent surfaces and generating skills. Workspace setup should feel similar, but the installation target is the workspace root rather than any linked repo or folder.
The existing artifact workflow assumes a change lives under a repo-local `openspec/changes/<id>` path. Workspace planning needs the same workflow vocabulary, but the planning home may be a workspace root and the implementation homes may be linked repos or folders.
## Goals / Non-Goals
**Goals:**
- Install OpenSpec agent skills into the workspace root during workspace setup.
- Use the active global profile to select which workflow skills are installed in the workspace.
- Let users choose which agents receive skills with familiar `--tools` semantics.
- Persist workspace-local agent skill selection so update can refresh the same agents later.
- Let users refresh, add, or remove workspace-local skills later through `workspace update`.
- Detect and report workspace-local skill drift from the active global profile.
- Let `openspec config profile` offer to apply changed profile settings to the current workspace when run from inside a workspace.
- Redirect workspace users from repo-local `openspec update` to `openspec workspace update`.
- Add a built-in workspace planning schema for workspace-scoped changes.
- Create workspace changes under the workspace planning path.
- Represent affected areas without forcing implementation artifacts into linked repos.
- Give agents machine-readable planning context through status/instructions output.
- Preserve the workspace boundary: linked repos and folders remain untouched during setup/update.
**Non-Goals:**
- Generating slash commands as part of workspace setup.
- Honoring global `delivery: commands` by generating workspace command files.
- Installing skills into linked repos or folders.
- Adding workspace-local workflow profiles separate from global config.
- Solving workspace-scoped artifact path discovery in the first setup-skill step.
- Adding a separate artifact-context CLI command in the first version.
- Implementing workspace apply, verify, or archive semantics end to end.
- Changing repo-local `openspec init` or `openspec update` behavior.
## Decisions
### Use agent-skill language in workspace UX
Workspace setup should ask, "Which agents should get OpenSpec skills in this workspace?" rather than using the broader "AI tools" wording. The user-visible action is installing skills for coding agents, and the target is the workspace planning home.
Alternative considered: reuse the exact `init` wording. That would be familiar, but it hides the important distinction between opening a workspace and installing skills into it.
### Reuse the existing tool id model
The CLI should use the existing `--tools all|none|<ids>` grammar for non-interactive setup and update. Reusing the existing tool IDs avoids inventing a second naming system for the same configured agents.
Alternative considered: add `--agents`. That reads better in isolation, but it creates unnecessary parallel vocabulary next to `openspec init --tools`.
### Let profile choose workflows and tools choose agents
Workspace setup/update should use the active global profile to decide which OpenSpec workflow skills are installed. The profile answers "which actions are available?" while `--tools` answers "which agents get those actions?" Keeping those concerns separate preserves the existing profile model and avoids adding workspace-local workflow selection in this slice.
If global profile is `core`, workspace skills should include the core workflow set. If global profile is `custom`, workspace skills should include only the configured custom workflows. `--tools none` should still mean no agent skills are installed, regardless of profile.
Alternative considered: add a workspace-local profile file. That might be useful later for team-shared workspace defaults, but this slice already stores machine-local agent paths and should avoid introducing another config authority before the global profile behavior works.
### Preselect the preferred opener when possible
Interactive setup should preselect the preferred opener when that opener maps to a skill-capable agent. The user can accept the default, add more agents, or deselect it.
Alternative considered: install skills only for the preferred opener. That is simpler, but opener choice means "how should I open this workspace" while skill selection means "which agents should understand OpenSpec here."
### Persist selected workspace skill agents locally
Workspace setup should store the selected skill-capable agents in `.openspec-workspace/local.yaml` because agent paths and installed tool surfaces are machine-local. Workspace update should use that stored selection when the user does not pass `--tools` or make a new interactive selection.
Explicit `--tools` on workspace setup/update should replace the stored selection. `--tools none` should store an empty selection and remove only known OpenSpec-managed workspace skill directories.
The local state should also record enough last-applied information to support drift detection, such as the workflow IDs installed for each selected agent and the effective global profile/delivery at the time of the last successful sync. This is diagnostic state, not a second source of truth.
Alternative considered: infer selected agents by scanning `.codex/skills/`, `.claude/skills/`, and similar directories. Scanning is useful as a fallback, but persisted selection gives predictable update behavior and avoids treating unrelated user-authored files as OpenSpec-managed state.
### Keep non-interactive setup backward-compatible
`openspec workspace setup --no-interactive` should not require `--tools`. If `--tools` is omitted, setup should create the workspace and skip skill installation, preserving existing scripted workspace setup behavior. Human and JSON output should say that no workspace skills were installed and that `openspec workspace update --tools <ids>` can add them later.
`openspec workspace update --no-interactive` without `--tools` should refresh the stored workspace skill agent selection. If no selection is stored, it should complete without installing skills and report a clear no-op with guidance to pass `--tools`.
Alternative considered: require `--tools` whenever workspace setup/update is non-interactive. That mirrors repo-local init, but it would break existing workspace setup scripts that predate workspace-local skill installation.
### Generate workspace-local skills only
Workspace setup/update should generate skills under the workspace root, such as `.codex/skills/` or `.claude/skills/`. It should not generate slash commands in this slice because some command adapters resolve to global locations, and workspace setup should remain local and predictable.
When global delivery is `commands` or `both`, workspace setup/update should still generate only skills and report that workspace command generation is not part of this slice. This keeps profile workflow selection useful without making workspace setup perform global or repo-local command writes.
Alternative considered: mirror `init` exactly and generate both skills and commands. That risks surprising global writes and makes the setup boundary harder to explain.
### Add `workspace update` for skill refresh
`openspec workspace update` should refresh, add, or remove workspace-local OpenSpec skills after setup. It should resolve the current workspace when run from inside a workspace, and also support named and non-interactive forms.
Workspace update should compare the active global profile's workflow selection with the last applied workspace skill state. If they differ, update should add/remove only OpenSpec-managed workflow skill directories for the selected agents. Workspace doctor/list/status surfaces may report the drift as a warning, and `openspec config profile` no-op inside a workspace should use the same drift check for guidance.
Alternative considered: reuse `openspec update` from inside the workspace. That command currently means repo/project update, while workspace update needs workspace selection, workspace JSON/status behavior, and linked-repo safety rules.
### Make `config profile` workspace-aware
`openspec config profile` should remain a global configuration command. When it runs inside a repo-local OpenSpec project and the user chooses to apply changes, it should continue to run `openspec update`.
When it runs inside an OpenSpec workspace and the profile or delivery settings actually change, it should prompt to apply changes to the current workspace. If confirmed, it should run `openspec workspace update` for that workspace. If declined, it should explain that the global config changed and the user can run `openspec workspace update` later.
The preset shortcut `openspec config profile core` should keep its non-interactive character and not launch an apply prompt. When run from inside a workspace, it should save global config and print workspace-specific follow-up guidance to run `openspec workspace update`. When run inside a repo-local project, it should keep the existing repo-local guidance.
For this slice, automatic workspace context should come from the workspace planning home and its own subdirectories. Running a command from inside a linked repo or folder should keep that location's repo-local behavior unless the user explicitly selects the workspace with a workspace command option. This avoids surprising repo-local commands merely because the repo is registered as a workspace link.
If a directory is both inside a workspace planning home and inside a repo-local OpenSpec project, the nearest planning home should determine the apply prompt. This avoids applying a workspace profile change to a linked repo when the user is intentionally operating from the workspace planning home.
Alternative considered: make `openspec config profile` update all known workspaces. That would be convenient in small setups, but global config changes should not fan out into multiple planning homes without an explicit per-workspace action.
### Resolve a planning home before acting
Workflow commands should resolve whether the current change belongs to a repo-local planning home or a workspace planning home before computing paths. The resolver should identify the planning root, change root, linked areas when present, and whether implementation edits are allowed. Linked repos are not implicitly treated as workspace planning homes just because they are registered in a workspace; workspace-scoped behavior is selected from the workspace planning home or through explicit workspace selection.
Alternative considered: add workspace-specific command branches wherever paths are used. That would make the workspace model leak into every workflow and make generated skills more fragile.
### Store workspace changes in the workspace planning path
Workspace changes should live under the workspace planning path, initially `changes/<id>` at the workspace root. Creating the workspace change should capture shared intent once and may record affected areas, but it should not create repo-local `openspec/changes/<id>` directories in linked repos.
Alternative considered: materialize a repo-local change in every affected repo during workspace change creation. That was easy to reason about in the POC, but it commits too early and makes exploration look like implementation.
### Add a workspace planning schema
Workspace-scoped changes should use a built-in `workspace-planning` schema by default. This keeps the workflow verbs familiar while letting workspace changes have a structure that fits cross-area planning.
Initial artifact shape:
```text
changes/<id>/
.openspec.yaml # schema: workspace-planning
proposal.md # shared goal and scope
design.md # cross-area decisions
tasks.md # coordination tasks, optionally grouped by affected area
specs/
<area-or-repo>/
<capability>/spec.md
```
The first schema should stay intentionally close to the normal OpenSpec artifact shape: proposal, specs, design, and tasks. Area-specific requirements live under `specs/` and area-specific work can be represented as sections in `tasks.md`. This slice does not introduce another area manifest beside those normal planning artifacts.
Alternative considered: reuse `spec-driven` unchanged and make all workspace differences implicit in status output. That hides the fact that workspace planning needs different instructions for organizing requirements and tasks by affected area.
Alternative considered: create separate workspace workflow skills instead of a schema. That would duplicate workflow guidance and make workspace mode feel like a different product.
### Support nested workspace spec paths in the schema
The `workspace-planning` schema should define its specs artifact so nested workspace paths are first-class, not accidental. The intended output pattern is `specs/**/*.md`, and the schema instructions should explicitly describe `specs/<area-or-repo>/<capability>/spec.md` as the default convention for area-specific requirements.
Status and instructions output should preserve the concrete nested paths it discovers. Repo-local spec sync, archive, and validation paths that assume `specs/<capability>/spec.md` should not treat workspace-scoped specs as repo-local capability specs until a later explicit implementation, sync, or archive workflow selects an affected area and defines the destination.
### Use affected areas, not targets or repo slices
The planning model should call ownership or implementation boundaries "affected areas." Affected areas can start with registered workspace link names, but the language should leave room for folders, packages, services, apps, or docs sites. Delivery breakdown remains a separate concept and should not be called an area.
Alternative considered: keep "targets" because it maps to the old POC flag. That term is implementation-first and encourages users to choose repos before the plan is clear.
### Make status JSON the agent context contract
`openspec status --change <id> --json` should become the primary source of machine-readable action context. It should include the planning home, change root, concrete artifact paths, affected areas, next steps, and constraints such as allowed edit roots when implementation is later in scope.
Alternative considered: create a separate context command immediately. Status is already used by generated workflow skills, so enriching it first gives agents a single place to look.
### Keep generated skills path-agnostic
Generated workflow skills should ask OpenSpec where artifacts live instead of embedding repo-local paths such as `openspec/changes/<name>`. The standard skill pattern should be:
```text
1. Run `openspec status --change "<name>" --json`.
2. Use the returned planning home, artifacts, next steps, and action context.
3. Run `openspec instructions <artifact> --change "<name>" --json` before writing an artifact.
4. Write to the resolved path returned by the CLI.
```
This keeps the same skill usable in repo-local and workspace-scoped changes. If status/instructions output later becomes too crowded, a separate context command can be introduced in a future change without changing the high-level skill rule.
Alternative considered: add a new `openspec context` command now. That may become useful, but it adds a new surface before we have proven that enriched status/instructions are insufficient.
### Guard unsupported workspace workflow actions
The global profile may select workflows whose workspace-scoped behavior is not implemented in this slice, such as full workspace apply, verify, or archive. Generated workspace-local skills for those workflows should be safe: they should inspect status/instructions, explain the unsupported workspace action, and avoid editing linked repos unless a later explicit implementation workflow supplies an allowed edit root.
This keeps the workspace skill set aligned with the user's profile while preventing repo-local fallbacks from pretending to implement workspace semantics.
Alternative considered: filter unsupported workflows out of workspace skill generation. That would avoid unsupported commands, but it would make the workspace skill set silently diverge from the user's profile and make drift harder to explain.
### Redirect repo update from workspace roots
`openspec update` should remain the repo/project update command. When it is run from an OpenSpec workspace planning home, it should not try to treat the workspace as a repo-local project. It should fail or redirect with clear guidance to run `openspec workspace update`.
Alternative considered: make `openspec update` polymorphic and perform workspace update inside workspaces. That would be convenient, but it blurs the repo/project versus workspace boundary this change is trying to make explicit.
### Update docs, help, and completions
The CLI help, command registry/completions, and user docs should include `openspec workspace update`, its `--tools` behavior, the global-profile relationship, and the skills-only workspace delivery rule.
Alternative considered: document this only after implementation. Because profile/update behavior is easy to confuse with repo-local update, the docs and help updates are part of the user-facing feature.
### Treat manual acceptance and UX review as phase gates
Each phase should produce a user-testable increment, even when most of the work is internal. The phase is not done until a user can exercise the named behavior through the CLI, inspect the resulting output or files, and understand what changed.
Each implementation phase should include a manual acceptance pass in addition to automated tests. The manual pass should exercise the real CLI flow, inspect the generated files or output, and confirm linked repos or folders stay untouched where that is part of the contract.
Each phase should also include a lightweight UX review of prompts, command forms, human output, JSON output, artifact paths, and next-step guidance. Any confusing UX found during review should be fixed in the same phase or recorded as an intentional follow-up before the phase is considered done.
Alternative considered: keep manual review only in the final verification phase. That would catch end-to-end issues late, but workspace planning is mostly workflow and agent-facing UX, so each phase needs its own human check while the behavior is still fresh.
### Reduce self-validation bias with evidence-based review
Implementation should define acceptance evidence before marking tasks done. For each phase, the implementer should capture the exact manual commands or interaction path, expected observations, and actual observations. A task is not complete merely because the implementer believes the code matches the design.
When practical, a separate reviewer or fresh agent context should run the manual acceptance checklist and UX review using only the change artifacts, CLI output, and observed filesystem state. If a separate reviewer is not available, the implementer should rerun the checklist from a clean temporary workspace and record the evidence in the change notes or final implementation summary.
Alternative considered: rely on automated tests plus the implementer's final review. Automated tests are necessary, but this change is workflow-heavy and agent-facing, so independent evidence is more useful than confidence alone.
## Deferred Direction
The earlier product notes pointed at a richer workspace model than this slice ships. Keep that direction as follow-up material, not competing current scope.
- Full workspace apply should select or confirm one work focus before implementation. The first work focus should be an affected area with an allowed edit root; later work may add an optional delivery phase when a large change needs sequencing. Until that model exists, workspace apply/verify/archive skills remain guarded.
- Workspace verify and archive should wait for a clear model of partial area completion, final whole-change completion, and how workspace-scoped specs become repo-local canonical specs.
- Scoped plan files may eventually attach at the change, phase, affected-area, or work-focus level. This slice intentionally keeps the first workspace schema close to normal OpenSpec artifacts: proposal, specs, design, and tasks.
- Affected areas can start as registered workspace link names, but future flows may refine or derive them from planning artifacts. That derivation should avoid reintroducing target-first or repo-slice language.
- Workflow skills may later separate generic OpenSpec workflow semantics from agent-specific affordances such as asking questions, tracking todos, or delegating work. This slice only makes generated workflow skills path-agnostic.
- OpenSpec may need a named exploratory-notes convention for preserving unsettled thinking before it is promoted into proposal, design, specs, or tasks. This cleanup keeps the current change folder focused on standard artifacts.
## Risks / Trade-offs
- Skill generation logic may drift from `init/update` → share the same template generation and tool validation helpers where practical.
- Removing unselected skills could remove user-modified files → remove only known OpenSpec-managed workflow skill directories by explicit workflow list.
- `--tools` is less precise than `--agents` in workspace UX → keep `--tools` for CLI consistency, but use "agents" in prompts and human output.
- Global delivery can say `commands` while workspace update remains skills-only → report this explicitly so users know command generation is deferred, not silently broken.
- `config profile` may run from a linked repo inside an opened workspace → resolve the current planning home carefully and apply only to that home.
- Stored workspace skill state can become stale or hand-edited → treat it as diagnostic machine-local state and always reconcile managed files from the active global profile during update.
- Profile-selected workflows may not yet have full workspace semantics → generated skills must guard unsupported actions and avoid repo-local fallbacks.
- Existing generated skills still contain repo-local path assumptions → handle that as a later artifact-context step after workspace-local skills can be installed.
- Status JSON may become too broad → keep fields plain and action-oriented, such as `planningHome`, `artifacts`, `affectedAreas`, `nextSteps`, and `actionContext`.
- Affected area discovery may be ambiguous → start with explicit registered workspace links and allow later refinement instead of parsing free-form Markdown headings as the only source of truth.
- A new schema can drift from repo-local workflow expectations → keep artifact IDs plain and make status/instructions carry the schema-specific paths.
- Skill instructions may lag behind CLI behavior → audit source workflow templates for hardcoded repo-local paths and replace them with the path-agnostic status/instructions pattern.
@@ -0,0 +1,78 @@
## Why
Once repos are visible and the agent has workspace context, the user should be able to plan a cross-repo change without creating repo-local artifacts before implementation starts.
The user goal is:
```text
Explore the product goal across repos.
Decide the scope.
Create one workspace-level proposal that identifies the affected areas.
```
Planning should be the commitment point. Repo visibility alone should remain lightweight.
## What Changes
Add workspace-level change planning:
- install and refresh OpenSpec agent skills from the workspace root so agents can operate from the planning home
- use the active global workflow profile to decide which workflow skills are installed in the workspace
- keep `--tools` focused on which agents receive those workspace-local skills
- add a workspace-specific planning schema for workspace changes
- create a workspace change from the coordination root
- capture the product goal once
- identify affected areas by registered workspace link name where applicable
- let the agent explore before committing to affected areas or delivery slices
- keep the workspace as the planning source of truth
- update workflow skill instructions to use CLI-reported artifact paths instead of hardcoded repo-local paths
This slice should avoid creating repo-local artifacts as a side effect of planning. Repo-local artifacts should not be created merely because a workspace change exists.
Workspace setup and update may write agent skill files into the workspace root, such as `.codex/skills/` or `.claude/skills/`, because those files make the workspace planning home usable by agents. That setup work must not write OpenSpec artifacts or agent skill files into linked repos or folders.
Interactive setup should ask which agents should get OpenSpec skills in the workspace, preselecting the preferred opener when that opener supports skills. Workspace update should let users refresh or change those installed agent skills later, including when run from inside the workspace.
Workspace setup and update should treat the global profile as the workflow selection source. For this slice, workspace setup and update are skills-only even when global delivery is `commands` or `both`; command generation for workspaces is deferred.
`openspec config profile` should remain global, but when it runs from inside an OpenSpec workspace and changes the global profile or delivery settings, it should offer to apply the new workflow selection to the current workspace by running `openspec workspace update`.
Workspace-local skill selection should be machine-local state: setup records which agents received skills, update refreshes that stored selection by default, and explicit `--tools` changes the stored selection. OpenSpec should detect when workspace-local skills drift from the current global profile and give clear update guidance.
Selected profile workflows that are not yet fully implemented for workspace-scoped changes should still be safe. Generated skills and CLI guidance must guard unsupported workspace actions instead of falling back to repo-local behavior or editing linked repos implicitly.
Workspace help, docs, and completions should make the distinction legible: `openspec update` remains repo/project sync, while `openspec workspace update` syncs workspace-local agent skills.
Planning dependency:
- Depends on `workspace-open-agent-context`.
## Capabilities
### New Capabilities
- `workspace-change-planning`: Creates and manages workspace-level proposals for cross-repo goals.
### Modified Capabilities
- `workspace-links`: Adds workspace setup/update behavior for workspace-local agent skill installation.
- `cli-config`: Makes `openspec config profile` aware of workspace roots and able to apply global profile changes to the current workspace.
- `change-creation`: Adds workspace-aware change creation semantics and affected area identification.
- `cli-artifact-workflow`: Enriches workflow status and instructions so agents can discover planning context and artifact paths without hardcoded repo-local assumptions.
- `artifact-graph`: Adds a built-in workspace planning schema for workspace-scoped changes.
- `schema-resolution`: Ensures workspace-scoped change creation and workflow commands can resolve the workspace planning schema.
- `openspec-conventions`: Defines the relationship between workspace-level planning and repo-local implementation work.
## Impact
- Workspace change creation.
- Workspace-specific planning schema and templates.
- Affected area metadata and validation.
- Workspace setup and update behavior for installing or refreshing agent skills in the workspace root.
- Global profile integration for workspace-local skill workflow selection.
- Workspace-aware `openspec config profile` apply prompt behavior.
- Workspace-local agent skill selection state and drift detection.
- Guarded workflow guidance for profile workflows whose workspace behavior is not implemented in this slice.
- Docs, help, and completions for workspace skill update behavior.
- Agent instructions for proposing cross-repo changes without hardcoded change paths.
- Tests that registered repos are visible before change creation and that creating a change does not imply repo-local artifact creation.
@@ -0,0 +1,36 @@
## ADDED Requirements
### Requirement: Workspace planning schema
The artifact graph SHALL provide a built-in workspace planning schema for workspace-scoped changes.
#### Scenario: Built-in workspace planning schema is available
- **WHEN** schemas are resolved from package built-ins
- **THEN** a schema named `workspace-planning` SHALL be available
- **AND** it SHALL describe the artifact structure for workspace-scoped planning
#### Scenario: Workspace planning schema artifacts
- **WHEN** the `workspace-planning` schema is loaded
- **THEN** it SHALL include the normal planning artifacts for a shared proposal, workspace-scoped specs, cross-area design, and coordination tasks
- **AND** it SHALL not require an additional area manifest outside those normal planning artifacts
#### Scenario: Workspace planning schema supports nested specs
- **WHEN** the `workspace-planning` schema defines its specs artifact
- **THEN** the specs artifact SHALL resolve workspace-scoped spec files under `specs/**/*.md`
- **AND** schema guidance SHALL describe `specs/<area-or-repo>/<capability>/spec.md` as the default convention for area-specific requirements
#### Scenario: Workspace planning schema templates
- **WHEN** artifact instructions are requested for the `workspace-planning` schema
- **THEN** the schema SHALL provide templates that guide agents to write workspace-level planning content
- **AND** those templates SHALL avoid instructing agents to create repo-local implementation artifacts
- **AND** specs instructions SHALL support organizing area-specific requirements under workspace-scoped `specs/` paths
#### Scenario: Workspace nested spec paths stay workspace-scoped
- **GIVEN** a workspace change has spec files under `specs/<area-or-repo>/<capability>/spec.md`
- **WHEN** OpenSpec reports status or artifact instructions for the workspace change
- **THEN** it SHALL preserve the concrete nested workspace spec paths
- **AND** it SHALL not treat those files as repo-local specs to sync or archive without an explicit affected-area implementation context
#### Scenario: Workspace planning apply readiness
- **WHEN** the `workspace-planning` schema defines apply readiness
- **THEN** it SHALL require coordination tasks before implementation begins
- **AND** the apply guidance SHALL direct agents to select an affected area before making implementation edits
@@ -0,0 +1,42 @@
## ADDED Requirements
### Requirement: Workspace-aware change creation
Change creation SHALL support both repo-local and workspace planning homes.
#### Scenario: Creating a change from a workspace root
- **GIVEN** the command runs from an OpenSpec workspace root
- **WHEN** the user creates a new change
- **THEN** OpenSpec SHALL create the change under the workspace planning path
- **AND** it SHALL not create the change under a linked repo's `openspec/changes/` directory
- **AND** it SHALL use the `workspace-planning` schema when no explicit schema is provided
#### Scenario: Creating a change from inside a workspace
- **GIVEN** the command runs from a subdirectory of an OpenSpec workspace planning home
- **WHEN** the user creates a new change
- **THEN** OpenSpec SHALL resolve the current workspace as the planning home
- **AND** it SHALL create the change under that workspace's planning path
- **AND** it SHALL use the `workspace-planning` schema when no explicit schema is provided
#### Scenario: Creating a change from inside a linked repo
- **GIVEN** a repo or folder is registered as a workspace link
- **AND** the command runs from inside that linked repo or folder rather than from the workspace planning home
- **WHEN** the user creates a new change without explicitly selecting a workspace
- **THEN** OpenSpec SHALL preserve repo-local change creation behavior for that location
- **AND** it SHALL not create a workspace-scoped change merely because the location is registered as a workspace link
#### Scenario: Preserving repo-local change creation
- **GIVEN** the command runs outside an OpenSpec workspace
- **WHEN** the user creates a new change in a repo-local OpenSpec project
- **THEN** OpenSpec SHALL continue to create the change under `openspec/changes/`
#### Scenario: Rejecting invalid workspace affected areas
- **GIVEN** a workspace change creation request includes affected area names
- **WHEN** one or more names are not registered workspace links
- **THEN** OpenSpec SHALL reject those invalid affected areas
- **AND** it SHALL list the valid workspace link names
#### Scenario: Creating without affected areas
- **GIVEN** the user is still exploring scope
- **WHEN** the user creates a workspace change without affected areas
- **THEN** OpenSpec SHALL create the workspace change
- **AND** it SHALL allow affected areas to be identified later
@@ -0,0 +1,100 @@
## ADDED Requirements
### Requirement: Status JSON provides planning context
The status command SHALL provide machine-readable planning context for repo-local and workspace changes.
#### Scenario: Reporting planning home
- **WHEN** a user runs `openspec status --change <id> --json`
- **THEN** the output SHALL identify whether the change is repo-local or workspace-scoped
- **AND** it SHALL include the planning home root and change root
#### Scenario: Reporting concrete artifact paths
- **WHEN** a user runs `openspec status --change <id> --json`
- **THEN** the output SHALL include concrete paths for existing artifacts
- **AND** agents SHALL be able to read those paths without assuming `openspec/changes/<id>/`
- **AND** workspace-scoped nested spec paths SHALL be reported without flattening the area or capability path
#### Scenario: Reporting workspace affected areas
- **GIVEN** the change is workspace-scoped
- **WHEN** a user runs `openspec status --change <id> --json`
- **THEN** the output SHALL include known affected areas
- **AND** it SHALL indicate when affected areas remain unresolved without requiring an additional area manifest artifact
#### Scenario: Reporting next steps
- **WHEN** a user runs `openspec status --change <id> --json`
- **THEN** the output SHALL include next step guidance for agents
- **AND** the guidance SHALL use plain action language
### Requirement: Status JSON action context
The status command SHALL expose action context that lets agents act without hardcoded filesystem assumptions.
#### Scenario: Planning action context
- **WHEN** a workspace change is still in planning
- **THEN** status JSON SHALL identify the planning artifacts agents may read or update
- **AND** it SHALL indicate that linked repos and folders are context for exploration
#### Scenario: Implementation action context
- **WHEN** a workspace change has a selected affected area for implementation
- **THEN** status JSON SHALL include the allowed edit root for that area
- **AND** it SHALL avoid authorizing edits outside that selected area
#### Scenario: Repo-local action context
- **GIVEN** the change is repo-local
- **WHEN** a user runs `openspec status --change <id> --json`
- **THEN** status JSON SHALL preserve existing artifact status behavior
- **AND** it SHALL report a repo-local planning home for agents that use action context
### Requirement: Instructions use resolved planning paths
Artifact and apply instructions SHALL use resolved planning paths rather than hardcoded repo-local change paths.
#### Scenario: Workspace artifact instructions
- **GIVEN** the change is workspace-scoped
- **WHEN** a user runs `openspec instructions <artifact> --change <id> --json`
- **THEN** instruction output SHALL point to the artifact path under the workspace change root
- **AND** it SHALL not instruct the agent to write under a linked repo unless an explicit implementation context allows it
#### Scenario: Repo-local artifact instructions
- **GIVEN** the change is repo-local
- **WHEN** a user runs `openspec instructions <artifact> --change <id> --json`
- **THEN** instruction output SHALL preserve existing repo-local paths
### Requirement: Workflow skills use CLI artifact context
Generated workflow skills SHALL use OpenSpec CLI output as the source of truth for artifact locations.
#### Scenario: Skills inspect status before artifact work
- **WHEN** a generated workflow skill needs to inspect or create artifacts for a change
- **THEN** it SHALL instruct the agent to run `openspec status --change <id> --json`
- **AND** it SHALL use returned planning context and artifact paths rather than assuming a repo-local change path
#### Scenario: Skills use instructions before writing artifacts
- **WHEN** a generated workflow skill is about to create or update an artifact
- **THEN** it SHALL instruct the agent to run `openspec instructions <artifact> --change <id> --json`
- **AND** it SHALL write to the resolved artifact path returned by the command
#### Scenario: Skills avoid hardcoded repo-local paths
- **WHEN** generated workflow skills describe artifact locations
- **THEN** they SHALL avoid hardcoded examples that require changes to live under `openspec/changes/<id>/`
- **AND** any examples SHALL defer to CLI-reported paths for repo-local and workspace-scoped changes
#### Scenario: Skills guard unsupported workspace workflows
- **GIVEN** a generated workflow skill is selected by the global profile
- **AND** the workflow does not yet have full workspace-scoped behavior in this slice
- **WHEN** the skill is used for a workspace-scoped change
- **THEN** it SHALL tell the agent that the workspace action is not supported yet
- **AND** it SHALL not instruct the agent to fall back to repo-local paths or edit linked repos without an explicit allowed edit root
### Requirement: Workspace schema instructions
Workflow commands SHALL use the workspace planning schema instructions for workspace-scoped changes that use that schema.
#### Scenario: Workspace planning artifact order
- **GIVEN** a workspace-scoped change uses schema `workspace-planning`
- **WHEN** a user runs `openspec status --change <id> --json`
- **THEN** the artifact list SHALL reflect the workspace planning schema
- **AND** it SHALL include the normal proposal, specs, design, and tasks artifacts
#### Scenario: Workspace specs instructions
- **GIVEN** a workspace-scoped change uses schema `workspace-planning`
- **WHEN** a user requests instructions for the specs artifact
- **THEN** instruction output SHALL guide the agent to organize area-specific requirements under workspace-scoped `specs/` paths
- **AND** it SHALL not require all affected areas to be finalized before planning can continue
- **AND** it SHALL not instruct the agent to create repo-local spec files while the change is still in workspace planning
@@ -0,0 +1,55 @@
## ADDED Requirements
### Requirement: Config profile applies to current workspace
The `openspec config profile` command SHALL remain global while offering an explicit workspace apply path when run from inside an OpenSpec workspace.
#### Scenario: Config profile run inside a workspace
- **GIVEN** the command runs from inside an OpenSpec workspace
- **WHEN** the user changes profile or delivery settings with interactive `openspec config profile`
- **THEN** OpenSpec SHALL save the global config changes
- **AND** it SHALL prompt: `Apply changes to this workspace now?`
#### Scenario: User confirms workspace apply
- **GIVEN** `openspec config profile` changed global profile or delivery settings inside a workspace
- **WHEN** the user confirms the workspace apply prompt
- **THEN** OpenSpec SHALL run `openspec workspace update` for the current workspace
- **AND** it SHALL not run repo-local `openspec update` unless the current planning home is repo-local
#### Scenario: User declines workspace apply
- **GIVEN** `openspec config profile` changed global profile or delivery settings inside a workspace
- **WHEN** the user declines the workspace apply prompt
- **THEN** OpenSpec SHALL explain that global config was updated
- **AND** it SHALL tell the user to run `openspec workspace update` later to apply the profile to workspace-local skills
- **AND** it SHALL not modify workspace skill files
#### Scenario: No-op inside workspace
- **GIVEN** the command runs from inside an OpenSpec workspace
- **WHEN** `openspec config profile` exits with no effective config changes
- **THEN** OpenSpec SHALL not prompt to apply changes
- **AND** it SHALL warn if workspace-local skills are out of sync with the current global profile
- **AND** the warning SHALL suggest `openspec workspace update`
#### Scenario: Core preset shortcut inside a workspace
- **GIVEN** the command runs from inside an OpenSpec workspace
- **WHEN** the user runs `openspec config profile core`
- **THEN** OpenSpec SHALL save the global config change without prompting to apply immediately
- **AND** it SHALL tell the user to run `openspec workspace update` to apply the profile to workspace-local skills
#### Scenario: Core preset shortcut inside a repo project
- **GIVEN** the command runs from inside a repo-local OpenSpec project
- **WHEN** the user runs `openspec config profile core`
- **THEN** OpenSpec SHALL preserve existing repo-local shortcut behavior
- **AND** it SHALL tell the user to run `openspec update` to apply the profile to project files
#### Scenario: Workspace planning home wins over linked repo project
- **GIVEN** the command runs in a path under a workspace planning home where a repo-local OpenSpec project could also be detected
- **WHEN** OpenSpec decides which apply prompt to show
- **THEN** the nearest current planning home SHALL determine whether to offer `openspec workspace update` or repo-local `openspec update`
- **AND** OpenSpec SHALL not apply profile changes to a linked repo when the current planning home is the workspace
#### Scenario: Linked repo keeps repo-local profile behavior
- **GIVEN** a repo-local OpenSpec project is registered as a workspace link
- **AND** the command runs from inside that linked repo rather than from the workspace planning home
- **WHEN** OpenSpec decides which apply prompt or guidance to show
- **THEN** OpenSpec SHALL preserve repo-local `openspec update` behavior for that repo
- **AND** it SHALL not offer `openspec workspace update` unless the workspace is explicitly selected
@@ -0,0 +1,21 @@
## ADDED Requirements
### Requirement: Repo update redirects from workspace planning homes
The repo-local `openspec update` command SHALL not silently treat a workspace planning home as a repo-local OpenSpec project.
#### Scenario: Running update from a workspace root
- **GIVEN** the command runs from an OpenSpec workspace root
- **WHEN** the user runs `openspec update`
- **THEN** OpenSpec SHALL not generate repo-local project files in the workspace root
- **AND** it SHALL tell the user to run `openspec workspace update`
#### Scenario: Running update from inside a workspace planning directory
- **GIVEN** the command runs from a subdirectory of an OpenSpec workspace planning home
- **WHEN** the user runs `openspec update`
- **THEN** OpenSpec SHALL not run repo-local update behavior
- **AND** it SHALL tell the user to run `openspec workspace update`
#### Scenario: Running update from a repo-local project
- **GIVEN** the command runs from inside a repo-local OpenSpec project
- **WHEN** the user runs `openspec update`
- **THEN** OpenSpec SHALL preserve existing repo-local update behavior
@@ -0,0 +1,32 @@
## ADDED Requirements
### Requirement: Workspace planning vocabulary
OpenSpec conventions SHALL distinguish workspace planning concepts using user-facing product language.
#### Scenario: Naming affected areas
- **WHEN** documentation or generated guidance refers to repos, folders, packages, services, apps, or docs sites touched by a workspace change
- **THEN** it SHALL call them affected areas
- **AND** it SHALL avoid using "target repo" or "repo slice" as the primary user-facing term
#### Scenario: Naming delivery slices
- **WHEN** documentation or generated guidance refers to delivery increments inside a larger change
- **THEN** it SHALL call them slices or phases only when delivery sequencing is the subject
- **AND** it SHALL not use slice as a synonym for repo, folder, or affected area
### Requirement: Workspace planning and implementation boundary
OpenSpec conventions SHALL distinguish workspace-level planning from repo-local implementation ownership.
#### Scenario: Workspace as shared planning home
- **WHEN** a change spans linked repos or folders
- **THEN** conventions SHALL describe the workspace as the shared planning home
- **AND** repo-local implementation homes SHALL retain ownership of their code and canonical behavior
#### Scenario: Avoiding materialization-first language
- **WHEN** documentation explains workspace change creation
- **THEN** it SHALL describe the user outcome in terms of shared planning and affected areas
- **AND** it SHALL avoid making users understand implementation terms such as materialization before they can plan
#### Scenario: Preserving familiar workflow verbs
- **WHEN** workspace guidance describes OpenSpec workflows
- **THEN** it SHALL keep the familiar verbs explore, propose, apply, verify, and archive
- **AND** it SHALL explain that workspace context changes paths, scope, and allowed edit roots rather than creating a separate workflow family
@@ -0,0 +1,25 @@
## ADDED Requirements
### Requirement: Workspace planning schema resolution
Schema resolution SHALL support the built-in workspace planning schema.
#### Scenario: Listing workspace planning schema
- **WHEN** a user runs `openspec schemas`
- **THEN** the output SHALL include `workspace-planning`
- **AND** it SHALL identify it as a package-provided schema unless overridden by a higher-precedence schema
#### Scenario: Resolving workspace planning schema by name
- **WHEN** a workflow command requests schema `workspace-planning`
- **THEN** schema resolution SHALL resolve it using the normal project, user, then package precedence order
#### Scenario: Workspace default schema for new changes
- **GIVEN** the command creates a change in a workspace planning home
- **AND** the user did not pass an explicit `--schema`
- **WHEN** OpenSpec resolves the schema for the new change
- **THEN** it SHALL use `workspace-planning` as the default schema
#### Scenario: Explicit schema override for workspace change
- **GIVEN** the command creates a change in a workspace planning home
- **WHEN** the user passes an explicit `--schema <name>`
- **THEN** OpenSpec SHALL use the explicitly requested schema
- **AND** it SHALL validate that schema using normal schema resolution
@@ -0,0 +1,67 @@
## ADDED Requirements
### Requirement: Workspace change planning home
OpenSpec SHALL support workspace-level changes whose shared plan lives in the workspace planning home.
#### Scenario: Creating a workspace change
- **GIVEN** the command runs from an OpenSpec workspace
- **WHEN** the user creates a change for workspace planning
- **THEN** OpenSpec SHALL create the change under the workspace planning path
- **AND** it SHALL treat the workspace as the planning home for that change
- **AND** it SHALL use the workspace planning schema when no explicit schema is provided
#### Scenario: Workspace planning artifact structure
- **GIVEN** a workspace change uses the workspace planning schema
- **WHEN** OpenSpec reports or creates planning artifacts for that change
- **THEN** it SHALL use workspace-level artifacts for proposal, specs, cross-area design, and coordination tasks
- **AND** those artifacts SHALL live under the workspace change root
- **AND** it SHALL not require an additional area manifest outside those normal planning artifacts
#### Scenario: Capturing the shared goal once
- **WHEN** a workspace change is proposed
- **THEN** OpenSpec SHALL capture the product goal at the workspace change level
- **AND** it SHALL avoid requiring separate repo-local proposals before the affected areas are understood
#### Scenario: Preserving linked repos during change creation
- **WHEN** OpenSpec creates a workspace-level change
- **THEN** it SHALL not create repo-local OpenSpec change directories inside linked repos or folders
- **AND** it SHALL not edit implementation files in linked repos or folders
### Requirement: Workspace affected areas
OpenSpec SHALL represent ownership or implementation boundaries in a workspace change as affected areas.
#### Scenario: Using registered workspace links as areas
- **GIVEN** a workspace has linked repos or folders
- **WHEN** a workspace change identifies affected areas by registered link name
- **THEN** OpenSpec SHALL validate those area names against the workspace links
- **AND** it SHALL report invalid area names clearly
#### Scenario: Planning before all areas are known
- **WHEN** a user is still exploring a workspace change
- **THEN** OpenSpec SHALL allow the shared plan to exist before all affected areas are finalized
- **AND** it SHALL keep unresolved affected area questions visible in the normal planning artifacts and status output
#### Scenario: Organizing requirements by area
- **GIVEN** a workspace change has requirements owned by one or more affected areas
- **WHEN** OpenSpec reports or creates workspace-scoped specs
- **THEN** it SHALL allow area-specific requirements to be organized under `specs/<area-or-repo>/<capability>/spec.md`
- **AND** it SHALL not require separate area folders outside the normal `specs/` artifact tree
- **AND** it SHALL preserve the area-or-repo path segment as workspace planning context rather than flattening it into a repo-local capability name
#### Scenario: Separating areas from delivery slices
- **WHEN** a workspace change reports affected areas
- **THEN** OpenSpec SHALL distinguish affected areas from delivery slices or phases
- **AND** it SHALL not require users to define delivery slices for a small cross-area change
### Requirement: Workspace planning source of truth
OpenSpec SHALL keep the workspace change plan as the source of truth until implementation begins for a selected affected area.
#### Scenario: Exploring before implementation
- **WHEN** an agent explores a workspace change
- **THEN** it SHALL use workspace-level planning artifacts as the shared planning source
- **AND** it SHALL treat linked repos and folders as available context rather than committed implementation targets
#### Scenario: Deferring repo-local implementation
- **WHEN** repo-local implementation work is needed for a workspace change
- **THEN** OpenSpec SHALL require an explicit implementation workflow with a selected affected area
- **AND** it SHALL expose the allowed edit root for that selected area before implementation edits begin
@@ -0,0 +1,163 @@
## ADDED Requirements
### Requirement: Workspace setup installs agent skills
OpenSpec SHALL let users install OpenSpec agent skills into a workspace during workspace setup.
#### Scenario: Prompting for workspace agent skills
- **WHEN** interactive workspace setup reaches agent skill installation
- **THEN** OpenSpec SHALL ask which agents should get OpenSpec skills in this workspace
- **AND** the prompt SHALL use agent-skill language rather than "AI tools" language
#### Scenario: Preselecting the preferred opener
- **GIVEN** the user selected a preferred opener that supports OpenSpec skill generation
- **WHEN** interactive workspace setup asks which agents should get skills
- **THEN** OpenSpec SHALL preselect the matching agent
- **AND** the user SHALL be able to select additional agents or deselect the preselected agent
#### Scenario: Installing selected workspace skills
- **WHEN** workspace setup completes with one or more selected agents
- **THEN** OpenSpec SHALL generate or refresh OpenSpec skill files under the workspace root for each selected agent
- **AND** it SHALL report which agents received skills
- **AND** it SHALL store the selected agents in workspace-local machine state
#### Scenario: Installing profile-selected workflows
- **GIVEN** global config resolves to a workflow profile
- **WHEN** workspace setup installs agent skills
- **THEN** OpenSpec SHALL install workspace-local skills for the workflows selected by that profile
- **AND** it SHALL treat `--tools` as agent selection, not workflow selection
- **AND** it SHALL record the last applied workflow IDs for drift detection
#### Scenario: Installing skills only during setup
- **WHEN** workspace setup installs agent skills
- **THEN** OpenSpec SHALL generate skill files only
- **AND** it SHALL not generate slash command files or global command files as part of workspace setup
#### Scenario: Ignoring command delivery for workspace setup
- **GIVEN** global config delivery is `commands` or `both`
- **WHEN** workspace setup installs agent skills
- **THEN** OpenSpec SHALL still generate workspace-local skills only
- **AND** it SHALL report that workspace command generation is not part of this slice
#### Scenario: Preserving linked repos during skill installation
- **WHEN** workspace setup installs agent skills
- **THEN** OpenSpec SHALL leave linked repos and folders unchanged
- **AND** generated skills SHALL be scoped to the workspace planning home
#### Scenario: Non-interactive setup tool selection
- **WHEN** non-interactive workspace setup receives `--tools all`, `--tools none`, or `--tools <ids>`
- **THEN** OpenSpec SHALL use the selected tool set for workspace agent skill installation
- **AND** it SHALL validate tool IDs using the same supported tool IDs as skill generation for repo initialization
#### Scenario: Non-interactive setup without tool selection
- **WHEN** non-interactive workspace setup omits `--tools`
- **THEN** OpenSpec SHALL create the workspace without installing agent skills
- **AND** it SHALL report that no workspace skills were installed
- **AND** it SHALL tell the user to run `openspec workspace update --tools <ids>` to install skills later
#### Scenario: Reporting setup skills in JSON output
- **WHEN** non-interactive workspace setup installs agent skills with JSON output enabled
- **THEN** OpenSpec SHALL include generated, refreshed, skipped, or failed skill installation results in machine-readable output
### Requirement: Workspace update manages agent skills
OpenSpec SHALL provide a workspace update flow for refreshing agent skills after setup.
#### Scenario: Updating the current workspace
- **GIVEN** the command runs from inside an OpenSpec workspace
- **WHEN** the user runs `openspec workspace update`
- **THEN** OpenSpec SHALL update that current workspace
#### Scenario: Updating a named workspace
- **GIVEN** a workspace named `platform` is known locally
- **WHEN** the user runs `openspec workspace update platform`
- **THEN** OpenSpec SHALL update the `platform` workspace
#### Scenario: Updating a workspace selected by flag
- **GIVEN** a workspace named `platform` is known locally
- **WHEN** the user runs `openspec workspace update --workspace platform`
- **THEN** OpenSpec SHALL update the `platform` workspace
#### Scenario: Updating selected workspace skills
- **WHEN** workspace update completes with selected agents
- **THEN** OpenSpec SHALL refresh OpenSpec skills for selected agents
- **AND** it SHALL add skills for newly selected agents
- **AND** it SHALL remove OpenSpec-managed workflow skill directories for agents that are no longer selected
- **AND** it SHALL update the stored workspace-local selected agent list
#### Scenario: Updating profile-selected workflows
- **GIVEN** global config resolves to a workflow profile
- **WHEN** workspace update refreshes workspace-local skills
- **THEN** OpenSpec SHALL sync the workspace-local skill workflow set to the workflows selected by that profile
- **AND** deselected workflow skill directories SHALL be removed only when they are known OpenSpec-managed workflow skill directories
- **AND** it SHALL update the last applied workflow IDs used for drift detection
#### Scenario: Ignoring command delivery for workspace update
- **GIVEN** global config delivery is `commands` or `both`
- **WHEN** workspace update refreshes workspace-local skills
- **THEN** OpenSpec SHALL still update workspace-local skills only
- **AND** it SHALL not generate slash command files or global command files
#### Scenario: Removing only managed skill directories
- **WHEN** workspace update removes skills for an unselected agent
- **THEN** OpenSpec SHALL remove only known OpenSpec-managed workflow skill directories
- **AND** it SHALL preserve unrelated files in the agent directory
#### Scenario: Updating stored agent selection by flag
- **WHEN** workspace update receives `--tools <ids>` or `--tools none`
- **THEN** OpenSpec SHALL replace the stored workspace-local selected agent list with that selection
- **AND** future workspace updates without `--tools` SHALL use the stored selection
#### Scenario: Non-interactive update tool selection
- **WHEN** workspace update receives `--tools all`, `--tools none`, or `--tools <ids>`
- **THEN** OpenSpec SHALL update workspace agent skills using that selected tool set
- **AND** it SHALL avoid prompting for agent selection
#### Scenario: Non-interactive update without tool selection
- **GIVEN** workspace-local selected agents are stored
- **WHEN** non-interactive workspace update omits `--tools`
- **THEN** OpenSpec SHALL refresh the stored selected agents using the active global profile
- **AND** it SHALL avoid prompting for agent selection
#### Scenario: Non-interactive update without stored selection
- **GIVEN** no workspace-local selected agents are stored
- **WHEN** non-interactive workspace update omits `--tools`
- **THEN** OpenSpec SHALL complete without installing agent skills
- **AND** it SHALL report a no-op with guidance to pass `--tools`
#### Scenario: Reporting workspace skill drift
- **GIVEN** workspace-local skill state records last applied workflow IDs
- **AND** the active global profile resolves to a different workflow set
- **WHEN** OpenSpec reports workspace skill state
- **THEN** it SHALL report that workspace-local skills are out of sync with the global profile
- **AND** it SHALL suggest `openspec workspace update`
#### Scenario: Reporting clean workspace skill sync
- **GIVEN** workspace-local skill state matches the active global profile and selected agents
- **WHEN** OpenSpec reports workspace skill state
- **THEN** it SHALL not report profile drift
#### Scenario: Reporting workspace skill update results
- **WHEN** workspace update changes agent skill state
- **THEN** OpenSpec SHALL report which agents were refreshed, added, removed, skipped, or failed
#### Scenario: Reporting workspace update results in JSON output
- **WHEN** workspace update runs with JSON output enabled
- **THEN** OpenSpec SHALL include refreshed, added, removed, skipped, or failed skill results in machine-readable output
### Requirement: Workspace skill update surface is documented
OpenSpec SHALL expose workspace skill setup/update behavior in user-facing command surfaces.
#### Scenario: Workspace update appears in help
- **WHEN** a user runs `openspec workspace --help`
- **THEN** OpenSpec SHALL list `workspace update`
- **AND** it SHALL describe it as refreshing workspace-local agent skills
#### Scenario: Workspace update options appear in help
- **WHEN** a user runs `openspec workspace update --help`
- **THEN** OpenSpec SHALL document workspace selection options
- **AND** it SHALL document `--tools all|none|<ids>`
- **AND** it SHALL state that global profile selects workflows and `--tools` selects agents
#### Scenario: Workspace update appears in completions
- **WHEN** shell completions are generated
- **THEN** the workspace command registry SHALL include `workspace update`
- **AND** it SHALL include relevant options such as `--workspace`, `--tools`, `--json`, and `--no-interactive`
@@ -0,0 +1,133 @@
## Phase 1: Workspace Setup Skills
User-testable outcome: A user can run workspace setup, choose which agents get the active profile's OpenSpec skills, and verify the selected skills are generated in the workspace root only.
- [x] 1.1 Add an interactive workspace setup step named "Install agent skills" that asks which agents should get OpenSpec skills in this workspace.
- [x] 1.2 Preselect the preferred opener when that opener supports skills, while allowing users to choose different or additional agents.
- [x] 1.3 Support non-interactive agent selection with the existing `--tools all|none|<ids>` style.
- [x] 1.4 Validate workspace setup tool IDs using the same supported skill-generation tool set as repo initialization.
- [x] 1.5 Resolve the active global profile and use it to choose which workflow skills workspace setup installs.
- [x] 1.6 Ensure `openspec workspace setup` generates or refreshes OpenSpec agent skills in the workspace root for the selected agents.
- [x] 1.7 Keep setup-time skill generation scoped to the workspace planning home; do not write skills or OpenSpec artifacts into linked repos or folders during workspace setup.
- [x] 1.8 Keep workspace setup skill generation skills-only for this slice; do not generate slash commands or global command files even when global delivery includes commands.
- [x] 1.9 Define how setup reports generated, refreshed, skipped, failed, and skills-only delivery work in human and JSON output.
- [x] 1.10 Store the selected workspace skill agents and last-applied workflow IDs in workspace-local machine state.
- [x] 1.11 Preserve non-interactive setup compatibility when `--tools` is omitted by skipping skill installation with clear guidance.
- [x] 1.12 Manually run workspace setup in interactive and non-interactive modes and verify the selected profile workflows land only in the workspace root.
- [x] 1.13 Review the setup UX: prompt wording, defaults, skip path, profile/delivery messaging, success output, and JSON output are clear before moving on.
## Phase 2: Workspace Skill Updates
User-testable outcome: A user can change the global profile, run workspace update in an existing workspace, and see workspace-local skills refresh to the selected workflows with clear human and JSON output.
- [x] 2.1 Add a workspace update flow that refreshes, adds, or removes OpenSpec agent skills in an existing workspace.
- [x] 2.2 Let `openspec workspace update` resolve the current workspace when run from inside a workspace.
- [x] 2.3 Support named and selected-workspace update forms such as `openspec workspace update platform` and `openspec workspace update --workspace platform`.
- [x] 2.4 Support non-interactive update forms such as `openspec workspace update platform --tools codex,claude`.
- [x] 2.5 Remove only known OpenSpec-managed workflow skill directories for agents that are no longer selected.
- [x] 2.6 Sync workspace-local workflow skill directories to the current global profile selection.
- [x] 2.7 Keep workspace update skills-only for this slice; do not generate slash commands or global command files even when global delivery includes commands.
- [x] 2.8 Define how update reports refreshed, added, removed, skipped, failed, and skills-only delivery work in human and JSON output.
- [x] 2.9 Use stored selected agents when workspace update runs without `--tools`, and update that stored selection when `--tools` is passed.
- [x] 2.10 Detect workspace-local skill drift from the active global profile and report `openspec workspace update` guidance.
- [x] 2.11 Manually run workspace update for refresh, add, remove, no-op, omitted-`--tools`, and profile-change cases and verify linked repos remain unchanged.
- [x] 2.12 Review the update UX: command forms, current-workspace detection, profile/delivery messaging, drift messaging, removal messaging, and JSON output are understandable.
## Phase 3: Config Profile Workspace Apply
User-testable outcome: A user can run `openspec config profile` inside a workspace and choose whether to apply the changed global profile to that workspace now.
- [x] 3.1 Detect when `openspec config profile` runs from inside an OpenSpec workspace.
- [x] 3.2 After an actual profile or delivery change inside a workspace, prompt to apply changes to the current workspace now.
- [x] 3.3 When confirmed, run `openspec workspace update` for the current workspace instead of repo-local `openspec update`.
- [x] 3.4 When declined, report that global config changed and that `openspec workspace update` applies it later.
- [x] 3.5 Preserve existing repo-local `openspec config profile` apply behavior outside workspaces.
- [x] 3.6 Keep `openspec config profile core` non-interactive, but print workspace-specific `openspec workspace update` guidance when run inside a workspace.
- [x] 3.7 Warn on no-op config profile inside a workspace when workspace-local skills drift from the active global profile.
- [x] 3.8 Manually run `openspec config profile` inside a workspace for confirm, decline, no-op, drift-warning, and `core` preset paths.
- [x] 3.9 Review the config-profile UX: prompt wording, project/workspace distinction, no-op behavior, preset guidance, and follow-up guidance are clear.
## Phase 4: Workspace Change Creation
User-testable outcome: A user can create a workspace-level change from the coordination root, inspect its workspace planning artifacts, and confirm linked repos were not edited.
- [x] 4.1 Add a built-in `workspace-planning` schema and templates that keep the normal proposal/specs/design/tasks artifact shape.
- [x] 4.2 Define the workspace-planning specs artifact with nested `specs/**/*.md` output support and instructions for `specs/<area-or-repo>/<capability>/spec.md`.
- [x] 4.3 Add workspace-aware change creation from the workspace coordination root.
- [x] 4.4 Default workspace-scoped change creation to the `workspace-planning` schema.
- [x] 4.5 Store workspace-level changes under the workspace planning path rather than under linked repos or folders.
- [x] 4.6 Capture the product goal once at the workspace change level.
- [x] 4.7 Record or validate affected area names through workspace-scoped specs or task sections using registered workspace link names where applicable.
- [x] 4.8 Ensure creating a workspace change does not create repo-local OpenSpec artifacts or edit linked repos.
- [x] 4.9 Preserve repo-local change creation behavior outside workspaces.
- [x] 4.10 Manually create a workspace change from a coordination root and verify the generated artifacts, workspace-scoped specs/tasks, affected areas, and untouched linked repos.
- [x] 4.11 Review the change creation UX: goal capture, affected-area identification, artifact paths, and next-step guidance feel clear.
## Phase 5: Planning Home And Agent Context
User-testable outcome: A user can run status and instructions for repo-local and workspace changes and see the resolved planning home, artifact paths, affected areas, constraints, and next steps.
- [x] 5.1 Introduce a shared planning-home resolver that identifies repo-local versus workspace planning homes.
- [x] 5.2 Enrich `openspec status --change <id> --json` with planning home, change root, relevant artifact paths, affected areas, next steps, and action context.
- [x] 5.3 Enrich `openspec instructions <artifact> --change <id> --json` with resolved artifact paths for repo-local and workspace-scoped changes.
- [x] 5.4 Keep workspace-level planning as the source of truth until an explicit implementation workflow selects an affected area.
- [x] 5.5 Preserve nested workspace spec paths in status and instructions output without flattening them into repo-local capability paths.
- [x] 5.6 Manually run status and instructions for both repo-local and workspace-scoped changes and verify paths and action context are correct.
- [x] 5.7 Review the planning-context UX: human output, JSON field names, and next-step guidance are easy for users and agents to follow.
## Phase 6: Workflow Skill Instructions
User-testable outcome: A user can inspect regenerated workflow skills and verify they are path-agnostic and tell agents to use CLI-reported artifact paths.
- [x] 6.1 Update generated workflow skill templates to run `openspec status --change <id> --json` before artifact work and trust returned planning context.
- [x] 6.2 Update generated workflow skill templates to run `openspec instructions <artifact> --change <id> --json` before writing artifacts and use the resolved output path.
- [x] 6.3 Audit source workflow templates for hardcoded `openspec/changes/<name>` assumptions and replace them with CLI-reported path guidance.
- [x] 6.4 Keep a separate artifact-context command out of this slice unless enriched status/instructions prove insufficient during implementation.
- [x] 6.5 Manually regenerate or inspect installed workflow skills and verify they follow CLI-reported artifact paths in a workspace change.
- [x] 6.6 Guard profile-selected workflow skills whose workspace behavior is not implemented yet so they do not fall back to repo-local paths or edit linked repos.
- [x] 6.7 Review the agent-instruction UX: instructions are concise, path-agnostic, safe for unsupported workspace workflows, and practical for both repo-local and workspace planning.
## Phase 7: Verification
User-testable outcome: A user or reviewer can run the full manual checklist from a clean workspace and compare expected versus actual evidence for every earlier phase.
- [x] 7.1 Add tests that workspace setup installs skills in the workspace root and leaves linked repos unchanged.
- [x] 7.2 Add tests that workspace update refreshes, adds, and removes only managed workspace skill directories.
- [x] 7.3 Add tests that workspace setup/update use the current global profile for workflow skill selection while keeping workspace delivery skills-only.
- [x] 7.4 Add tests that `openspec config profile` inside a workspace can apply changes through `openspec workspace update`.
- [x] 7.5 Add tests for stored workspace skill agent selection, omitted-`--tools` behavior, and profile drift reporting.
- [x] 7.6 Add tests that `openspec update` from a workspace planning home redirects to `openspec workspace update`.
- [x] 7.7 Add tests that unsupported workspace workflow skills are guarded and do not instruct repo-local fallback edits.
- [x] 7.8 Add tests that registered repos are visible before change creation.
- [x] 7.9 Add tests that workspace change creation does not imply repo-local artifact creation.
- [x] 7.10 Add tests that the workspace-planning schema resolves nested `specs/<area-or-repo>/<capability>/spec.md` files as workspace-scoped specs.
- [x] 7.11 Add cross-platform path tests for workspace-root skill paths and workspace change paths.
- [x] 7.12 Update CLI docs, command help, and shell completion coverage for `workspace update`, `--tools`, profile behavior, and workspace skills-only delivery.
- [x] 7.13 Run `openspec validate workspace-change-planning --strict`.
- [x] 7.14 Run the full manual acceptance checklist across setup, update, config profile, change creation, planning context, and workflow skills before marking the change complete.
- [x] 7.15 Complete a final UX review across the whole workflow and record any follow-up fixes or intentional deferrals.
- [x] 7.16 Before implementation sign-off, record the manual commands or interaction paths, expected observations, and actual observations for each phase.
- [x] 7.17 Have a separate reviewer or fresh agent context rerun the manual acceptance and UX checklist when available; otherwise rerun it from a clean temporary workspace and report the evidence.
## Verification Evidence
Completion evidence was recorded on 2026-05-14.
Automated checks:
```bash
pnpm run build
pnpm vitest run test/commands/workspace.test.ts test/commands/artifact-workflow.test.ts test/core/workspace/skills.test.ts test/core/planning-home.test.ts test/core/templates/skill-templates-parity.test.ts
node dist/cli/index.js validate workspace-change-planning --strict
git diff --check
```
Clean workspace rerun covered non-interactive workspace setup, workspace doctor, config profile update guidance, workspace update redirection, workspace change creation with `--areas api,web`, status/instructions JSON for nested workspace specs, linked repo cleanliness, and guarded unsupported workflow skills.
Observed results:
- Build, targeted tests, strict validation, and whitespace checks passed.
- Workspace setup/update generated skills only in the workspace root and left linked repos untouched.
- Workspace change creation used schema `workspace-planning`, reported affected areas `api` and `web`, preserved nested `specs/api/login/spec.md`, and kept `actionContext.allowedEditRoots` empty during planning.
- Generated workflow skills used CLI-reported paths and workspace guards rather than hardcoded `openspec/changes/<name>` paths.
- Fresh-agent rerun was not available; the clean temporary workspace rerun served as the fallback independent acceptance pass.
@@ -1,48 +0,0 @@
## Why
After a workspace proposal exists, users need a practical way to implement one repo slice at a time.
In the proper workspace model, apply means implementation:
```text
Take the selected workspace change.
Take the selected repo slice.
Open or use the right checkout.
Implement that slice while preserving the workspace plan.
```
It should not mean copying or materializing planning files into every repo as a user-facing workflow.
## What Changes
Add the repo-slice apply workflow for workspace changes:
- select a workspace change
- select one target repo alias
- resolve the local checkout for that alias
- provide the agent with the workspace plan and repo-specific implementation context
- track progress without making the workspace lose ownership of the plan
The workflow should support implementation across separate branches or sessions while keeping the workspace proposal as the continuity layer.
Planning dependency:
- Depends on `workspace-change-planning`.
## Capabilities
### New Capabilities
- `workspace-repo-slice-apply`: Applies one repo slice of a workspace change as an implementation workflow.
### Modified Capabilities
- `cli-artifact-workflow`: Defines workspace apply as implementation rather than materialization.
- `context-injection`: Supplies repo-specific implementation context from a workspace change.
## Impact
- Workspace apply command behavior.
- Agent handoff text for repo-slice implementation.
- Local checkout resolution and branch/worktree assumptions.
- Tests that apply operates on one target repo slice and does not require copying workspace planning artifacts as the primary user contract.
@@ -1,47 +0,0 @@
## Why
Once repos are visible and the agent has workspace context, the user should be able to plan a cross-repo change without immediately materializing repo-local artifacts.
The user goal is:
```text
Explore the product goal across repos.
Decide the scope.
Create one workspace-level proposal that identifies the repo slices.
```
Planning should be the commitment point. Repo visibility alone should remain lightweight.
## What Changes
Add workspace-level change planning:
- create a workspace change from the coordination root
- capture the product goal once
- identify target repos by registered alias
- let the agent explore before committing to implementation slices
- keep the workspace as the planning source of truth
This slice should avoid rebuilding the POC's materialization-first behavior. Repo-local artifacts should not be created merely because a workspace change exists.
Planning dependency:
- Depends on `workspace-open-agent-context`.
## Capabilities
### New Capabilities
- `workspace-change-planning`: Creates and manages workspace-level proposals for cross-repo goals.
### Modified Capabilities
- `change-creation`: Adds workspace-aware change creation semantics and target repo selection.
- `openspec-conventions`: Defines the relationship between workspace-level planning and repo-local implementation work.
## Impact
- Workspace change creation.
- Target repo metadata and validation.
- Agent instructions for proposing cross-repo changes.
- Tests that registered repos are visible before change creation and that creating a change does not imply repo-local materialization.
@@ -1,44 +0,0 @@
## Why
After a user creates a workspace and links repos or folders, they need to open that workspace with an agent and have the agent understand the working set immediately.
The user should not need to explain where every repo lives, which aliases matter, or whether they are currently planning versus implementing. The workspace should provide that context.
## What Changes
Add the workspace-open experience:
```text
Open this workspace with my agent.
The agent sees the workspace location, linked repos or folders, current changes, and relevant instructions.
```
Links are the planning context. The local registry is only a workspace-discovery index for finding known workspaces on the current machine.
The launch context should separate stable guidance from dynamic runtime scope:
- stable behavior belongs in workspace-level agent guidance where possible
- dynamic scope belongs in the launch prompt or equivalent runtime context
- linked repos or folders should be visible even when no change is active
- change-scoped sessions should include the selected change and target repo context
Planning dependency:
- Depends on `workspace-create-and-register-repos`.
## Capabilities
### New Capabilities
- `workspace-agent-context`: Opens a workspace session with enough dynamic context for an agent to reason across linked repos or folders.
### Modified Capabilities
- `context-injection`: Extends context construction to include workspace location, workspace links, active workspace changes, and selected change scope.
## Impact
- `openspec workspace open`
- Workspace prompt and agent-launch context.
- Generated or committed agent guidance for workspace mode.
- Tests for opening outside a workspace, opening a workspace by name, and opening change-scoped workspace sessions.
@@ -1,259 +0,0 @@
# Workspace POC Reference Guide
This guide is for a fresh agent starting a new session with no prior context about the workspace POC.
Root entry point: `WORKSPACE_REIMPLEMENTATION_START_HERE.md`.
The goal is not to continue the POC. The goal is to use it as research material before reimplementing workspace support cleanly from the current base.
## Reference Point
Use this exact commit as the stable reference:
```text
workspace-poc @ 79a45ac043f414e63d13e08b9da83b135cb20a39
```
Do not rely only on the moving branch name. Do not merge this commit into the implementation branch. Do not cherry-pick from it unless a later proposal explicitly decides that a small piece should be preserved.
## What The POC Was Trying To Prove
Start from the user journey:
```text
create workspace
-> add repos
-> open workspace with an agent
-> explore across repos
-> create a proposal
-> apply one repo slice
-> verify
-> archive
```
The POC is useful if it helps answer:
- What did the user experience feel like when workspace mode worked?
- Which CLI surfaces made the workflow easier to understand?
- Which tests captured real product expectations?
- Which implementation choices were shortcuts that should not survive?
- Which terminology became misleading once the desired product shape was clearer?
## First Files To Read
Read these from the POC commit before implementation:
```text
WORKSPACE_REIMPLEMENTATION_DIRECTION.md
WORKSPACE_POC_FOLLOWUP_NOTES.md
docs/workspace.md
docs/workspace-demo.md
docs/cli.md
src/commands/workspace.ts
src/core/workspace/open.ts
test/commands/workspace/open.test.ts
test/core/workspace/open.test.ts
test/cli-e2e/workspace/workspace-open-cli.test.ts
```
Optional deeper context:
```text
workspace-poc-explorer.html
workspace-poc-phase-playground.html
copilot-session-d4e9c61e-readable.md
copilot-session-d4e9c61e-timeline.md
```
The optional files are historical research aids. Use them to understand how the POC evolved, not as implementation requirements.
## How To Inspect The POC Safely
Preferred approach: use a separate worktree or read files directly from the pinned commit.
Example direct reads:
```bash
git show 79a45ac043f414e63d13e08b9da83b135cb20a39:WORKSPACE_REIMPLEMENTATION_DIRECTION.md
git show 79a45ac043f414e63d13e08b9da83b135cb20a39:src/commands/workspace.ts
git diff origin/main...79a45ac043f414e63d13e08b9da83b135cb20a39 --stat
```
Example separate worktree:
```bash
git worktree add ../openspec-workspace-poc 79a45ac043f414e63d13e08b9da83b135cb20a39
```
Keep the implementation branch based on the current target branch. The POC worktree is for reading and running tests only.
## What To Bring Back
Before implementing a slice, come back with a short POC findings note:
```text
POC findings for <slice>:
User behavior to preserve:
- ...
Tests or examples worth translating:
- ...
Implementation shortcuts to avoid:
- ...
Open design questions:
- ...
```
Put durable findings in the relevant OpenSpec proposal or design artifact. Do not leave important decisions only in chat.
## Slice-Specific Reading
### `workspace-foundation`
Focus on:
- workspace folder shape
- metadata directory naming
- local versus committed state
- stable workspace name semantics
Read:
```text
WORKSPACE_REIMPLEMENTATION_DIRECTION.md
WORKSPACE_POC_FOLLOWUP_NOTES.md
docs/workspace.md
src/commands/workspace.ts
```
Bring back:
- the storage model worth keeping
- the metadata naming decision
- any compatibility risks with repo-local `openspec/`
### `workspace-create-and-register-repos`
Focus on:
- how a user creates a workspace
- how repos or folders are linked
- what `doctor` or equivalent status output should explain
- how POC `create`/`add-repo` behavior maps to the target `setup`/`link`/`relink`/`doctor` flow before change creation
- how planning-only repos and monorepo modules differ from implementation-ready repo-local OpenSpec projects
Read:
```text
docs/workspace.md
docs/workspace-demo.md
src/commands/workspace.ts
test/commands/workspace/setup.test.ts
```
Bring back:
- expected commands
- expected files
- validation behavior for bad paths, duplicate workspace names, missing paths, planning-only links, and duplicate link names
### `workspace-open-agent-context`
Focus on:
- what context the agent receives
- how linked repos or folders become visible
- how one-session agent selection should work
- what should be stable guidance versus dynamic launch context
Read:
```text
WORKSPACE_POC_FOLLOWUP_NOTES.md
src/commands/workspace.ts
src/core/workspace/open.ts
test/commands/workspace/open.test.ts
test/core/workspace/open.test.ts
test/cli-e2e/workspace/workspace-open-cli.test.ts
```
Bring back:
- launch-context requirements
- agent-specific behavior to preserve
- prompt or guidance text that should become stable instructions
### `workspace-change-planning`
Focus on:
- when repo scope becomes a planning commitment
- whether targets should be inferred from artifacts
- how proposal, design, tasks, and specs should be arranged
Read:
```text
WORKSPACE_REIMPLEMENTATION_DIRECTION.md
docs/workspace.md
docs/workspace-demo.md
```
Bring back:
- the artifact shape to use
- how targets should be confirmed
- which POC target metadata ideas should be avoided or deferred
### `workspace-apply-repo-slice`
Focus on:
- the terminology decision that apply means implementation
- what context the agent needs to implement one repo slice
- why materialization should not be the user-facing contract
Read:
```text
WORKSPACE_REIMPLEMENTATION_DIRECTION.md
WORKSPACE_POC_FOLLOWUP_NOTES.md
```
Bring back:
- the normalized apply context shape
- the user-facing apply contract
- any POC materialization behavior that should be explicitly rejected
### `workspace-verify-and-archive`
Focus on:
- partial repo completion versus full workspace completion
- how verification should report gaps
- how archive should avoid forcing repo-local planning copies
Read:
```text
WORKSPACE_REIMPLEMENTATION_DIRECTION.md
docs/workspace-demo.md
```
Bring back:
- the minimum useful verify behavior
- the archive preconditions
- the distinction between repo-slice completion and workspace hard-done state
## Ground Rules
- Treat the POC as evidence, not inheritance.
- Preserve user-visible lessons before preserving code.
- Prefer current repo patterns over POC-only abstractions.
- Implement one user-visible step at a time.
- Update this roadmap when a POC lesson changes a later slice.
@@ -1,71 +0,0 @@
# Workspace Reimplementation Roadmap
This change is the continuity layer for reimplementing workspace support across multiple sessions and branches.
Root entry point for fresh agents: `WORKSPACE_REIMPLEMENTATION_START_HERE.md`.
The user journey we are implementing is:
```text
create workspace
-> add repos
-> open workspace with agent context
-> plan a cross-repo change
-> implement one repo slice
-> verify and archive
```
The POC branch is reference material only:
```text
workspace-poc @ 79a45ac043f414e63d13e08b9da83b135cb20a39
```
Use it to understand behavior, tests, and lessons learned. Do not merge it or preserve its architecture by default. The full source direction document from that branch is copied at the repository root as `WORKSPACE_REIMPLEMENTATION_DIRECTION.md`.
Fresh agents should read `POC_REFERENCE_GUIDE.md` before implementing any slice. That guide explains how to inspect the pinned POC commit, which files to read for each slice, and what findings to bring back into the OpenSpec artifacts.
## Change Order
Implement the flat sibling changes in this order:
1. `workspace-foundation`
2. `workspace-create-and-register-repos`
3. `workspace-open-agent-context`
4. `workspace-change-planning`
5. `workspace-apply-repo-slice`
6. `workspace-verify-and-archive`
OpenSpec currently discovers active changes as immediate directories under `openspec/changes/`, and change names are kebab-case identifiers. Keep these changes as flat siblings until formal change-stacking metadata is available.
## Dependency Notes
`workspace-foundation` establishes the storage, root detection, and naming model. Every later slice should build on that model instead of redefining workspace metadata.
`workspace-create-and-register-repos` creates the workspace and makes linked repos or folders visible before a change exists. Linked items may be full repos, monorepo modules, or planning-only folders. This preserves the product rule that workspace visibility is not change commitment.
`workspace-open-agent-context` gives the agent the workspace location, linked repos or folders, active changes, and selected change scope.
`workspace-change-planning` creates the workspace-level planning commitment and identifies target repo slices.
`workspace-apply-repo-slice` treats apply as implementation of one selected repo slice, not materialization of workspace planning files.
`workspace-verify-and-archive` makes cross-repo progress visible and separates partial repo completion from final workspace completion.
## Session Handoff Prompt
Use this prompt at the start of future implementation sessions:
```text
Continue the workspace reimplementation roadmap. Read
openspec/changes/workspace-reimplementation-roadmap/README.md and
openspec/changes/workspace-reimplementation-roadmap/POC_REFERENCE_GUIDE.md
first, then pick up the next unfinished flat sibling change in order. Use
workspace-poc at 79a45ac043f414e63d13e08b9da83b135cb20a39 as reference
material only. Preserve intended behavior, but reimplement cleanly from the
current base. Before editing, summarize the POC findings for the slice.
```
## Branching Guidance
Each sibling change may be implemented on its own branch or PR. Keep decisions that affect later slices in this README or in the relevant proposal so future sessions do not depend on chat history.
@@ -1,53 +0,0 @@
## Why
Workspace support needs to be reimplemented as a user-facing workflow, not carried forward as a direct port of the proof of concept.
A user should be able to say they have a multi-repo product goal, create a workspace, add the relevant repos, open that workspace with an agent, plan the change, implement one repo slice at a time, verify it, and archive it. The POC branch captured useful behavior and discovery, but its implementation should remain reference material rather than the base architecture.
This roadmap also needs to survive multiple sessions and branches. Current OpenSpec change discovery treats active changes as flat immediate directories under `openspec/changes/`, and change names are kebab-case identifiers rather than nested paths. This change is therefore a flat planning container with sibling proposal changes instead of nested child changes.
Reference material:
- `workspace-poc` at `79a45ac043f414e63d13e08b9da83b135cb20a39`
- `WORKSPACE_REIMPLEMENTATION_DIRECTION.md` on that branch
- `WORKSPACE_POC_FOLLOWUP_NOTES.md` on that branch
## What Changes
Add a lightweight roadmap for reimplementing workspace support as a stack of flat sibling OpenSpec changes:
- `workspace-foundation`
- `workspace-create-and-register-repos`
- `workspace-open-agent-context`
- `workspace-change-planning`
- `workspace-apply-repo-slice`
- `workspace-verify-and-archive`
Each sibling change owns one step in the lived user journey. Dependencies are documented in proposal prose for now. When change stacking metadata lands, this roadmap can be migrated to explicit `parent` and `dependsOn` metadata.
The intended order is:
```text
workspace-foundation
-> workspace-create-and-register-repos
-> workspace-open-agent-context
-> workspace-change-planning
-> workspace-apply-repo-slice
-> workspace-verify-and-archive
```
## Capabilities
### New Capabilities
- `workspace-reimplementation-roadmap`: Coordinates the workspace reimplementation plan across multiple flat OpenSpec changes.
### Modified Capabilities
- `openspec-conventions`: Clarifies that this workspace effort uses flat sibling changes until nested or stacked change metadata is supported.
## Impact
- Planning only in this PR.
- Future changes will affect workspace metadata, workspace CLI flows, agent context construction, workspace change planning, repo-slice application, verification, and archive behavior.
- No runtime behavior changes are introduced by this roadmap proposal.
@@ -1,47 +0,0 @@
## Why
Users need to know whether a cross-repo workspace change is complete without flattening all repo progress into one ambiguous done state.
The desired lifecycle is:
```text
Verify each repo slice.
See which slices are complete or still open.
Archive repo-local results when appropriate.
Archive the workspace change when the cross-repo goal is done.
```
Verification and archive should make the user's cross-repo status clearer, not force them to reason about internal artifact placement.
## What Changes
Add workspace-aware verify and archive behavior:
- verify workspace-level change structure and target repo status
- show per-repo slice progress
- support repo-local archive work where needed
- support explicit workspace-level archive when the coordinated goal is complete
- avoid treating partial repo completion as full workspace completion
Planning dependency:
- Depends on `workspace-apply-repo-slice`.
## Capabilities
### New Capabilities
- `workspace-verify-archive`: Verifies and archives workspace changes with per-repo progress visibility.
### Modified Capabilities
- `cli-archive`: Adds workspace-aware archive semantics.
- `opsx-verify-skill`: Adds workspace verification guidance.
- `opsx-archive-skill`: Adds workspace archive guidance.
## Impact
- Workspace status, verify, and archive behavior.
- Per-repo slice completion reporting.
- Workspace-level hard-done marker or equivalent archive state.
- Tests for partial completion, final workspace archive, and compatibility with standalone repo-local archive flows.
@@ -0,0 +1,27 @@
version: 1
id: context-store-and-initiatives
title: Context Store And Initiatives Direction
status: exploring
summary: >
Define the direction for a synced context store, mounted collections,
initiatives, local workspaces, and repo-local changes.
owners: []
artifacts:
readme: README.md
direction: direction.md
roadmap: roadmap.md
tasks: tasks.md
decisions: decisions.md
questions: questions.md
work_items: work-items/
linked_changes:
- change: workspace-reimplementation-roadmap
relationship: informs
- change: workspace-agent-guidance
relationship: reframes
- change: workspace-apply-repo-slice
relationship: reframes
- change: workspace-verify-and-archive
relationship: reframes
links: []
metadata: {}
@@ -0,0 +1,58 @@
# Context Store And Initiatives
Status: transition evidence / beta history.
This folder preserves the beta context-store and workspace direction, the
decisions made while exploring it, and the evidence that led to the simpler
Git-native model.
It is not the active product roadmap or implementation queue. For current
direction, start with:
1. `openspec/work/simplify-context-and-workspace-model/goal.md`
2. `openspec/work/simplify-context-and-workspace-model/roadmap.md`
The `direction-git-native-work.md` note is the transition note that led to the
current goal. If it conflicts with the current `goal.md`, the current `goal.md`
wins.
## Reading Order
Use this reading order when researching the beta history:
1. `direction-git-native-work.md` explains the transition from the old beta
model toward Git-native specs and work.
2. `direction.md` preserves the earlier context-store and initiative direction.
3. `roadmap.md` preserves the historical beta roadmap snapshot.
4. `tasks.md` preserves historical initiative-wide progress.
5. `decisions.md` records accepted decisions made during the beta.
6. `questions.md` tracks questions that were open at the time.
7. `work-items/<id>/` contains execution notes for one historical roadmap item.
## Boundary
These artifacts preserve product intent, roadmap decisions, and beta evidence
from the old model. OpenSpec specs describe the current behavioral contract
behind the code.
Do not rewrite specs for future intent until behavior changes with an
implementation slice.
The earlier product boundary was:
```text
Context stores sync truth.
Collections shape truth.
Initiatives coordinate work.
Workspaces open local views.
Changes implement repo-owned slices.
```
The newer direction is:
```text
OpenSpec is a Git-native artifact format for specs and work.
Specs are what is true.
Work is what is in motion.
```
@@ -0,0 +1,225 @@
# Context Store And Initiatives Decisions
## 2026-05-20: Track Roadmap Execution Inside The Initiative
Decision: Track initiative roadmap implementation inside
`openspec/initiatives/context-store-and-initiatives/` rather than creating an
OpenSpec change for each roadmap item.
Why: The initiative is the durable coordination object for this work. Repo-local
OpenSpec changes should be reserved for implementation slices owned by a repo or
team. Roadmap-item tracking belongs with the initiative until a task needs a
repo-owned implementation plan.
Implications:
- Use `tasks.md` as the initiative-wide progress dashboard.
- Use `work-items/<nn-slug>/` for detailed execution notes on one roadmap item.
- Link repo-local OpenSpec changes back to the initiative later when
implementation moves into a repo-owned slice.
## 2026-05-20: Lock Workspace-To-Initiative Product Boundary
Decision: Workspaces are local working views, not durable shared planning
objects. Durable coordination belongs to context stores and initiatives. Repo
local changes own implementation.
Implications:
- Preserve workspace setup, link, relink, list, open, update, and doctor as
beta local-view infrastructure.
- Treat workspace-planning behavior as beta or transitional compatibility.
- Defer workspace apply, verify, and archive until initiative-linked repo-local
changes exist.
## 2026-05-21: Leave Specs Alone Until Behavior Changes
Decision: Do not use the initial direction lock to rewrite OpenSpec specs.
Specs should describe the current behavioral contract behind the code. The
initiative artifacts should carry product intent, roadmap decisions, and future
direction until a later implementation change deliberately updates behavior and
its specs together.
Implications:
- Initial Item 1 cleanup should focus on initiative docs, historical roadmap
artifacts, active proposal disposition, and user-facing docs.
- Existing workspace-planning specs and schemas may continue to describe current
implemented behavior.
- Future changes to specs should happen with the behavior they govern.
## 2026-05-21: Keep Deferred Workspace Changes As Reference Placeholders
Decision: Keep the active workspace changes for agent guidance, repo-slice
apply, verify/archive, and the reimplementation roadmap as deferred reference
placeholders.
Why: These areas are still expected to matter after context stores, initiatives,
and initiative-linked repo-local changes exist. Archiving or deleting them now
would lose useful research and continuity.
Implications:
- Do not pick them up as the immediate next implementation focus.
- Treat their current proposals as historical/deferred direction.
- Revisit and reframe them after initiative-linked repo-local changes define the
durable handoff model.
## 2026-05-21: Generated Workspace Guidance Routes Work By Ownership
Decision: Generated workspace guidance should describe workspaces as local
working views and route durable work to the owning artifact: initiatives own
cross-team or cross-repo intent, repo-local OpenSpec changes own implementation
plans, and linked repos or folders own their implementation.
Why: The initiative direction supersedes the older model where a workspace-level
`changes/` tree owned the canonical shared cross-repo plan. New agent guidance
should not reinforce that old model.
Implications:
- Remove guidance that tells agents to use workspace-level `changes/` as the
planning home for coordinated work.
- Keep legacy or beta workspace-planning files readable as compatibility
context when present.
- Update generated workspace guidance before broad user-facing docs or specs.
- Leave specs untouched until the corresponding behavior intentionally changes.
## 2026-05-21: Workspace Action Context Is Local Compatibility Context
Decision: Workspace-planning action context should no longer describe
workspace-level artifacts as the source of truth. It should report
`sourceOfTruth: "workspace-local"` and describe workspace-local planning
artifacts as compatibility context for the current local view.
Why: Workspace-planning artifacts can still exist in the beta workflow, but the
initiative direction assigns durable coordination to initiatives and
implementation planning to repo-local changes.
Implications:
- Keep `actionContext.mode: "workspace-planning"` for compatibility.
- Keep `allowedEditRoots: []` until an explicit edit root is selected.
- Keep linked repos and folders as context, not implicit edit roots.
- Route durable coordination to initiatives when initiative context exists.
## 2026-05-21: Reorder Roadmap Around Agent-First Initiative Handoff
Decision: Treat initiatives as an agent-first workflow. Users should be able to
prompt an agent with intent like "using initiative X, explore Y and create a
proposal"; OpenSpec should provide small CLI primitives the agent can compose.
Why: The practical UX is not a human manually typing every coordination command.
Agents need reliable structured answers about where canonical initiative context
lives and how repo-local changes reference it. Local paths come from workspace
state, not from an initiative command.
Implications:
- Promote minimal context-store setup, registration, listing, and doctoring
before workspace initiative opening.
- Add `initiative show --json` before broader progress/status concepts.
- Connect repo-local changes with checked-in initiative metadata, not checked-in
snapshots of initiative prose.
- Do not add `initiative resolve`; workspace local-view state owns local path
mapping.
- Teach workspace opening about initiatives after show and repo-change linkage
semantics exist.
## 2026-05-26: Workspace Initiative Opening Uses Generated Runtime Files
Decision: Treat workspace initiative opening as a private local view record plus
generated runtime files. The workspace does not contain the work. It remembers
how this runtime opens the work.
Why: Initiative context is shared truth in the context store, repo-local changes
own implementation, and agent/editor affordances need to exist in the runtime
where the agent actually runs. Persisting generated files as workspace truth
would blur local view state with shared coordination and create stale or
privacy-sensitive artifacts.
Implications:
- Persist only tiny private local view choices: selected store, selected
initiative, selected local links, opener, and selected tools.
- Preserve the selected context-store selector inside the private workspace
record, so a runtime-local `--store-path` open can be reopened without writing
machine-local paths into checked-in repo metadata.
- Generate agent guidance, skills, launch prompts, and editor workspace files as
runtime support when opening or preparing a view.
- Open existing local paths only; do not clone, branch, create worktrees, use
submodules, or infer local repos in Item 10.
- Treat generated runtime files as disposable and regenerable.
- Allow context-only initiative open; linked repos are optional local view
choices.
- Keep edit boundaries advisory in Item 10 until enforcement is designed.
## 2026-05-26: Workspace Storage Is Keyed By Workspace Name
Decision: Store private workspace views under
`getGlobalDataDir()/workspaces/<workspace-name>/`. The workspace name is the
local identity. The selected context store and initiative, if any, live inside
one durable private `workspace.yaml` record.
Why: Workspaces are generic local views, not initiative-owned directories. A
user may want a custom workspace with linked repos and folders but no initiative,
or multiple personal workspaces over the same initiative. Keying storage by
store and initiative would overfit the filesystem layout to one workflow.
Implications:
- Keep initiative references optional inside `workspace.yaml`.
- Store initiative context with an explicit context-store binding rather than a
flat store id, because workspace state may need to remember a registry selector
or a runtime-local path selector.
- Generate `AGENTS.md`, opener workspace files, and tool-specific skills at the
managed workspace root.
- Keep `workspace.yaml` as the only view file for Item 10; do not add a separate
machine-readable view file.
- Do not introduce a separate generated-output directory for Item 10.
- If the user opens an initiative without a workspace name, derive a friendly
default workspace name from the initiative id when that is unambiguous.
- On workspace-name collisions or multiple workspaces pointing at the same
initiative, ask the human to choose or require an explicit workspace name in
non-interactive mode.
## 2026-05-26: Item 10 Workspace Open UX Decisions
Decision: Close the remaining Item 10 product decisions around runtime identity,
JSON output, Codex Desktop, edit boundaries, and implementation scope.
Implications:
- Use `getGlobalDataDir()` as the cross-platform runtime-local boundary. Do not
add path translation or a separate runtime id in Item 10.
- Keep `workspace open --json` as a machine-facing receipt for the same open
operation. It should return useful generated paths, selected context, opened
roots, skipped roots, opener, launch status, and warnings.
- Do not add `--prepare-only` for Item 10.
- For Codex Desktop, open the generated workspace root as the project and expose
attached initiative and repo/folder paths through generated guidance and
`workspace open --json` output.
- Emit advisory edit boundaries only; do not enforce write restrictions.
- Continue to open known existing local paths only. Do not clone, branch, create
worktrees, use submodules, or infer local repos in Item 10.
## 2026-05-30: Defer Hardcoded Agent Handoff Guidance
Decision: Skip Item 13, agent handoff output and delivery polish, as an
implementation item for now.
Why: The underlying beta pain is real: users and agents need better receipts
after setup, initiative creation, workspace opening, and repo-local change
creation. However, fixed "Next for your agent" guidance assumes a linear
workflow path and may not fit dynamic agentic work, where the agent should
inspect current state and choose the next move.
Implications:
- Do not implement hardcoded next-step blocks yet.
- Preserve Item 13 as research context for a future receipt or affordance model.
- Prefer future output that reports what exists, where it lives, and what
actions are available, rather than prescribing one next command.
- Deterministic receipt improvements such as direct `created_paths` fields may
be split into a smaller implementation slice if they remain clearly useful.
- Delivery terminology concerns may be handled separately from handoff output.
@@ -0,0 +1,472 @@
# Git-Native Specs And Work Direction
This note captures the current product direction after the initiative,
workspace, context-store, and multi-repo planning discussion.
The positive shape is:
```text
OpenSpec is a Git-native artifact format for specs and work.
Specs are what is true.
Work is what is in motion.
```
OpenSpec artifacts live as files in Git. That Git repo may be the code repo, a
planning repo, or a contracts repo. OpenSpec should not introduce a separate
authoritative state system outside those files.
## Core Shape
The preferred future shape is:
```text
openspec/
README.md
openspec.yml
specs/
work/
```
- `specs/` describes accepted behavior.
- `work/` describes intended effort in motion.
This shape should be the same whether the OpenSpec root lives beside code or in
a dedicated planning or contracts repo.
```text
app-repo/
openspec/
specs/
work/
planning-repo/
openspec/
specs/
work/
```
There is no separate product mode for "repo-local", "external", "workspace",
"context store", or "multi-repo" artifacts. The placement choice is simply
which Git repo contains the OpenSpec files.
## Vocabulary
Use a small vocabulary first:
```text
Spec current accepted behavior
Work intended effort in motion
Change work that applies concrete deltas to targets
Initiative work that coordinates or decomposes other work
Target repo, service, package, path, or system where work lands
```
Users should not need to learn `context store`, `project`, `workspace`,
`artifact home`, or `index` as primary product nouns.
## Domain Terms
Use these terms when explaining the near-term product:
```text
OpenSpec root
The `openspec/` directory that contains specs, changes, work, and config.
In-project OpenSpec
OpenSpec initialized inside the project repo it helps describe.
Standalone OpenSpec repo
A separate Git repo whose main purpose is to hold OpenSpec artifacts.
Target project repo
A code repo that a change or work item applies to.
Local repo map
Private local resolution from a target repo id to a checkout path.
Workspace view
Legacy or beta local-view language. In the new direction, this should reduce
to a local repo map plus an optional focused OpenSpec root or work item.
```
Examples:
```text
In-project OpenSpec:
app-repo/
openspec/
specs/
changes/
Standalone OpenSpec repo:
app-openspec-repo/
openspec/
specs/
changes/
Target project repo:
app-repo/
src/
tests/
```
The product should avoid the term `repo-local` for this distinction. It is too
easy to confuse "OpenSpec lives in this project repo" with "this work targets
this repo."
The product should also avoid making `workspace` a primary user-facing noun.
The job that remains is simpler: map target repo ids to local checkout paths so
agents and commands can assemble the relevant Git repos on this machine.
## Work Is The Primitive
`work/` is one canonical area for units of work at different scales.
```text
openspec/
specs/
auth/session-limits.md
work/
add-login-rate-limit/
work.yaml
proposal.md
tasks.md
deltas/
checkout-modernization/
work.yaml
README.md
```
A change is work with change capabilities:
```yaml
id: add-login-rate-limit
kind: change
status: proposed
targets:
- repo: app
```
An initiative is also work:
```yaml
id: checkout-modernization
kind: initiative
status: active
children:
- work: add-login-rate-limit
- work: add-checkout-tax
```
The distinction between a change and an initiative should not come from which
top-level folder the artifact lives in. It should come from metadata and
capabilities:
- Work with targets and deltas can validate and archive those deltas into
`specs/`.
- Work with children, dependencies, and context can coordinate and roll up other
work.
- Some work may be both change-shaped and coordination-shaped.
## Git Is The Source Of Truth
OpenSpec should stay Git-native:
- History comes from Git.
- Review uses normal Git and forge workflows.
- Diffs are normal file diffs.
- External planning means another Git repo, not another state system.
- Indexes, dashboards, status rollups, and orchestration are derived views.
Forge-specific status such as pull request state, CI, review approvals, or
merge status may be read by adapters. That status should not become a competing
OpenSpec truth.
## Targets
Filesystem location should not imply implementation target. Work declares where
it lands.
```yaml
targets:
- repo: api
- repo: web
```
Targets may later address repos, services, packages, paths, external systems,
or monorepo subtrees. Use plural `targets` in the format early, even if some MVP
lifecycle commands only support one target.
## Nesting And References
The rule is:
```text
Nest within a repo.
Reference across repos.
```
Within one Git repo, work can nest when that is the real relationship:
```text
app-repo/
openspec/
work/
checkout-modernization/
work.yaml
work/
add-login-rate-limit/
```
Across Git repo boundaries, work references other work by stable identity:
```yaml
id: checkout-modernization
kind: initiative
children:
- repo: api
work: add-tax-api
- repo: web
work: update-checkout-ui
```
This keeps each repo's executable work close to the code it affects while still
allowing a planning or contracts repo to coordinate the larger effort.
Work identity must come from metadata, not from the path. Folder paths can help
humans browse; they should not be the durable identity of the work.
## Dependency And Sequencing
Multi-repo complexity is mostly about sequencing, not folder placement.
OpenSpec should be able to record dependency intent in Git:
```yaml
depends_on:
- work: publish-tax-contract
```
Future views can answer:
- How does this large effort decompose?
- What has to happen first?
- Which targets are affected?
- Which teams own the slices?
- What surrounding context does an agent need?
The free artifact format should be able to describe ordering and dependencies.
Automation that enforces sequencing, gates merges, or rolls up live forge status
can remain a derived orchestration layer.
## MVP Implication
The immediate release path should keep the current OpenSpec baseline working:
```text
openspec/
README.md
openspec.yml
specs/
changes/
```
The first mental model is:
```text
Specs = what is true.
Changes = what should change.
```
Near-term work should not require the future `work/` layout. `change` remains
important because a change applies deltas. The `work/` model is the future
layout direction, not a prerequisite for making standalone OpenSpec repos
useful.
## Roadmap
### 1. Preserve The Current Baseline
Keep the existing in-project OpenSpec flow working and understandable:
```text
app-repo/
openspec/
specs/
changes/
```
The first release goal is not to rename everything. It is to make the current
model boring and reliable.
### 2. Make The Placement Choice Explicit
Teach the product language:
```text
OpenSpec can live inside your project repo,
or in its own Git repo.
```
Use:
- `in-project OpenSpec` for `app-repo/openspec/`
- `standalone OpenSpec repo` for `app-openspec-repo/openspec/`
Avoid `repo-local` as the user-facing term for this split.
### 3. Support Standalone OpenSpec Repos
Allow OpenSpec to be initialized and validated in a Git repo that does not hold
application code:
```text
app-openspec-repo/
openspec/
specs/
changes/
```
This should use the same parser, templates, validation, and archive concepts as
in-project OpenSpec. A standalone repo is not a new state system.
### 4. Add Target Project Repo Resolution
Standalone OpenSpec repos need to describe where changes land:
```yaml
targets:
- repo: app
```
The first slice can keep target resolution simple:
- register local target repos
- validate that referenced targets exist
- report unresolved targets clearly
- let agents know which OpenSpec repo and target repos are involved
Do not clone, branch, sync, orchestrate, or infer complex repo state yet.
This is the simplified successor to the larger workspace-view concept. Existing
workspace beta behavior may remain as compatibility, but new direction should
use local repo mapping as the product shape.
### 5. Add Cross-Repo Context And Doctoring
Once standalone OpenSpec repos can target project repos, add read-oriented
support for relevant context:
- doctor checks for missing target repo mappings
- local path mapping for agents
- read-only references to other OpenSpec repos when needed
- clear output showing which Git repo owns each artifact
Remote Git URL support, pull/push helpers, status dashboards, and sequencing
enforcement can come later.
### 6. Evolve Toward `work/`
After the baseline and standalone repo flow are solid, introduce the future
layout direction:
```text
openspec/
specs/
work/
```
At that point:
- existing `changes/` can be supported as legacy or migrated
- changes become change-shaped work
- initiatives become coordination-shaped work
- dependency and sequencing views can build on stable work identity
Do not make `/work` block the standalone OpenSpec repo release.
## Decisions Considered
### Separate `changes/` And `initiatives/`
Rejected as the preferred future shape:
```text
openspec/
changes/
initiatives/
```
This uses folders as the type system and makes changes and initiatives feel
artificially unrelated. The cleaner model is one `work/` tree where change and
initiative are shapes of work.
### Initiative-Owned Change Folders
Rejected as canonical storage:
```text
openspec/
initiatives/
checkout-modernization/
changes/
add-tax-api/
```
This makes initiative ownership look like lifecycle ownership. A larger unit of
work may coordinate a smaller one, but the smaller unit still has its own
identity, targets, deltas, and lifecycle.
### Project Or Repo Buckets As Lifecycle Roots
Rejected as the default:
```text
projects/
api/
openspec/
changes/
web/
openspec/
changes/
```
Repo buckets work when each artifact cleanly belongs to one repo, but they get
awkward for cross-repo work, shared contracts, monorepos, and initiatives that
span several targets. Repos should be targets, not mandatory lifecycle roots.
### Stateful Context Store As Core Primitive
Rejected as the core framing.
A dedicated planning or contracts repo may hold OpenSpec artifacts, but it is
still a Git repo. OpenSpec should not create a separate authoritative store that
can disagree with Git.
### Configurable Layout Modes
Rejected as an MVP product shape.
Custom layout modes force every tool, doc, and agent instruction to branch.
Prefer one opinionated layout and let users choose which Git repo contains it.
### Workspace As A Primary Product Object
Rejected as the new user-facing shape.
The useful part of workspace-view behavior is local resolution: knowing where
the OpenSpec repo and target project repos are checked out on this machine. That
should be treated as a local repo map, not as a planning container, lifecycle
owner, or durable source of truth.
## Supersession Note
This direction supersedes the older product boundary that centered context
stores, collections, initiatives, workspaces, and repo-local changes as separate
primary nouns. Those artifacts remain useful historical context and describe
implemented beta behavior, but new product direction should start from the
Git-native `specs/` and `work/` shape.
@@ -0,0 +1,458 @@
# Context Store And Initiatives Direction
Status: historical beta direction.
This document preserves the earlier context-store and workspace direction from
the workspace/initiative discussion. It is useful transition evidence, but it
is not the current product authority for the simplification work.
For current direction, start with:
1. `openspec/work/simplify-context-and-workspace-model/goal.md`
2. `openspec/work/simplify-context-and-workspace-model/roadmap.md`
The main historical shift captured here was that "workspace" should not be the
durable shared planning object. In this earlier model, the durable shared
object was a synced context store, and initiatives were one opinionated
collection inside it.
## Historical Core Model
```text
Context Store
= synced shared content container
Collection
= mounted content system inside a store
Initiatives
= first major collection for cross-team implementation context
Workspace
= local working view over context stores and repos
Change
= repo/team-owned implementation plan
```
The clean rule:
```text
Context stores sync truth.
Collections shape truth.
Initiatives coordinate work.
Workspaces open local views.
Changes implement repo-owned slices.
```
## Historical Locked Product Boundary
The workspace-to-initiative pivot was the product boundary for this beta
coordination work:
- A workspace is a regenerable, machine-local working view. It maps context
stores, initiatives, projects, repos, and folders to paths the current user can
open.
- A context store is the durable synced container for shared files.
- An initiative is the durable coordination object for cross-team or cross-repo
implementation context.
- A repo-local change remains the implementation plan owned by the repo or team
doing the work.
This supersedes the older model where a workspace-level `changes/` tree owned
the canonical shared plan for cross-repo work. Existing workspace-planning
behavior can remain as beta or legacy infrastructure, but it should not steer
new lifecycle design.
Workspace roadmap disposition:
- Keep setup, link, relink, list, open, update, and doctor.
- Keep linked repos and folders visible for exploration before a change exists.
- Keep workspace-local agent guidance as local view setup, refreshed by
`workspace update`.
- Defer workspace apply, verify, and archive until initiatives can link to
repo-owned OpenSpec changes.
- Defer branch/worktree orchestration, multi-repo apply, strong cross-repo
validation, and dependency graph enforcement.
## Agent-First UX
The primary user experience for initiatives is expected to be agent-driven:
```text
Using initiative billing-launch, explore the API work and create a proposal.
```
The user should not need to know every command. OpenSpec should expose small,
structured CLI primitives that an agent can use to:
- find the intended initiative across registered context stores
- read canonical initiative files from the context store
- create or link a repo-local OpenSpec change
- use workspace state for local repo and folder views
- respect edit boundaries instead of treating every opened folder as editable
The CLI is therefore the agent's tool surface, not the whole user workflow.
Prefer explicit, machine-readable commands such as `initiative show --json`,
`new change --initiative ...`, and workspace local-view commands over broad
interactive flows as the first slice.
Canonical initiative context should stay in the context store. Repo-local
changes should reference the initiative rather than checking in copied snapshots
of initiative prose. If an agent needs a compact context pack, OpenSpec can
generate that as command output from the live initiative context.
## Context Store
A context store is the shared/synced folder of files. It is content-agnostic.
It should not know what an initiative is.
Example:
```text
acme-context/
initiatives/
decisions/
api-catalog/
playbooks/
```
The first backend should be Git:
```text
create/update/delete files
-> commit
-> push
-> other users pull
-> local views update
```
But the application should talk to a store abstraction, not directly to Git, so
the backend can later become a cloud database.
## Backend
A backend provides persistence and sync for a context store.
Examples:
- `git` backend: local clone, pull, commit, push, watch
- `cloud` backend: database records, subscriptions, hosted sync
- `memory` backend: tests and local prototypes
The backend should expose generic file/object operations:
```text
read
write
delete
list
sync
watch
```
It should not contain initiative-specific behavior.
## Collections
A collection is a mounted content system inside a context store. It is
plugin-like, but "collection" is the user-facing term.
Each collection owns:
- a folder namespace
- a content model
- templates
- validation/rules
- optional agent guidance
- optional UI views
Example:
```text
context-store/
initiatives/ # Initiative collection
decisions/ # Decision collection
api-catalog/ # API catalog collection
```
Core should enforce that a collection only writes inside its mount.
## Initiative Collection
The initiative collection is the first enterprise-oriented collection.
An initiative is shared, agent-consumable implementation context for a
coordinated outcome. It can span teams, repos, services, APIs, contracts, and
capabilities.
Default shape:
```text
initiatives/
launch-billing-flow/
initiative.yaml
requirements.md
design.md
contracts/
decisions.md
questions.md
tasks.md
```
This describes the runtime initiative collection shape in context stores. This
roadmap folder may still contain legacy `.initiative.yaml` progress metadata
while the initiative itself is being used to manage the migration; that legacy
tracker is not the model new context-store initiatives should copy.
The default structure should be opinionated for the enterprise design
partnership, but the collection system should allow other structures later.
## Initiative Responsibilities
Initiatives should own implementation-relevant shared context:
- product/program intent
- accepted requirements
- high-level technical coordination
- capability and ownership maps
- API/event/schema contracts
- dependency assumptions
- decisions and open questions
- workspace-readable context for repo-local implementation work
Initiatives should not try to become all of Jira or Confluence. The focused
positioning is:
```text
OpenSpec stores agreed implementation context.
Jira tracks work.
Confluence stores broad prose.
GitHub/GitLab store code.
```
## Initiative And Change Scope
An initiative can span one or many OpenSpec changes.
Those changes may live:
- in the same repo as the initiative
- in different repos
- in multiple context stores or OpenSpec roots later
The initiative stores shared coordination context. Workspace views can associate
that context with local repos and repo-owned changes without making the
initiative store machine-local checkout links.
This keeps grouping separate from storage:
```text
Initiative = shared grouping/context
Change = execution artifact
Workspace = local opened view of initiative + repos
```
## Workspace
A workspace is a local working view, not the source of truth.
It can map context stores and project identifiers to local paths, configure an
opener, and launch coding agents with the right folders visible.
A workspace can open an initiative by resolving:
- the initiative's context store
- locally selected repo-local changes
- local checkout paths for participating repos
The durable workspace record should stay tiny and private. It records this
runtime's local view choices, not generated agent files or shared initiative
content.
```text
getGlobalDataDir()/workspaces/<workspace-name>/
workspace.yaml
```
The workspace name is the local identity. The workspace record can optionally
store a selected context store and initiative, plus stable link names to local
paths and opener preferences. Initiative references are data inside the record,
not path segments.
Opening a workspace materializes opener-specific runtime files at the managed
workspace root. Those files can contain generated agent guidance, skills,
and editor workspace files. Machine-readable context is returned by JSON command
output. These are regenerated local support, not source of truth.
```text
private local view record
-> generated runtime files
-> opener-specific launch
-> initiative context + selected local repos/folders
```
Workspaces should be regenerable and runtime-specific. They should not be the
canonical home for initiative content, checked-in collaboration state, branches,
worktrees, clones, or implementation progress.
## Repo Changes
Repo-local changes remain the team-owned implementation plan.
An engineering team should be able to pull relevant initiative context into a
repo and create a linked OpenSpec change.
Example:
```text
repo/
openspec/
changes/
add-billing-api/
.openspec.yaml
proposal.md
design.md
specs/
tasks.md
```
The local change should reference the initiative in metadata, for example:
```yaml
initiative:
store: platform
id: billing-launch
```
This metadata is durable repo context and should be checked in. It should not
contain machine-local paths. Agents should read the initiative's canonical files
from the registered context store when they need the shared context.
## Relationship Between Concepts
```text
Context Store
contains Collections
Collection
defines structure/rules for a mounted folder
Initiative Collection
defines initiatives/
Initiative
coordinates one shared outcome
Workspace
opens local views of context stores and repos
Repo Change
implements one team's/repo's part of an initiative
```
End-to-end flow:
```text
Product/program/architect creates initiative
-> initiative syncs through context store
-> engineers open local workspace
-> repo team pulls relevant initiative context
-> repo team creates linked OpenSpec change
-> repo team implements locally
-> workspace view surfaces local progress alongside initiative context
```
## Local API Direction
The app should use dependency injection:
```ts
const store = createStore({
id: "acme-context",
backend: gitBackend({
remote: "git@github.com:acme/context.git",
localPath: "~/.openspec/stores/acme-context",
autoSync: true,
}),
collections: [
initiativeCollection({ mount: "initiatives" }),
],
});
```
Usage:
```ts
const initiatives = store.collection("initiatives");
await initiatives.create({ id: "launch-billing-flow" });
await initiatives.update("launch-billing-flow", patch);
await store.sync();
```
Important separation:
```text
Git backend knows Git.
Store knows sync/lifecycle/events.
Collection knows content structure.
Initiative collection knows initiatives.
```
## UI Direction
The UI should be content-agnostic at the core:
- browse folders/files
- edit Markdown/YAML
- preview content
- search
- show diffs/history
- sync status
Collections can add richer views:
- initiative status view
- contract table
- owner/dependency graph
- linked repo-change view
The UI should work no matter which collections are mounted.
## Open Questions
- What is the first concrete context store command surface?
- Should stores be called `context`, `store`, or something more product-facing?
- Where should enterprise context stores live by default: customer GitHub,
OpenSpec-managed Git, or later hosted cloud?
- How do non-technical users edit Git-backed content without feeling Git?
- What is the minimum viable auto-sync behavior before conflict handling gets
painful?
- How does an initiative contract graduate into a canonical owner repo contract?
- How should linked repo changes report status back into an initiative without
becoming Jira?
- How should monorepos map capabilities, folders, and repo-local changes?
- What should the first repo-change linking command be called?
- Which initiative progress/status signals are useful after linked changes
exist?
## Suggested Next Direction
After the initial store, collection, and initiative create/list foundations,
build the next slices in this order:
1. Reconcile the Initiative MVP around create/list, validation, templates, and
explicit deferral of read/update/delete policy.
2. Add minimal context-store UX for setup, registration, listing, and doctoring.
3. Add agent-first initiative discovery with `initiative show --json` and
registered-store lookup.
4. Add repo-local change metadata and an agent-friendly create/link flow for
`--initiative`.
5. Reject standalone `initiative resolve`; local path mapping belongs to
workspaces, not initiative commands.
6. Let workspaces open initiative-aware local views once show/link semantics
exist.
7. Add local-to-initiative escalation UX.
8. Harden team-shared coordination, sync, conflict guidance, and progress
status after real usage shapes those needs.
@@ -0,0 +1,23 @@
# Context Store And Initiatives Questions
## Open
- Should the user-facing command vocabulary say `context`, `store`, or
something more product-facing?
- What migration or compatibility path should existing workspace-planning
changes get once initiatives exist?
- How should linked repo changes report progress back into an initiative without
becoming a Jira clone?
- How should monorepos map capabilities, folders, and repo-local changes?
- Should OpenSpec support configurable change homes across context stores and
local OpenSpec repos, and what ownership rules keep that model safe?
## Resolved
- Workspaces should not be the durable shared planning object.
- Initiative roadmap implementation should be tracked inside the initiative
until repo-owned implementation changes are needed.
- The first concrete context store command surface is `context-store setup`,
`context-store register`, `context-store list`/`ls`, and
`context-store doctor`. Sync, push/pull, remotes, and conflict handling are
future work.
@@ -0,0 +1,775 @@
# Context Store And Initiatives Roadmap
Status: historical beta roadmap snapshot.
This roadmap preserves the implementation queue that existed while the
context-store and workspace model was being explored. It is not the active
roadmap for current simplification work.
For current direction, start with:
1. `openspec/work/simplify-context-and-workspace-model/goal.md`
2. `openspec/work/simplify-context-and-workspace-model/roadmap.md`
The historical product decision underneath this roadmap was:
```text
Context stores sync truth.
Collections shape truth.
Initiatives coordinate work.
Workspaces open local views.
Changes implement repo-owned slices.
```
## Historical Beta Priority Snapshot
At the time, the manual beta pass pulled first-run friction forward. This was
the historical working order before investing in deeper schema or lifecycle
machinery:
1. Finish the manual beta reality pass enough to keep the next slices grounded.
2. Item 12, context-store first-run and cleanup UX: interactive no-argument setup,
target-path safety, and a supported unregister/remove path.
3. Skip Item 13 as an implementation item for now. Preserve the handoff
findings, but avoid hardcoding linear "next step" guidance until the agent
handoff model is clearer.
4. Item 14, workspaces beta guide split: make user docs match the interactive
setup path and keep exact flags in the agent playbook.
5. Item 15, context store project roots and schema-led initiatives: sparse initiative
creation and store-local schemas.
Escalation UX, team-sharing hardening, and initiative-hosted target-bound
changes remain important, but they should wait until the first-run path feels
boring in the good way.
Before workspaces become public/stable, run Item 19 as a late beta cleanup pass
so beta compatibility code is reviewed intentionally instead of treated as a
permanent contract.
## 1. Lock The Direction
Goal: make the workspace-to-initiative pivot explicit so future workspace work
does not keep implementing the older "workspace owns the plan" model.
Ship:
- Record that workspaces are local working views, not durable shared planning
objects.
- Record that initiatives are the durable coordination object for cross-team or
cross-repo work.
- Mark the current workspace apply, verify, and archive direction as deferred or
superseded until initiative-linked repo changes exist.
- Keep the already-built workspace setup, link, open, update, and doctor
behavior as useful beta infrastructure.
Done when:
- Fresh agents can tell which workspace ideas still apply and which ones should
not steer implementation.
Locked disposition:
- Keep workspace setup, link, relink, list, open, update, and doctor as beta
local-view infrastructure.
- Keep "workspace visibility is not change commitment" as a safety rule for
linked repos and folders.
- Supersede "workspace is the durable planning home" with "initiatives are the
durable coordination object."
- Supersede workspace-level planning artifacts as the canonical shared
cross-repo plan.
- Defer workspace apply, verify, and archive as first-class lifecycle commands
until initiative-linked repo-local changes exist.
- Defer branch/worktree orchestration, strong cross-repo validation, dependency
graph enforcement, and shared contract governance.
Fresh-agent historical reading rule:
- Start from `openspec/work/simplify-context-and-workspace-model/goal.md` and
`openspec/work/simplify-context-and-workspace-model/roadmap.md` for current
product authority.
- Use `openspec/initiatives/context-store-and-initiatives/direction.md` as
historical beta direction, not as the current product authority.
- Treat `openspec/changes/workspace-reimplementation-roadmap/HISTORICAL_DIRECTION.md` and
`openspec/changes/workspace-reimplementation-roadmap/` as historical reference
material for preserved local-view behavior and POC lessons.
- Do not pick up `workspace-apply-repo-slice` or
`workspace-verify-and-archive` as the next implementation slice unless a later
initiative-linked repo-change design explicitly reactivates them.
## 2. Stabilize Workspace As Local View
Goal: keep workspaces useful without making them the source of truth.
Ship:
- Workspace guidance that routes durable coordination to initiatives,
implementation planning to repo-local changes, and linked repos or folders to
local context until an edit root is selected.
- Workspace-open behavior that launches the local planning view with linked
folders visible.
- Workspace doctor/status output that explains local path mappings, unresolved
links, installed agent skills, and repair steps.
- Clear docs that `workspace update` refreshes local agent guidance and does not
modify linked repos.
Done when:
- A user can set up a workspace, link repos, open an agent, and understand that
the workspace is a local view over context, not the canonical shared plan.
## 3. Add Context Store Foundation
Goal: create the generic local context-store foundation that can later hold
initiatives and other shared context collections. Sync/watch behavior remains a
future hardening slice.
Ship:
- A context store abstraction with generic local operations: read, write,
delete, and list.
- A first Git-shaped backend model that can point at a local store root.
- A test/memory backend for fast tests and prototypes.
- A store configuration model that does not contain initiative-specific logic.
Done when:
- OpenSpec can create and manipulate files inside a local context store without
the core store layer knowing what those files mean. Pull, push, watch,
remote creation, and conflict handling are tracked as future sync work.
## 4. Add Collection Foundation
Goal: let product-specific content systems live inside a context store without
hardcoding every future concept into the store layer.
Ship:
- A collection interface with a mounted folder namespace.
- Rules that keep a collection's writes inside its mount.
- Basic collection validation and template hooks.
- A way for collections to expose optional agent guidance or UI metadata later.
Done when:
- The context store can host a mounted `initiatives/` collection while staying
generic enough for future collections like decisions, API catalogs, or
playbooks.
## 5. Ship Initiative MVP
Goal: give coordinated work a durable, shared, agent-consumable home.
Ship:
- Initiative creation and listing.
- A default initiative file shape:
```text
initiatives/<id>/
initiative.yaml
requirements.md
design.md
decisions.md
questions.md
tasks.md
```
- Templates for product intent, accepted requirements, design decisions, open
questions, and coordination tasks.
- Validation for required initiative metadata.
- Explicit deferral of full read/show, update, and delete policy until the
agent-first discovery and lifecycle needs are clearer.
Done when:
- A user or agent can create and list initiatives as shared planning objects
before any repo has committed to implementation details.
## 6. Add Minimal Context Store UX
Goal: make shared initiative storage usable before repo handoff or workspace
opening depends on it.
Ship:
- `context-store setup <id>` for creating a local Git-backed store folder with
portable store metadata and local registration.
- `context-store register <path>` for registering an existing clone or folder,
defaulting the store id from the repo or folder name.
- `context-store list` and `context-store doctor` for local visibility and
non-mutating diagnostics.
- `initiative list` defaulting to all registered stores, with `--store` as a
filter and `--store-path` as an escape hatch.
- Minimal human output and JSON output suitable for agents.
Done when:
- A single developer or teammate can create or register a shared context store,
list initiatives across registered stores, and diagnose missing or broken
local store setup without learning the internal registry layout.
## 7. Add Agent-First Initiative Discovery
Goal: let an agent resolve the initiative the user named and read canonical
initiative context from the source of truth.
Ship:
- `initiative show <id>` that searches registered stores by default.
- Ambiguity handling when the same initiative id exists in multiple stores.
- JSON output with canonical initiative metadata, store identity, initiative
root path, and metadata path.
- Human output focused on identity and available files, not work progress.
Done when:
- An agent can answer, "Which initiative did the user mean, where is the
canonical context, and where is the initiative metadata?"
## 8. Connect Repo-Local Changes To Initiatives
Goal: split shared coordination from repo-owned implementation plans cleanly.
Discussion points to confirm before implementation:
- Should the create/link flow explicitly report where the change lives, which
initiative it references, and the next suggested command?
- Should `--initiative <id>` search registered stores by default, or should it
require `--store` when more than one store is registered?
- What should the command do when the initiative exists but the current repo has
no obvious ownership match?
Ship:
- Repo-local change metadata that can reference an initiative by store id and
initiative id.
- An agent-friendly create or link flow such as
`new change <id> --initiative <store>/<initiative>`.
- Guidance that repo-local changes remain responsible for implementation,
validation, and archive.
- No checked-in `initiative.md` snapshot by default; agents read canonical
initiative files live from the context store.
Done when:
- One initiative can coordinate several repo-local changes without copying the
shared plan into every repo, storing machine-local links in the initiative, or
making the initiative own implementation artifacts.
## 9. Reject Initiative Resolve
Decision: do not add `openspec initiative resolve`, now or later.
Rationale:
- `initiative show` already resolves canonical shared initiative context.
- A workspace is the local view over repos, folders, context stores, and
initiatives.
- Repo-local changes already carry durable initiative links in checked-in
`.openspec.yaml` metadata.
- Repo-local status already reports work progress.
- A standalone resolve command would either duplicate workspace local-view state
or produce weak output when no workspace is present.
Do not ship:
- `openspec initiative resolve <id>`
- all-workspace or all-repo scans for initiative availability
- explicit path scanning as an initiative command
- Git remote matching for initiative participation
- repo ownership inference
- cloning, branch creation, or worktree creation as part of initiative
resolution
- initiative backlinks
- local availability or progress dashboards under the initiative command
Done when:
- Future agents can see that "initiative resolve" is intentionally rejected and
should not be revived under another command name.
## Proposed Discussion Point: Add Initiative Next / Agent Handoff UX
Status: candidate work item, not locked into the numbered roadmap yet.
Question to confirm:
- Should this become a roadmap item before "Let Workspaces Open Initiatives"?
Goal: give agents and users a small "what now?" command after initiative
discovery from the current repo or workspace, without turning it into a
dashboard or progress/status surface.
Possible shape:
```bash
openspec initiative next billing-launch --json
```
Possible JSON answer:
```json
{
"initiative": "billing-launch",
"next_action": "create_repo_change",
"reason": "initiative found, no linked local change exists for this repo",
"suggested_command": "openspec new change add-billing-api --initiative billing-launch"
}
```
Discussion points to confirm before implementation:
- Is `initiative next` the right command name, or should this guidance belong
inside workspace initiative opening or repo-local status?
- Should it return exactly one suggested next action, or a ranked set of options?
- Should it ever inspect work progress, or stay limited to handoff/readiness?
- How should it behave when no stores are registered, the initiative is
ambiguous, or the local repo is unrelated?
Done when, if accepted:
- An agent can answer "what should I do next for this initiative from here?"
without guessing across `show`, workspace state, and repo-local
change metadata.
## 10. Let Workspaces Open Initiatives
Goal: connect durable initiative context to this runtime's local working view
after initiative show and repo-change linkage exist.
Locked direction:
- A workspace does not contain the work. It remembers how this runtime opens the
work.
- Persist only tiny private local view choices.
- Generate opener-specific runtime files on open.
- Attach initiative context and selected existing local repos or folders.
- Do not clone, branch, create worktrees, use submodules, or infer local repos in
this slice.
- Context-only open is valid.
Product decision status:
- No remaining Item 10 product decisions are open. Implementation may still
uncover mechanical details, but the intended UX shape is locked.
Command UX decision:
- Use `openspec workspace open --initiative <initiative>`.
- Support `<store>/<initiative>` and `<initiative> --store <store>`.
- Support `openspec workspace open <workspace-name> --initiative <initiative>`
when the user wants to choose the local workspace identity explicitly.
- If only `<initiative>` is provided, proceed when exactly one registered
context store has that initiative id.
- On ambiguity, list exact matches and require an explicit store selector.
- On no exact match, show likely matches when available and suggest `openspec
initiative list`; do not silently open a fuzzy match.
- If the user omits a workspace name, derive a friendly default from the
initiative id when that is unambiguous; otherwise require the user to pick an
explicit workspace name.
Open target decision:
- Open the initiative directory by default, not the whole context store.
- Generated guidance and JSON output should still report the context store root
and that broader context is available.
- A later explicit option may open the whole context store, but broad store
scope is not the Item 10 default.
Local view record decision:
- Use one private local view record for initiative-aware local views.
- Store initiative-view state in the root `workspace.yaml` file.
- The record stores selected context-store binding, initiative, local links,
opener, and selected tools. The binding may preserve a registry selector or a
runtime-local path selector.
- The context binding is optional, so a workspace can also be a custom local view
with linked folders and no initiative.
Workspace storage decision:
- Store each private workspace view under
`getGlobalDataDir()/workspaces/<workspace-name>/`.
- The workspace name is the local identity. Selected store and initiative, if
any, are data inside the private record rather than path segments.
- Use one durable `workspace.yaml` at the workspace root.
- Generate `AGENTS.md`, opener workspace files, and tool-specific skills at the
workspace root.
- Do not introduce a separate generated-output directory for Item 10.
Runtime identity decision:
- Use `getGlobalDataDir()` as the cross-platform runtime-local boundary.
- Local paths are valid only in the runtime that wrote the private
`workspace.yaml`.
- Do not add path translation or a separate `<runtime-id>` path segment in Item
10.
Prepare/JSON decision:
- Keep `workspace open --json` as a machine-facing receipt for the same open
operation.
- Do not add `--prepare-only` for Item 10.
- JSON should return useful generated paths, selected context, opened roots,
skipped roots, opener, launch status, and warnings rather than a bare success
response.
Codex Desktop decision:
- Open the generated workspace root as the Codex Desktop project.
- Expose attached initiative and linked repo/folder paths through generated
guidance and `workspace open --json` output.
- Defer Desktop multi-root automation until there is a clearer Desktop contract.
Edit-boundary decision:
- Emit advisory boundaries only.
- Label initiative/context-store files as shared coordination context and linked
repos/folders as local implementation context when selected.
- Do not enforce write restrictions in Item 10.
Ship:
- Private local view state that can remember the selected context store,
selected initiative, selected local links, opener, and selected tools for this
runtime.
- `workspace open` support for generating opener-specific runtime files and
opening initiative context plus locally resolved linked repos/folders.
- Agent guidance and machine-readable `workspace open --json` output that
explain the current initiative, opened roots, skipped roots, local paths, and
advisory edit boundaries.
- Workspace-name reuse behavior that avoids silently repointing an existing
workspace to a different initiative.
- Open-time warnings that skip missing linked repos/folders while failing when
the selected initiative or context store cannot be resolved.
- Continued support for custom non-initiative workspaces as first-class local
views.
- Doctor guidance for missing context stores, missing linked repos/folders, and
stale local view records.
Done when:
- A teammate can open the same initiative in their runtime while using their own
local paths and selected repo subset.
- Generated runtime files are clearly derived and can be regenerated without
losing the user's local view choices.
## 11. Manual Beta Reality Pass
Status: proposed immediate beta-learning item.
Goal: manually run what exists and use the friction to update initiative notes
before designing more surface area.
Ship:
- A fresh-user walkthrough of context-store setup, initiative creation,
workspace opening, repo linking, doctor output, and repo-local linked change
creation.
- Notes on what felt clear, what felt odd, where prompts were missing, and where
docs pushed too many flags onto the user.
- A short disposition that separates docs-only fixes from follow-on
implementation slices.
Done when:
- The initiative contains concrete notes from trying the current beta flow by
hand.
- The next implementation or docs slice is grounded in observed friction rather
than guessed workflow shape.
## 12. Context Store First-Run And Cleanup UX
Goal: make context-store setup and cleanup feel like a normal local workflow,
without adding sync, remote, or governance automation.
Work item:
`work-items/12-context-store-first-run-and-cleanup-ux/`
Ship:
- Interactive no-argument `context-store setup` for terminal users.
- Deterministic non-interactive and JSON behavior when required setup choices
are missing.
- Target-path safety output for managed defaults, explicit paths, existing Git
repos, and non-empty directories.
- A supported local cleanup path for unregistering or removing a context store
without hand-editing the registry.
- Setup output that explains local registry state and Git state, including
uncommitted shared-store files after `--init-git`.
Done when:
- A fresh user can set up or clean up a local context store without knowing
hidden registry paths, environment variables, or manual file edits.
## 13. Agent Handoff Output And Delivery Polish
Status: deferred as an implementation item.
Goal, if revisited: define an agent handoff receipt model that reports what
exists, where it lives, and which affordances are available without prescribing
one linear next step.
Work item:
`work-items/13-agent-handoff-output-and-delivery-polish/`
Ship:
Do not ship fixed "Next for your agent" guidance yet. The current shape assumes
that users and agents move through the beta flow linearly, but real agentic
workflows may inspect, branch, skip steps, or start from existing context.
Preserve for future exploration:
- Whether command output should include context receipts, available affordances,
or nothing beyond deterministic paths.
- Whether direct path fields like `created_paths` are a small standalone receipt
improvement rather than part of a broader handoff model.
- How delivery wording should distinguish baseline OpenSpec guidance from
workflow entrypoints without coupling it to this handoff item.
## 14. Workspaces Beta Guide Split
Status: proposed immediate beta-learning item.
Goal: make the beta docs reflect the intended division of labor:
```text
Users make local choices.
Agents run OpenSpec work commands.
```
Ship:
- A user-facing guide that prefers interactive terminal setup for local choices
such as context-store location, opener, and local repo paths.
- An agent-facing CLI playbook that keeps explicit commands, JSON output,
current-directory rules, and caveats.
- A clear rule for which flags are normal user-facing escape hatches and which
are mostly agent-facing precision.
Done when:
- A new user can get to a working beta setup without reading a flag-heavy CLI
tutorial.
- A coding agent can still find the exact commands needed to create initiatives,
link repo-local changes, and inspect state safely.
## 15. Context Store Project Roots And Schema-Led Initiatives
Goal: let context stores behave like OpenSpec roots for shared planning config
and schemas, while keeping implementation changes repo-owned by default.
Work item:
`work-items/15-context-store-project-roots-and-schema-led-initiatives/`
Product decision to confirm:
- A context store can have `openspec/config.yaml` and `openspec/schemas/` like a
repo after `openspec init`.
- That project-like shape is for shared context configuration and initiative
schemas. It must not silently make the context store an implementation repo.
- `initiative create` should create a sparse shell and let reviewed initiative
artifacts grow through schema-led status/instructions.
Ship:
- Context-store setup that creates or supports store-local OpenSpec config.
- A default initiative schema for high-level requirements and design artifacts.
- Sparse initiative creation: `initiative.yaml` plus a short `brief.md`, with no
`TBD` placeholders and no default `tasks.md`.
- Initiative artifact status and instructions output rooted in the initiative
directory.
- Guardrails so `openspec new change` does not accidentally create executable
repo-local changes inside a context store just because the store has an
`openspec/` directory.
- Compatibility for existing six-file MVP initiatives.
Done when:
- A context store can resolve store-local initiative schemas.
- Agents can iteratively create initiative requirements and design artifacts
from CLI instructions.
- Existing MVP initiatives continue to list and show.
- Docs stop presenting initiative creation as "fill every markdown file now."
## 16. Add Escalation UX
Goal: let users start locally and upgrade only when coordination is actually
needed.
Work item:
`work-items/16-add-escalation-ux/`
Ship:
- Explore/propose guidance that starts in the current repo by default.
- A recommendation path when work spans multiple owned areas:
```text
This appears to span multiple owned areas.
OpenSpec can upgrade it into a coordinated initiative and carry the current
planning context forward.
```
- Carry-forward behavior for the current change name, product goal, notes,
inferred areas, and relevant questions.
- Clear prompts that ask about concrete affected areas rather than abstract
storage models.
Done when:
- Coordinated planning feels like a continuation of local planning, not a
workflow restart.
## 17. Harden Team-Shared Coordination
Goal: make initiatives practical for teams without turning setup into an admin
ceremony.
Work item:
`work-items/17-harden-team-shared-coordination/`
Ship:
- A recommended Git-backed shared context store pattern.
- Lightweight teammate onboarding:
```text
Clone the context store.
Run openspec workspace doctor.
Open the initiative with your agent.
```
- Repair flows for local path mappings.
- Sync status and conflict guidance.
- Clear separation between committed initiative state and machine-local
workspace state.
Done when:
- Several teammates can share the same initiative while each keeps their own
local checkout layout.
## 18. Explore Initiative-Hosted Target-Bound Change Artifacts
Goal: decide whether shared initiative artifacts can graduate into executable
OpenSpec changes only after they are bound to a target repo or spec root,
without blurring initiative coordination, repo ownership, and workspace
local-view boundaries.
Work item:
`work-items/18-explore-initiative-hosted-target-bound-change-artifacts/`
Discussion points to confirm before exploration:
- Should "change home" stay internal resolver language, with user-facing
phrasing like "where should this plan live?" and "editable target"?
- What is the difference between initiative work items, briefs, target-bound
changes, and repo-local changes?
- What portable target metadata is required before an initiative-hosted artifact
can be considered implementation-ready?
- Should shared target-bound changes require explicit opt-in, or can
initiative/store policy select them?
- What user/team scenario would justify an initiative-hosted target-bound change
instead of a repo-local linked change?
Ship:
- Audit commands, templates, validation, archive, apply, completion, and docs
for repo-local `openspec/changes/` assumptions.
- Define the concepts of artifact home, implementation target, allowed edit
roots, and action context.
- Decide how initiative-hosted target-bound changes bind to repo specs,
implementation roots, branches, validation, archive, and sync/conflict
behavior.
- Define agent-readable JSON output for work target, artifact home,
implementation target, initiative link, edit boundaries, unsupported
lifecycle commands, and next commands.
- Record compatibility behavior for existing repo-local and workspace-local
changes.
- Recommend whether this should become an implementation slice, remain deferred,
start as initiative work items only, or be limited to specific schemas or
workflows first.
Done when:
- The initiative has a concrete recommendation, opt-in/config examples, affected
command list, and go/no-go criteria for implementation.
## 19. Review Workspace Beta Compatibility Before Public Release
Goal: decide which workspace beta compatibility behavior should survive into the
public workspace contract, and remove or migrate the rest while workspaces are
still unpublished.
Work item:
`work-items/19-review-workspace-beta-compatibility-before-public-release/`
Why this is late:
- Workspaces are still beta and not public/stable yet.
- We do not need to preserve every intermediate beta file shape forever.
- Early cleanup risks churn while first-run UX and initiative behavior are still
changing.
- The right compatibility contract is easier to define after manual beta usage
shows which local workspace artifacts real users have actually created.
Ship:
- Inventory workspace compatibility code, including legacy split state readers,
registry fallbacks, `codex` to `codex-cli` aliases, generated `.gitignore`
cleanup, and empty compatibility shims.
- Classify each path as public contract, beta migration, test-only shim, or
removable dead weight.
- Remove beta-only shims that only support unpublished intermediate workspace
shapes.
- Define any migration behavior worth keeping for people who tried the beta.
- Update docs, tests, generated guidance, and release notes so the public
workspace compatibility promise is explicit.
Done when:
- The workspace compatibility surface is intentionally small.
- Public docs do not imply support for beta-only workspace internals.
- Any remaining migration code has a clear owner, reason, and removal policy.
## Later, Not First
These are important, but should wait until the initiative model has real usage:
- Workspace apply, verify, and archive as first-class lifecycle commands.
- Branch or worktree orchestration.
- Strong cross-repo validation.
- Dependency graph enforcement.
- Shared contract ownership workflows.
- Sponsor/driver governance flows.
- Initiative progress/status dashboards.
- Cloud-hosted context stores.
## Suggested Shipping Sequence
1. Lock the direction and defer old workspace lifecycle slices.
2. Stabilize workspace as local view and agent launcher.
3. Add context store foundation.
4. Add collection foundation.
5. Ship initiative MVP.
6. Add minimal context-store UX.
7. Add agent-first initiative discovery.
8. Link repo-local changes to initiatives.
9. Keep initiative resolve rejected; use workspace local-view mapping instead.
10. Let workspaces open initiatives.
11. Manual beta reality pass.
12. Context store first-run and cleanup UX.
13. Skip agent handoff output and delivery polish until the handoff model is
clearer.
14. Workspaces beta guide split.
15. Context store project roots and schema-led initiatives.
16. Add local-to-initiative escalation UX.
17. Harden team-shared coordination.
18. Explore initiative-hosted target-bound change artifacts.
19. Review workspace beta compatibility before public release.
Pending discussion: revisit handoff receipts after the beta guide and sparse
initiative model clarify what context agents actually need.
@@ -0,0 +1,321 @@
# Context Store And Initiatives Tasks
Status: historical beta progress snapshot.
This file preserves the task state from the old context-store and workspace
initiative. It is not the active implementation queue for current
simplification work.
For current direction, start with:
1. `openspec/work/simplify-context-and-workspace-model/goal.md`
2. `openspec/work/simplify-context-and-workspace-model/roadmap.md`
Historical roadmap items live in `roadmap.md`; detailed working notes live
under `work-items/`.
## Historical Beta Priority Snapshot
At the time, the manual beta pass prioritized the things a fresh user hit while
getting started before deeper model work:
1. Finish Item 11 observations enough to keep implementation grounded.
2. Item 12: no-argument context-store setup, path safety, and
cleanup.
3. Skip Item 13 as an implementation item for now. Preserve the findings, but
do not hardcode linear "next step" guidance until the agent handoff shape is
better understood.
4. Item 14: update the beta guide so it matches the improved first-run flow.
5. Item 15: context-store project roots and sparse schema-led
initiatives.
6. Items 16-18: leave escalation, team hardening, and initiative-hosted
target-bound changes until after the onboarding path feels sane.
7. Item 19: review beta workspace compatibility near the end, before workspace
behavior becomes public/stable.
## 1. Lock The Direction
Work item: `work-items/01-lock-the-direction/`
- [x] Record the workspace-to-initiative product boundary in initiative docs.
- [x] Mark the old workspace reimplementation roadmap as historical reference.
- [x] Defer workspace apply, verify, and archive until initiative-linked repo
changes exist.
- [x] Complete a non-spec direction pass so roadmap, work items, docs, and
active change artifacts point to the initiative as product intent.
- [x] Decide whether user-facing workspace docs need any change now; default to
no unless they misrepresent current behavior.
- [x] Decide how to handle active no-task workspace changes after the
disposition pass.
- [x] Record final evidence and remaining risks for Item 1.
## 2. Stabilize Workspace As Local View
Work item: `work-items/02-stabilize-workspace-as-local-view/`
- [x] Re-anchor generated workspace guidance in the initiative direction.
- [x] Decide that generated guidance should stop recommending workspace-level
`changes/` as the planning home for coordinated work.
- [x] Decide that `workspace update` should refresh generated workspace
guidance for existing workspaces.
- [x] Decide that workspace-planning action context should treat beta workspace
artifacts as local compatibility context.
- [x] Decide to defer doctor installed-skill summaries and only update stale
`workspace update` wording for now.
- [x] Define exact local-view behavior to preserve.
- [x] Review current workspace setup, link, relink, list, open, update, and
doctor behavior against that definition.
- [x] Identify any product wording or guidance gaps left after Item 1.
## 3. Add Context Store Foundation
Work item: `work-items/03-add-context-store-foundation/`
- [x] Define the initial store/backend data model.
- [x] Decide that the first slice is core API only, with no CLI surface yet.
- [x] Decide that the first backend is Git/local checkout config only.
- [x] Decide where context store roots, local registry YAML, and portable store
metadata YAML live.
- [x] Implement context-store foundation helpers and tests.
## 4. Add Collection Foundation
Work item: `work-items/04-add-collection-foundation/`
- [x] Define collection mount rules.
- [x] Decide validation/template hooks stay inert extension fields for this
slice.
- [x] Prove `initiatives/` can mount without store-specific logic.
## 5. Ship Initiative MVP
Work item: `work-items/05-ship-initiative-mvp/`
- [x] Define initiative file shape and validation.
- [x] Add templates for requirements, design, decisions, questions, and tasks.
- [x] Implement create/list mounted collection operations and CLI adapter.
- [x] Decide full read/show, update, and delete policy should move to later
agent-first discovery and lifecycle work.
## 6. Add Minimal Context Store UX
Work item: `work-items/06-add-minimal-context-store-ux/`
- [x] Create Item 6 work-item tracking notes.
- [x] Define high-level `context-store setup`, `register`, `list`, and `doctor`
UX direction.
- [x] Decide exact checked-in store metadata and machine-local registry
behavior.
- [x] Decide setup/register/list/doctor human behavior and responsibility split.
- [x] Decide `initiative list` partial-success behavior across registered
stores.
- [x] Decide final Item 6 edge cases: id inference, non-empty setup folders,
registry conflicts, empty states, JSON exit behavior, and static completions.
- [x] Update `initiative list` to default across registered stores, with
`--store` as a filter and `--store-path` as an escape hatch.
- [x] Add focused tests and verification for context-store CLI behavior.
## 7. Add Agent-First Initiative Discovery
- [x] Define `initiative show <id>` human and JSON output.
- [x] Search registered stores by default and handle ambiguous initiative ids.
- [x] Return canonical initiative metadata, store identity, root path, and
metadata path for agent reads.
- [x] Keep work-progress status out of this command.
## 8. Connect Repo-Local Changes To Initiatives
Work item: `work-items/08-connect-repo-local-changes-to-initiatives/`
- [x] Decide that the initiative link lives in repo-local `.openspec.yaml`.
- [x] Add repo-local initiative metadata.
- [x] Add an agent-friendly create or link flow for repo-local changes.
- [x] Decide command naming for `--initiative` linking on new change creation.
- [x] Confirm whether create/link output should report where the change lives,
which initiative it references, and the next suggested command.
- [x] Confirm whether `--initiative <id>` searches registered stores by default
or requires explicit store selection in multi-store setups.
- [x] Keep canonical initiative context in the context store; do not add a
checked-in `initiative.md` snapshot by default.
## 9. Reject Initiative Resolve
Work item: `work-items/09-add-initiative-resolve/`
- [x] Pressure-test whether a standalone `initiative resolve` command is needed.
- [x] Decide not to add `openspec initiative resolve`, now or later.
- [x] Keep canonical initiative discovery in `initiative show`.
- [x] Keep local path mapping in workspace behavior.
- [x] Keep implementation progress in repo-local status.
- [x] Reject all-repo scans, all-workspace scans, explicit path scanning as an
initiative command, Git remote matching, cloning, worktree creation, and
initiative backlinks.
## Proposed Discussion: Initiative Next / Agent Handoff UX
Work item draft:
`work-items/proposed-initiative-next-agent-handoff-ux/`
- [ ] Decide whether to add this as a numbered roadmap item between Item 9 and
Item 10.
- [ ] Decide whether the surface is `initiative next`, workspace initiative
opening, or repo-local status guidance.
- [ ] Decide whether it suggests one next action or multiple ranked options.
- [ ] Decide that progress/status stays out of scope, unless we explicitly want
this command to grow into a broader status surface.
## 10. Let Workspaces Open Initiatives
- [x] Create Item 10 work-item tracking notes.
- [x] Lock the command UX for opening an initiative as a local workspace view.
- [x] Define the private local view record for selected context store,
initiative, local links, opener, and selected tools.
- [x] Decide the private local view record storage namespace and keying.
- [x] Decide the default open target: initiative directory versus full context
store.
- [x] Decide where generated runtime files live and how they are regenerated.
- [x] Define runtime identity rules for macOS, Codespaces, WSL, SSH, and
containers without path translation.
- [x] Decide the prepare/JSON surface for agents and desktop integrations.
- [x] Decide the Codex Desktop behavior for generated workspace roots and attached
paths.
- [x] Define advisory edit-boundary output for Item 10.
- [x] Confirm this slice opens known local paths only and does not create
clones, branches, worktrees, or submodules.
## 11. Manual Beta Reality Pass
Work item: `work-items/11-manual-beta-reality-pass/`
- [ ] Manually run the current context-store, initiative, workspace, and
repo-local change flows from a fresh user's point of view.
- [ ] Capture notes on confusing commands, missing prompts, unclear output, and
places where the docs over-explain or under-explain.
- [ ] Update initiative notes as observations come in.
- [ ] Decide which findings should become implementation slices versus docs-only
fixes.
## 12. Context Store First-Run And Cleanup UX
Work item: `work-items/12-context-store-first-run-and-cleanup-ux/`
- [x] Decide and implement interactive no-argument `context-store setup`.
- [x] Define target-path safety behavior for managed defaults, explicit paths,
Git repos, and non-empty directories.
- [x] Add local cleanup support for unregistering or removing a context store.
- [x] Make setup and cleanup output report the agreed human-facing summary and
exact JSON state without workflow `next_commands`.
- [x] Update docs and tests for first-run setup and cleanup behavior.
## 13. Agent Handoff Output And Delivery Polish
Work item: `work-items/13-agent-handoff-output-and-delivery-polish/`
Status: deferred. Do not implement fixed "Next for your agent" output from this
item yet.
- [ ] Revisit the handoff model after Item 14/15 clarify the beta guide and
sparse initiative flow.
- [ ] If needed, split deterministic receipt improvements such as direct
`created_paths` into a smaller future implementation slice.
- [ ] Avoid prescribing one linear workflow path; future handoff output should
report state, paths, and possible affordances that agents can compose.
## 14. Workspaces Beta Guide Split
Work item: `work-items/14-workspaces-beta-guide-split/`
- [ ] Update the user-facing guide to prefer interactive terminal setup for
local choices.
- [ ] Move initiative creation, initiative editing, and repo-local change
creation into "ask your coding agent" guidance.
- [ ] Keep explicit flags, JSON output, cwd rules, and caveats in the
agent-facing CLI playbook.
- [ ] Decide which flags remain useful in user docs as escape hatches for
ambiguity.
- [ ] Record any interactive prompt gaps found while writing the guide.
## 15. Context Store Project Roots And Schema-Led Initiatives
Work item:
`work-items/15-context-store-project-roots-and-schema-led-initiatives/`
- [x] Create Item 15 work-item tracking notes.
- [ ] Update initiative direction language so context stores are OpenSpec-aware
shared project roots, not only cross-team/cross-repo coordination folders.
- [ ] Decide the minimal context-store OpenSpec structure:
`.openspec-store/store.yaml`, `openspec/config.yaml`,
`openspec/schemas/`, and collection mounts.
- [ ] Decide the store-local config shape for initiative collection defaults,
including whether to use `collections.initiatives.schema`.
- [ ] Decide how context-store setup creates, preserves, or repairs
store-local `openspec/config.yaml`.
- [ ] Define the built-in high-level initiative schema and its initial
artifacts.
- [ ] Decide whether `initiative create` creates only `initiative.yaml`, or
`initiative.yaml` plus one schema-selected seed artifact such as `brief.md`.
- [ ] Replace eager six-file initiative scaffolding with sparse iterative
creation.
- [ ] Add initiative artifact status/instructions behavior rooted at the
initiative directory.
- [ ] Reuse project-local schema resolution with the context-store root as the
project root for initiative commands.
- [ ] Decide whether schema CLI commands need `--store` or `--store-path`
selectors.
- [ ] Guard planning-home resolution so context stores with `openspec/config.yaml`
do not accidentally make the store an implementation repo.
- [ ] Preserve existing six-file beta initiatives as readable valid
initiatives.
- [ ] Update docs, generated agent guidance, and tests for the project-like
context-store model.
## 16. Add Escalation UX
Work item: `work-items/16-add-escalation-ux/`
- [ ] Define local-to-initiative recommendation triggers.
- [ ] Carry current planning context into a new initiative.
- [ ] Keep prompts grounded in affected areas.
## 17. Harden Team-Shared Coordination
Work item: `work-items/17-harden-team-shared-coordination/`
- [ ] Document recommended Git-backed store setup.
- [ ] Define teammate onboarding and repair flows.
- [ ] Add sync status and conflict guidance.
## 18. Explore Initiative-Hosted Target-Bound Change Artifacts
Work item: `work-items/18-explore-initiative-hosted-target-bound-change-artifacts/`
- [ ] Confirm "change home" stays internal language and user-facing wording is
closer to "where should this plan live?"
- [ ] Define user-facing naming for initiative work items, briefs,
target-bound changes, artifact homes, and editable targets.
- [ ] Decide whether initiative-hosted artifacts can graduate into executable
changes, and which target metadata is required first.
- [ ] Decide the configuration or opt-in surface for repo-local versus
initiative-hosted artifacts.
- [ ] Define how `openspec new change` selects and reports the artifact home,
implementation target, initiative link, and action context.
- [ ] Decide how initiative-hosted target-bound changes bind to repo specs,
implementation roots, validation, archive, and sync behavior.
- [ ] Record compatibility behavior for existing repo-local and
workspace-local changes.
- [ ] Identify follow-on implementation slices and risks.
## 19. Review Workspace Beta Compatibility Before Public Release
Work item:
`work-items/19-review-workspace-beta-compatibility-before-public-release/`
- [ ] Inventory workspace beta compatibility code and tests.
- [ ] Decide which beta-only compatibility paths should be removed before
public release.
- [ ] Decide which compatibility paths need explicit migration behavior or
release notes.
- [ ] Remove low-value shims that only support unpublished beta workspace
shapes.
- [ ] Update docs, tests, and agent guidance to match the chosen public
workspace compatibility contract.
@@ -0,0 +1,154 @@
# Work Item 01 Evidence
## 2026-05-20 Initial Direction Lock
Completed before this work item folder was created:
- Added locked disposition to `roadmap.md`.
- Added locked product boundary to `direction.md`.
- Marked `openspec/changes/workspace-reimplementation-roadmap/START_HERE.md` as historical reference.
- Marked `openspec/changes/workspace-reimplementation-roadmap/HISTORICAL_DIRECTION.md` as historical reference.
- Marked `openspec/changes/workspace-reimplementation-roadmap/` as historical
reference.
- Marked `workspace-apply-repo-slice` and `workspace-verify-and-archive` as
deferred until initiative-linked repo-local changes exist.
Research findings:
- Current workspace setup, link, relink, list, open, update, and doctor behavior
is useful beta local-view infrastructure and should be preserved.
- Live specs describe current workspace-planning behavior. They should not be
rewritten during the initial direction lock; initiative artifacts should carry
future product intent until behavior changes.
- Existing runtime behavior should remain intact until initiatives and linked
repo-local changes can replace workspace-level planning.
Verification:
- `git diff --check` passed after the initial direction-lock edits.
- `openspec validate workspace-reimplementation-roadmap --no-interactive`,
`openspec validate workspace-apply-repo-slice --no-interactive`, and
`openspec validate workspace-verify-and-archive --no-interactive` failed
because those existing active changes have no spec deltas. That predates the
disposition wording and is tracked as an active-change cleanup question.
## 2026-05-21 Initiative Entry Point
Added `README.md` as the initiative entry point and linked it from
`.initiative.yaml`.
The README explains:
- this initiative is the source of product intent
- the reading order for direction, roadmap, tasks, decisions, questions, and
work items
- specs remain the current behavioral contract behind the code
- specs should not be rewritten for future intent until behavior changes
Updated `work-items/01-lock-the-direction/tasks.md` to mark the initiative
source-of-intent review complete.
## 2026-05-21 Historical Workspace Roadmap Review
Reviewed the historical workspace reimplementation entry points:
- `openspec/changes/workspace-reimplementation-roadmap/START_HERE.md`
- `openspec/changes/workspace-reimplementation-roadmap/HISTORICAL_DIRECTION.md`
- `openspec/changes/workspace-reimplementation-roadmap/README.md`
- `openspec/changes/workspace-reimplementation-roadmap/proposal.md`
- `openspec/changes/workspace-reimplementation-roadmap/POC_REFERENCE_GUIDE.md`
Added a guard near the top of
`openspec/changes/workspace-reimplementation-roadmap/HISTORICAL_DIRECTION.md` stating
that the remaining sections are historical POC follow-up direction and should
not be treated as active implementation guidance.
The roadmap README and handoff prompt already direct agents to the initiative
direction first and warn not to continue the old flat sibling queue unless a
later initiative-linked repo-change design reactivates it.
## 2026-05-21 Active Workspace Proposal Review
Reviewed active workspace proposal artifacts:
- `workspace-reimplementation-roadmap`
- `workspace-agent-guidance`
- `workspace-apply-repo-slice`
- `workspace-verify-and-archive`
Added small notes to `workspace-apply-repo-slice` and
`workspace-verify-and-archive` clarifying that the remaining proposal sections
are preserved for later reference, not discarded, and should become relevant
again after initiatives and initiative-linked repo-local changes exist.
Left `workspace-agent-guidance` untouched because it already has unrelated
worktree edits and should be handled as a separate active-change disposition
decision.
## 2026-05-21 User-Facing Docs Decision
Decision: Do not update `docs/cli.md` as part of the initial direction lock
unless it misrepresents current user-facing behavior.
Reasoning:
- The direction lock is for contributors and agents deciding what to build next.
- User-facing docs should describe current CLI behavior, not future initiative
intent.
- Initiatives do not have a CLI surface yet, so announcing the pivot in user
docs would draw attention to an internal product direction before users can act
on it.
Revisit user-facing docs when initiative or context-store commands exist, or if
current docs promise unavailable workspace apply, verify, or archive behavior.
Verification:
- `git diff --check` passed.
- No files under `openspec/specs/` or `schemas/workspace-planning/` were
modified in this pass.
## 2026-05-21 Active Change Disposition
Decision: Keep the active workspace changes as deferred reference placeholders.
Rationale:
- Workspace agent guidance, apply, verify, and archive are still expected to
matter after initiative infrastructure exists.
- The immediate focus should be context stores, initiatives, and
initiative-linked repo-local changes.
- Keeping the proposals preserves research and continuity without making them
the next implementation queue.
Follow-up:
- Revisit the deferred workspace changes after initiative-linked repo-local
changes define the durable handoff model.
## Final Item 1 State
Item 1 is complete.
What is locked:
- Initiative artifacts are the source of product intent for context stores,
collections, initiatives, workspaces, and repo-local changes.
- Specs and schemas remain the current behavioral contract and were not edited
for future intent.
- Historical workspace roadmap artifacts remain available as reference, not as
the active shipping queue.
- Deferred workspace changes remain active reference placeholders because their
domains are expected to matter after initiative infrastructure exists.
- User-facing docs were intentionally left unchanged unless they misrepresent
current behavior.
Remaining risks:
- `openspec list` still shows deferred workspace changes as active no-task
changes. This is intentional for now but may remain visually noisy.
- `workspace-agent-guidance` has unrelated worktree edits and should be handled
carefully before any future commit or archive decision.
- Future agents still need to read the initiative README first; the historical
workspace docs are safer now, but still contain useful old lifecycle details
deeper in the file.
@@ -0,0 +1,90 @@
# Work Item 01: Lock The Direction
## Goal
Make the workspace-to-initiative pivot explicit enough that future agents and
contributors do not continue implementing the older "workspace owns the plan"
model.
The locked model is:
```text
Context stores sync truth.
Collections shape truth.
Initiatives coordinate work.
Workspaces open local views.
Changes implement repo-owned slices.
```
## Direction
This work item is a non-spec direction pass, not a runtime removal.
Specs should continue to describe the current behavioral contract behind the
code. Product intent, roadmap decisions, and future direction should live in the
initiative artifacts until a later implementation change intentionally updates
behavior and its specs together.
Keep:
- workspace setup, link, relink, list, open, update, and doctor
- linked repos and folders as local planning context
- workspace-local skills as local agent guidance
- "workspace visibility is not change commitment"
Mark as transitional:
- workspace-level `changes/` planning
- `workspace-planning` schema
- workspace-scoped status/instructions compatibility
Defer:
- workspace apply, verify, and archive as first-class lifecycle commands
- branch/worktree orchestration
- strong cross-repo validation
- dependency graph enforcement
Supersede:
- workspace as the durable shared planning home
- workspace-level planning artifacts as the canonical cross-repo plan
- workspace change planning as the long-term source of truth
## Files To Review Now
- `openspec/initiatives/context-store-and-initiatives/*.md`
- `openspec/initiatives/context-store-and-initiatives/work-items/**/*.md`
- `openspec/changes/workspace-reimplementation-roadmap/START_HERE.md`
- `openspec/changes/workspace-reimplementation-roadmap/HISTORICAL_DIRECTION.md`
- `openspec/changes/workspace-reimplementation-roadmap/*`
- active `openspec/changes/workspace-*` proposals
- `docs/cli.md`
## Files To Leave Alone For Now
- `openspec/specs/**/*.md`
- `schemas/workspace-planning/**`
Those files should change only when we intentionally change behavior or create a
repo-owned implementation change that updates the relevant behavioral contract.
## Non-Goals
- Do not remove current workspace-planning runtime behavior.
- Do not delete the `workspace-planning` schema.
- Do not add CLI deprecation warnings until the initiative replacement exists.
- Do not implement context stores in this work item.
- Do not edit OpenSpec specs as part of the initial direction lock.
## Done When
- Initiative artifacts clearly carry the product intent and roadmap decisions.
- Historical workspace roadmap artifacts no longer read as the active shipping
queue.
- User-facing docs describe current workspaces as local views where that does
not contradict current behavior.
- Existing workspace-planning behavior is clearly treated as current behavior,
not the future product model, in initiative and roadmap artifacts.
- Workspace apply, verify, and archive are clearly deferred.
- Fresh agents can identify the initiative direction as the source of truth.
@@ -0,0 +1,44 @@
# Work Item 01 Tasks
## Tracking Setup
- [x] Create initiative-level `tasks.md`, `decisions.md`, and `questions.md`.
- [x] Create `work-items/01-lock-the-direction/`.
- [x] Record why roadmap implementation is tracked inside the initiative instead
of creating a new OpenSpec change.
## Direction Lock Already Captured
- [x] Add locked disposition to `roadmap.md`.
- [x] Add locked product boundary to `direction.md`.
- [x] Mark `openspec/changes/workspace-reimplementation-roadmap/START_HERE.md` as historical reference.
- [x] Mark `openspec/changes/workspace-reimplementation-roadmap/HISTORICAL_DIRECTION.md` as historical reference.
- [x] Mark `workspace-reimplementation-roadmap` as historical reference.
- [x] Mark `workspace-apply-repo-slice` as deferred.
- [x] Mark `workspace-verify-and-archive` as deferred.
## Non-Spec Direction Pass
- [x] Keep OpenSpec specs unchanged until behavior changes.
- [x] Review initiative artifacts for a clear source-of-intent story.
- [x] Review historical workspace roadmap artifacts for any remaining language
that tells agents to continue the old shipping queue.
- [x] Review active workspace proposal artifacts for any remaining language that
presents workspace apply, verify, or archive as next.
- [x] Decide whether user-facing docs need changes now; default to no unless
they misrepresent current behavior.
- [x] Record a decision that specs remain current behavioral contracts, while
initiative docs carry future product intent.
## Active Change Disposition
- [x] Decide whether `workspace-agent-guidance` should be reframed, closed, or
kept as a local-view guidance item.
- [x] Decide whether no-task deferred workspace changes should stay active,
move to archive, or be represented only by initiative work items.
## Verification
- [x] Run `git diff --check`.
- [x] Confirm no OpenSpec specs were modified in this pass.
- [x] Record evidence in `evidence.md`.
@@ -0,0 +1,68 @@
# Stabilize Workspace As Local View Evidence
## Direction Evidence
`direction.md` says the durable shared object is a synced context store, with
initiatives as the first major collection. It defines workspaces as local
working views over context stores and repos, and repo changes as repo/team-owned
implementation plans.
The locked product boundary supersedes the older model where a workspace-level
`changes/` tree owned the canonical shared cross-repo plan. Existing
workspace-planning behavior can remain as beta or legacy infrastructure, but it
should not steer new lifecycle design.
## Subagent Research
Implementation research found that workspace setup, link, relink, list, open,
update, and doctor already mostly behave like local-view infrastructure:
- shared link names live in workspace state
- machine-local paths and opener/skill state live in local state
- `workspace open` launches linked folders as a local working set
- linked repos are treated as context for workspace-planning commands
- `workspace update` refreshes workspace-local skills and leaves linked repos
untouched
Guidance research found that the generated `AGENTS.md` block is the most
important mismatch because it still frames the workspace as planning across
linked repos and says to use `changes/` for workspace-level planning.
Test research found strong current coverage for setup/list/doctor, link/relink,
open, update, artifact placement, and workspace-planning guards. The targeted
workspace/artifact test slice passed, as did the skill-template parity test.
## Main Risk
If generated workspace guidance continues to recommend workspace-level
`changes/`, agents may treat the workspace as the durable shared planning
object even though the initiative direction assigns durable coordination to
initiatives and implementation planning to repo-local changes.
## Implementation Evidence
The first implementation slice updates the generated workspace `AGENTS.md`
guidance and makes `workspace update` refresh the workspace-local open surface.
It also updates workspace-planning action context so beta workspace artifacts are
reported as `workspace-local` compatibility context instead of the source of
truth.
Doctor/status review found that local path mappings, unresolved links, repair
steps, malformed local state, missing local state, repo specs paths, and skill
drift warnings are already covered. Normal installed-skill summaries are
deferred for now; the current slice only updates stale `workspace update`
wording so it matches the guidance refresh behavior.
Verification:
- `pnpm run build`
- `pnpm exec vitest run test/commands/workspace.test.ts test/commands/artifact-workflow.test.ts test/core/workspace/foundation.test.ts`
- `pnpm run lint`
- `git diff --check`
## Closeout Evidence
Live docs no longer describe workspaces as durable planning homes or as the
canonical place for cross-repo planning. Historical and deferred workspace
artifacts remain as reference material, with active deferred proposals labeled
so they do not steer the next implementation slice.
@@ -0,0 +1,80 @@
# Stabilize Workspace As Local View
## Status
Complete for the current local-view stabilization slice. Remaining workspace
planning/apply/verify/archive behavior stays deferred until initiative-linked
repo-local changes exist.
## Source Of Truth
Start from `../direction.md`.
The relevant model is:
```text
Context stores sync truth.
Collections shape truth.
Initiatives coordinate work.
Workspaces open local views.
Changes implement repo-owned slices.
```
## Goal
Keep workspace setup, link, relink, list, open, update, and doctor useful while
making it clear that a workspace is a regenerable machine-local view, not the
durable coordination object.
## Agreed Guidance Direction
Generated workspace guidance should route agents by ownership:
- Use the workspace to open the local view of coordinated work.
- Use initiatives for durable cross-team or cross-repo intent, decisions,
requirements, and coordination context.
- Use repo-local OpenSpec changes for implementation plans owned by a repo or
team.
- Use linked repos and folders to inspect context, understand ownership, and
make edits in the place that owns the work.
- Keep workspace-local files focused on local paths, opener state, agent setup,
and other machine-specific view state.
- Use OpenSpec workspace commands instead of hand-editing
`.openspec-workspace/*.yaml`.
- If a workspace contains legacy or beta workspace-level planning files, treat
them as compatibility context unless the user explicitly asks to use that beta
flow.
## Guidance To Stop Reinforcing
Do not tell agents to use workspace-level `changes/` as the planning home for
coordinated work. That reinforces the superseded model where a workspace-level
`changes/` tree owned the canonical shared cross-repo plan.
Existing workspace-planning behavior may remain as beta or legacy
infrastructure, but it should not steer new lifecycle design.
## Likely Repo Slice
- Reword generated workspace guidance in
`src/core/workspace/open-surface.ts`.
- Update focused guidance tests.
- Make `workspace update` refresh the guidance block for existing workspaces.
- Keep specs untouched until a behavior change intentionally updates them.
## Closeout
Implemented:
- generated workspace guidance now routes work by ownership
- `workspace update` refreshes workspace-local guidance/open-surface files and
managed agent skills
- workspace-planning action context treats beta workspace artifacts as
`workspace-local` compatibility context
- live docs describe workspaces as local views instead of durable planning homes
Deferred:
- normal doctor installed-skill inventory
- workspace apply, verify, and archive
- initiative-linked repo-local change orchestration
@@ -0,0 +1,23 @@
# Stabilize Workspace As Local View Tasks
- [x] Research current workspace runtime, guidance, and test coverage.
- [x] Re-anchor guidance direction in `direction.md`.
- [x] Decide that generated guidance should route durable coordination to
initiatives and implementation planning to repo-local changes.
- [x] Decide that generated guidance should stop recommending workspace-level
`changes/` as the planning home.
- [x] Decide that `workspace update` refreshes the generated guidance block
for existing workspaces.
- [x] Update workspace-planning action context so beta workspace artifacts are
compatibility context, not the source of truth.
- [x] Decide to defer normal doctor skill summaries until users need an
installed-skill inventory.
- [x] Update `workspace update` wording to include workspace-local guidance and
agent skills.
- [x] Define the minimal doctor/status improvement for local paths, unresolved
links, and installed agent skills.
- [x] Identify the focused code/test files for the implementation slice.
- [x] Run the targeted workspace and artifact workflow test slice before
landing implementation.
- [x] Close out live docs wording that still framed workspaces as durable
planning homes.
@@ -0,0 +1,43 @@
# Add Context Store Foundation Evidence
## Research Summary
Existing OpenSpec patterns point toward a small explicit foundation:
- Global data uses XDG/platform locations from `getGlobalDataDir()`.
- Workspace registries are machine-local convenience indexes under global data.
- Workspace portable state uses versioned YAML and strict Zod validation.
- Existing read/write helpers validate state before writing and use
`FileSystemUtils.writeFile()` to create parent directories.
- Schema/backend-style code favors small explicit adapters and registries over
heavy framework abstractions.
## Decisions
- The first context-store backend is Git/local checkout config only.
- OpenSpec records where the local checkout lives; it does not decide where real
team stores are cloned by default.
- The local registry is not source of truth. It is a machine-local index.
- Store-root metadata is portable source-of-identity for the synced store.
- Initiatives and collections are later consumers, not part of the store
foundation.
- A thin facade should hide raw registry/metadata writes before initiative CLI
wiring.
## Implementation Evidence
- `src/core/context-store/registry.ts` registers Git/local context stores,
lists local registry entries, and resolves registered stores with metadata id
validation.
- `src/core/context-store/index.ts` exports the facade.
- `test/core/context-store/registry.test.ts` covers registration, registry
merge/update, metadata mismatch rejection, listing, resolution, missing or
mismatched metadata, and initiative collection mounting from a resolved root.
## Verification
- `pnpm exec vitest run test/core/context-store/foundation.test.ts`
- `pnpm exec vitest run test/core/context-store/registry.test.ts`
- `pnpm run build`
- `pnpm run lint`
- `git diff --check`
@@ -0,0 +1,85 @@
# Add Context Store Foundation
## Status
Registration/resolution facade implemented.
## Source Of Truth
Start from `../direction.md`.
The relevant model is:
```text
Context stores sync truth.
Collections shape truth.
Initiatives coordinate work.
Workspaces open local views.
Changes implement repo-owned slices.
```
## Goal
Add the smallest core foundation for context stores without making the store
layer know about initiatives, collections, workspaces, or repo-local changes.
## Locked Direction
- Support one backend for the first slice: a Git/local checkout backend.
- Treat the actual context store root as a user-chosen local Git checkout or
synced folder.
- Do not hide real team context stores under XDG data by default.
- Store the machine-local registry under global data:
`$XDG_DATA_HOME/openspec/context-stores/registry.yaml`.
- Store portable context-store identity inside the store root:
`<store-root>/.openspec-store/store.yaml`.
- Start with backend identity/config, strict validation, path helpers, and
registry/metadata read-write helpers.
- Add a thin registration/resolution facade before initiative CLI wiring so
callers do not manipulate raw registry and metadata YAML directly.
- Do not reimplement the TypeScript or Node filesystem APIs as the public store
interface.
- Do not add initiative, collection, workspace-open, sync, pull, push, or CLI
behavior in this slice.
## Initial Shape
Machine-local registry:
```yaml
version: 1
stores:
acme-context:
backend:
type: git
local_path: /Users/me/repos/acme-context
remote: git@github.com:acme/context.git
branch: main
```
Portable metadata in the store root:
```yaml
version: 1
id: acme-context
```
## Likely Repo Slice
- Add `src/core/context-store/foundation.ts`.
- Add `src/core/context-store/registry.ts`.
- Add `src/core/context-store/index.ts`.
- Export the core context-store foundation from `src/core/index.ts`.
- Add focused tests under `test/core/context-store/`.
- Keep specs untouched until a behavior/API contract is deliberately surfaced.
## Implemented Facade Slice
- Added `registerContextStore(...)`.
- Added `listRegisteredContextStores(...)`.
- Added `resolveRegisteredContextStore(...)`.
- Registration writes portable store metadata when missing, validates existing
metadata when present, and merges/updates the machine-local registry.
- Resolution validates that the registry id matches the store-root metadata id.
- No Git clone, pull, push, sync, workspace state, collection manifest, or CLI
behavior was added.
@@ -0,0 +1,17 @@
# Add Context Store Foundation Tasks
- [x] Research existing config, registry, file-system, and schema/backend
patterns.
- [x] Decide to start with Git/local backend identity only, not a generic file
API.
- [x] Decide that real context store roots are user-chosen Git checkouts or
synced folders.
- [x] Decide that the local registry lives under global data and portable store
metadata lives inside the store root.
- [x] Add context-store foundation types, path helpers, parse/serialize, and
read/write helpers.
- [x] Add focused tests for validation, paths, registry roundtrip, metadata
roundtrip, and Git/local backend path resolution.
- [x] Run targeted verification.
- [x] Decide registration/resolution facade should precede initiative CLI.
- [x] Add context-store registration/list/resolve facade and tests.
@@ -0,0 +1,77 @@
# Add Collection Foundation Evidence
## Research Summary
Subagent and local review converged on the same direction:
- Item 4 should define the boundary between store identity and product-specific
content meaning.
- The collection layer should own mounted namespaces and logical path fences.
- The context-store layer should stay content-agnostic.
- Initiative CRUD and initiative file shape belong to Item 5.
- A runtime injected registry is enough for now; persisted manifests and dynamic
plugins are premature.
- A thin registration facade should hide metadata and local registry writes, but
Item 4 should not depend on that facade.
## Clean-Code Notes
- Use module boundaries and mounted objects to carry context.
- Prefer `validateMount`, `parseCollectionPath`, `createCollectionRegistry`,
and `mountCollections` inside the collection module.
- Avoid public helper names that stack every concept together, such as
`validateContextStoreCollectionRelativePath`.
- Keep path resolution pure and lexical until a future write-capable layer
deliberately handles symlinks, canonical parent paths, and backend behavior.
- Keep persisted YAML shape below the public setup surface. Runtime/public
handles should use camelCase fields such as `storeRoot`; persisted backend
state can continue to use `local_path`.
## Chosen Pattern
Use a two-step pattern:
```ts
const store = await registerContextStore({
id: "acme-context",
backend: gitLocalBackend({
localPath: "/Users/me/repos/acme-context",
remote: "git@github.com:acme/context.git",
branch: "main",
}),
});
const collections = createCollectionRegistry([
{ id: "initiatives", mount: "initiatives" },
]);
const mounted = mountCollections({
storeRoot: store.storeRoot,
collections,
});
```
For Item 4 itself, `mountCollections({ storeRoot, collections })` is the
canonical API. One-call setup facades, store lifecycle objects, builder DSLs,
and initiative-specific setup presets are deferred.
## Implementation Evidence
- `src/core/collections/runtime.ts` defines runtime collection
definitions, registries, mounted collection contexts, logical path parsing,
and mount/path resolution.
- `src/core/collections/index.ts` exports the collection module, and
`src/core/index.ts` re-exports it for core consumers.
- `test/core/collections/runtime.test.ts` covers mount and id validation,
logical path parsing, duplicate id/mount rejection, Windows-style roots,
`createHandle(context)`, no filesystem creation, and generic `initiatives/`
mounting.
## Verification
- `pnpm exec vitest run test/core/collections/runtime.test.ts`
- `pnpm run build`
- `pnpm exec vitest run test/core/collections/runtime.test.ts test/core/context-store/foundation.test.ts test/core/planning-home.test.ts`
- `pnpm exec vitest run test/utils/file-system.test.ts`
- `pnpm run lint`
- `git diff --check`
@@ -0,0 +1,198 @@
# Add Collection Foundation
## Status
First implementation slice implemented.
## Source Of Truth
Start from `../../direction.md`.
The relevant model is:
```text
Context stores sync truth.
Collections shape truth.
Initiatives coordinate work.
Workspaces open local views.
Changes implement repo-owned slices.
```
## Goal
Add the smallest collection foundation that lets product-specific content
systems mount inside a context store without making the context-store layer know
what those systems mean.
## Locked Direction So Far
- Treat Item 4 as a mount/path foundation, not a collection runtime.
- Keep collection composition runtime-only and dependency-injected.
- Keep context-store registration separate from runtime collection mounting.
- Use a future thin registration facade for metadata/registry setup instead of
showing raw registry or metadata state writes in public examples.
- Do not add a persisted collection manifest yet.
- Do not add CLI behavior yet.
- Do not add generic `read`, `write`, `list`, or `delete` helpers.
- Do not add initiative file shape, initiative CRUD, or initiative validation
yet.
- Prove `initiatives/` can mount through generic collection definitions, not
through initiative-specific context-store logic.
## Naming Direction
Use the module/object boundary to carry context instead of growing helper names.
Use a focused generic module such as `src/core/collections/runtime.ts` with
short names:
```ts
validateCollectionId(id);
validateMount(mount);
parseCollectionPath(input);
createCollectionRegistry(...);
mountCollections(...);
```
Prefer mounted objects for context-aware operations:
```ts
const mounted = collections.require("initiatives");
mounted.resolvePath("launch-billing-flow/initiative.yaml");
mounted.toStorePath("launch-billing-flow/initiative.yaml");
```
Avoid names like `validateContextStoreCollectionRelativePath`. They indicate
that too much context has leaked into a standalone helper name.
## Minimal API Shape
The first slice should stay close to this:
```ts
interface CollectionDefinition<THandle = unknown> {
id: string;
mount: string;
metadata?: CollectionMetadata;
hooks?: CollectionHooks;
createHandle?: (context: MountedCollectionContext) => THandle;
}
interface MountedCollectionContext {
storeRoot: string;
collectionId: string;
mount: string;
mountRoot: string;
resolvePath(relativePath?: string): string;
toStorePath(relativePath?: string): string;
}
interface MountedCollection<THandle = unknown> {
collectionId: string;
mount: string;
mountRoot: string;
context: MountedCollectionContext;
handle: THandle | undefined;
}
```
Use `id` on definitions, but `collectionId` on mounted handles and contexts so
domain object IDs such as initiative IDs do not collide with collection type IDs.
## Setup And Mounting Pattern
Use two separate layers:
1. A context-store registration facade for setup.
2. A pure runtime collection mounting API for Item 4.
Registration should hide persisted YAML details:
```ts
const store = await registerContextStore({
id: "acme-context",
backend: gitLocalBackend({
localPath: "/Users/me/repos/acme-context",
remote: "git@github.com:acme/context.git",
branch: "main",
}),
});
```
The registration facade can call lower-level helpers such as backend config
normalization, metadata writes, and local registry writes internally. Public
examples should not call raw `writeContextStoreMetadataState(...)`,
`writeContextStoreRegistryState(...)`, or expose persisted snake_case backend
state such as `local_path`.
Item 4 mounting should stay independent of registration and accept only the
authority it needs:
```ts
const collections = createCollectionRegistry([
{ id: "initiatives", mount: "initiatives" },
]);
const mounted = mountCollections({
storeRoot: store.storeRoot,
collections,
});
mounted.require("initiatives").resolvePath(
"launch-billing-flow/initiative.yaml"
);
```
Prefer `mountCollections({ storeRoot, collections })` as the canonical first
API. Passing a whole store handle can wait until there is a real need.
## Path Direction
- Mount names are single-segment kebab-case folder names such as `initiatives`,
`decisions`, or `api-catalog`.
- Collection-relative paths are logical portable paths inside a mount.
- The path resolver is lexical only. It proves that a logical path belongs under
a collection mount; it does not claim to be a filesystem security sandbox.
- Future write-capable helpers must revisit symlink and canonical parent-path
handling before touching disk.
Reject:
- empty mounts
- `.`
- `..`
- hidden/reserved mounts such as `.openspec-store`
- absolute paths
- Windows drive paths
- UNC paths
- NUL bytes
- traversal segments
- sibling-prefix escapes
## Deferred
- Store-level collection config files.
- Dynamic plugin loading.
- One-call `setupContextStore({ id, backend, collections })` APIs.
- `createStore(...).setup()` lifecycle APIs.
- Builder-style setup DSLs.
- Initiative-specific setup presets in the generic context-store layer.
- Template override search paths.
- Rich validation execution.
- Agent guidance generation.
- Workspace integration.
- Git sync, commits, pull, push, watch, or conflict behavior.
## Implemented Slice
- Added a pure runtime collection module at
`src/core/collections/runtime.ts`.
- Exported the module through `src/core/collections/index.ts` and
`src/core/index.ts`.
- Added focused tests under `test/core/collections/runtime.test.ts`.
- Proved a generic `{ id: "initiatives", mount: "initiatives" }` definition can
mount and resolve paths without initiative-specific store logic.
- Kept validation/template hooks as inert extension fields for now; rich hook
execution remains deferred.
@@ -0,0 +1,14 @@
# Add Collection Foundation Tasks
- [x] Research what Item 4 needs to decide.
- [x] Compare collection model options.
- [x] Run clean-code and design-pattern review.
- [x] Decide to keep Item 4 as a runtime mount/path foundation.
- [x] Decide to avoid long context-stacked helper names.
- [x] Decide to separate context-store registration from runtime collection
mounting.
- [x] Define exact collection mount and path rules.
- [x] Define the minimal runtime registry and mounted collection API.
- [x] Implement collection foundation helpers and tests.
- [x] Prove `initiatives/` can mount without store-specific initiative logic.
- [x] Run targeted verification.
@@ -0,0 +1,99 @@
# Ship Initiative MVP Evidence
## Research Summary
- Initiative code should live in `src/core/collections/initiatives/`, outside
`src/core/context-store/`.
- Initiative APIs should consume a mounted `initiatives` collection from Item 4
rather than raw context-store roots.
- The first coding slice should lock metadata and templates before mounted
create/list operations.
- Visible `initiative.yaml` is preferred for the new shared initiative model.
- `links.yaml` should not exist in the initiative MVP. Repo-change wiring is a
workspace/local coordination concern to revisit later.
- Read/show, update, and delete have extra policy risk, so create/list should
come before broader lifecycle behavior.
- The first mounted operation slice should do create/list only. A full
`readInitiative` API is deferred until the return shape is clearer.
## Decisions
- Use `src/core/collections/initiatives/` for initiative-domain code.
- Do not put initiative semantics into `src/core/context-store/`.
- Add `initiative.yaml` strict parse/serialize helpers.
- Generate Markdown files up front, but do not validate Markdown content beyond
existence/templates in the first pass.
- Defer workspace opening, repo resolution, status dashboards, sync, linked
change lifecycle, `links.yaml`, `contracts/`, and CLI behavior.
- Detect initiatives by valid `initiative.yaml`: missing means ignore, invalid
means fail loudly, and the YAML `id` must match the folder name.
## Suggested First Coding Slice
Add:
- `src/core/collections/initiatives/schema.ts`
- `src/core/collections/initiatives/templates.ts`
- `src/core/collections/initiatives/operations.ts`
- `src/core/collections/initiatives/index.ts`
- focused tests under `test/core/collections/initiatives/`
Cover:
- constants for initiative file names
- `validateInitiativeId`
- strict `initiative.yaml` parse/serialize
- create/list operations through a mounted `initiatives` collection
- template builders for `requirements.md`, `design.md`, `decisions.md`,
`questions.md`, and `tasks.md`
- tests for valid and invalid metadata, invalid IDs, unknown YAML fields,
required `created`, and generated template names/content shape
## Implementation Evidence
- `src/core/collections/initiatives/schema.ts` defines initiative constants,
strict persisted `initiative.yaml` parsing/serialization, required
`created`, bounded JSON-like metadata, statuses, and portable kebab-case
initiative IDs.
- `src/core/collections/initiatives/templates.ts` defines deterministic default
Markdown file builders for requirements, design, decisions, questions, and
tasks.
- `src/core/collections/initiatives/index.ts` exports the initiative
schema/template surface inside the initiative module only.
- `src/core/collections/initiatives/operations.ts` creates MVP initiative
folders and lists initiative states using the valid-`initiative.yaml`
detection rule.
- `src/core/collections/index.ts` exports the initiative module now that it has
a mounted operation API.
- `test/core/collections/initiatives/schema.test.ts` covers file constants,
no `links.yaml`, ID validation, strict YAML behavior, required `created`,
default owners/metadata, metadata validation, and serialization round trips.
- `test/core/collections/initiatives/templates.test.ts` covers generated
Markdown file names, deterministic ordering, trailing newlines, and expected
section headings.
- `test/core/collections/initiatives/operations.test.ts` covers create, list,
duplicate protection, cleanup on partial write failure, missing
`initiative.yaml` ignored, invalid `initiative.yaml` failure, and folder/id
mismatch failure.
- `src/core/context-store/registry.ts` was added as the next integration
enabler before CLI wiring.
- `src/commands/initiative.ts` adds `openspec initiative create/list` as a thin
CLI adapter over the context-store facade and mounted initiatives collection.
- `src/cli/index.ts` registers the initiative command.
- `src/core/completions/command-registry.ts` registers static completion
metadata for `initiative create/list/ls`.
- `test/commands/initiative.test.ts` covers JSON create, `--store-path` list,
human output, selector errors, duplicate create errors, and completion
registry entries.
## Verification
- `pnpm exec vitest run test/core/collections/initiatives/schema.test.ts test/core/collections/initiatives/templates.test.ts`
- `pnpm exec vitest run test/core/collections/initiatives/operations.test.ts`
- `pnpm exec vitest run test/core/collections/initiatives/schema.test.ts test/core/collections/initiatives/templates.test.ts test/core/collections/initiatives/operations.test.ts test/core/collections/runtime.test.ts test/core/context-store/foundation.test.ts test/core/planning-home.test.ts`
- `pnpm exec vitest run test/commands/initiative.test.ts`
- `pnpm exec vitest run test/core/context-store/registry.test.ts test/core/collections/initiatives/operations.test.ts test/core/collections/initiatives/schema.test.ts test/core/collections/initiatives/templates.test.ts test/core/collections/runtime.test.ts`
- `pnpm exec vitest run test/commands/workspace.test.ts`
- `pnpm run build`
- `pnpm run lint`
- `git diff --check`
@@ -0,0 +1,236 @@
# Ship Initiative MVP
## Status
Create/list operation and CLI adapter slices complete. Full read/show, update,
and delete policy is deferred to later agent-first discovery and lifecycle
work.
## Source Of Truth
Start from `../../direction.md`.
The relevant model is:
```text
Context stores sync truth.
Collections shape truth.
Initiatives coordinate work.
Workspaces open local views.
Changes implement repo-owned slices.
```
## Goal
Give coordinated work a durable, shared, agent-consumable home inside an
`initiatives/` collection.
## Roadmap Shape
Default initiative shape:
```text
initiatives/<id>/
initiative.yaml
requirements.md
design.md
decisions.md
questions.md
tasks.md
```
Direction also leaves room for later `contracts/` content:
```text
initiatives/<id>/
contracts/
```
## Initial Boundaries
- Initiative code should live outside `src/core/context-store/`.
- Context-store core should not know initiative semantics.
- Initiative APIs should consume a mounted `initiatives` collection from Item 4.
- Repo-local OpenSpec changes remain the implementation artifacts; initiatives
coordinate intent, decisions, questions, and tasks.
- Do not implement workspace opening, repo resolution, status dashboards, sync,
or linked change lifecycle in this item.
## Locked Direction So Far
- Put initiative code under `src/core/collections/initiatives/`.
- Export initiatives from `src/core/index.ts` only after a real API exists.
- Use visible `initiative.yaml`, not hidden `.initiative.yaml`, for the runtime
context-store initiative model. Existing roadmap folders may still carry
legacy `.initiative.yaml` progress metadata until that tracker is migrated or
retired.
- Use strict YAML parsing and validation, following the existing foundation
patterns.
- Do not create `links.yaml` in the initiative MVP. Repo-change wiring belongs
to workspace/local coordination work later.
- Keep Markdown validation light; generate useful structure but do not validate
prose content yet.
- Start implementation with initiative schema and template helpers before
mounted collection operations.
- For the first mounted operation slice, add create and list only. Avoid a
broad `readInitiative` API until the shape of "full initiative" is clearer.
- Treat a child folder as an initiative only when it contains a valid
`initiative.yaml`. Missing `initiative.yaml` means "not an initiative";
invalid `initiative.yaml` means broken shared state and should fail loudly.
## Deferred From Item 5
- Full initiative show/read behavior belongs in agent-first initiative discovery
once the return shape is clearer.
- Metadata update and guarded delete belong in later lifecycle work after
create/list usage has shaped the policy.
## Initial `initiative.yaml`
Recommended shape:
```yaml
version: 1
id: launch-billing-flow
title: Launch Billing Flow
summary: >
Coordinate the billing launch across product, API, and client surfaces.
status: exploring
created: "2026-05-21"
owners: []
metadata: {}
```
Required:
- `version`
- `id`
- `title`
- `summary`
- `status`
- `created`
Defaulted or optional:
- `owners`
- `metadata`
Initial statuses:
- `exploring`
- `active`
- `complete`
- `archived`
## Initial Markdown Templates
Create these files up front:
- `requirements.md`: product intent, accepted requirements, out of scope.
- `design.md`: context, approach, affected areas, dependencies, risks.
- `decisions.md`: accepted decisions with date/title/decision/why/implications.
- `questions.md`: open and resolved questions.
- `tasks.md`: coordination tasks only, not repo implementation tasks.
Defer `contracts/`, `README.md`, milestones, dependency graphs, external issue
links, workspace path mappings, status dashboards, `links.yaml`, and Markdown
content validation.
## Likely Repo Slice
- Add `src/core/collections/initiatives/schema.ts`.
- Add `src/core/collections/initiatives/templates.ts`.
- Add `src/core/collections/initiatives/index.ts`.
- Add focused tests under `test/core/collections/initiatives/`.
- Add types, constants, ID validation, strict `initiative.yaml`
parse/serialize helpers, and default template builders.
- Add create/list mounted collection operations after schema and templates are
locked.
- Keep context-store collection APIs unchanged unless a real integration gap is
found.
## Implemented Slice
- Added `src/core/collections/initiatives/schema.ts`.
- Added `src/core/collections/initiatives/templates.ts`.
- Added `src/core/collections/initiatives/index.ts`.
- Added focused tests under `test/core/collections/initiatives/`.
- Exported initiatives through `src/core/collections/index.ts` now that a
mounted operation API exists.
- Kept `links.yaml` out of the initiative MVP file contract.
## Operation Slice Direction
- Add `src/core/collections/initiatives/operations.ts`.
- Export initiatives through `src/core/collections/index.ts` now that a mounted
operation API exists.
- `createInitiative` should create exactly the MVP file shape:
`initiative.yaml`, `requirements.md`, `design.md`, `decisions.md`,
`questions.md`, and `tasks.md`.
- `createInitiative` should generate `created` through an injectable date
provider, fail if the initiative folder already exists, and clean up a
partially created folder on write failure.
- `listInitiatives` should inspect immediate child directories under the
mounted `initiatives` collection, ignore folders without `initiative.yaml`,
parse and validate folders with `initiative.yaml`, require
`initiative.yaml.id` to match the folder name, and return initiative states
sorted by id.
## Implemented Operation Slice
- Added `src/core/collections/initiatives/operations.ts`.
- Added `createInitiative` for creating the MVP folder shape through a mounted
`initiatives` collection.
- Added `listInitiatives` using the valid-`initiative.yaml` detection rule.
- Exported initiatives through `src/core/collections/index.ts`.
- Added focused operation tests under
`test/core/collections/initiatives/operations.test.ts`.
## Next Integration Enabler
Before adding `openspec initiative create/list`, add a context-store
registration/resolution facade so CLI code can resolve a named store and mount
the initiatives collection without exposing raw registry or metadata YAML.
## CLI Adapter Direction
Add the first initiative CLI surface as a thin adapter over the mounted
collection operations:
```bash
openspec initiative create <id> --store <store-id> --title <title> --summary <summary>
openspec initiative create <id> --store-path <path> --title <title> --summary <summary>
openspec initiative list --store <store-id>
openspec initiative list --store-path <path>
```
Use `initiative create/list` as a deliberate noun namespace, similar to
`workspace` and `schema`, even though newer OpenSpec conventions generally
prefer verb-first top-level commands. The stricter alternative would spread
initiative behavior across `new initiative` and global `list` flags, which is a
larger surface for this slice because initiative commands must resolve a
context store.
Keep store selection explicit in the first CLI slice. Require either
`--store <id>` or `--store-path <path>`, reject both together, and do not add
current-directory discovery, single-store auto-selection, an interactive picker,
a global default store, or workspace selected-store state yet.
Because shell completions are manually registered, adding the runtime command
also requires adding `initiative create/list/ls` to `COMMAND_REGISTRY`. Keep
completion support static for now: command names and flags only, with no dynamic
store-id or initiative-id completion.
## Implemented CLI Adapter Slice
- Added `src/commands/initiative.ts`.
- Registered `openspec initiative create` and `openspec initiative list` from
the top-level CLI.
- Added `openspec initiative ls` as an alias for list.
- Required explicit context-store selection through `--store <id>` or
`--store-path <path>`.
- Rejected conflicting `--store` and `--store-path` selectors.
- Returned workspace-style JSON payloads with a top-level `status` diagnostics
array.
- Added static shell completion metadata for `initiative create/list/ls`.
- Added focused command tests under `test/commands/initiative.test.ts`.
@@ -0,0 +1,21 @@
# Ship Initiative MVP Tasks
- [x] Create Item 5 work-item tracking notes.
- [x] Research initiative shape, API, module placement, and first slice.
- [x] Decide where initiative code lives.
- [x] Decide required `initiative.yaml` metadata.
- [x] Decide no initiative `links.yaml` in the MVP.
- [x] Decide first coding slice starts with initiative schema/templates before operations.
- [x] Add initiative schema helpers and tests.
- [x] Add default initiative templates.
- [x] Run targeted verification for schema/templates.
- [x] Decide create/list-only operation slice.
- [x] Add create/list mounted initiative operations and tests.
- [x] Run targeted verification for operations.
- [x] Research initiative CLI adapter gaps.
- [x] Decide explicit context-store selection for first CLI slice.
- [x] Document noun-command and manual-completion tradeoffs.
- [x] Add `openspec initiative create/list` CLI adapter.
- [x] Register static shell completions for initiative commands.
- [x] Add focused CLI tests for create/list, selection errors, and completions.
- [x] Run targeted verification for the initiative CLI adapter.
@@ -0,0 +1,97 @@
# Add Minimal Context Store UX Evidence
## Conversation Decisions
- The next roadmap step should not jump straight to repo-local change linking
or workspace initiative opening.
- Teams first need a simple way to create or register the shared context store
that holds initiatives.
- The workflow is agent-first: the user prompts an agent, and the agent uses CLI
primitives to discover stores and initiatives.
- `context-store` should be the top-level command namespace for now. It is more
explicit for agents than `store`, and `store` can remain shorthand in scoped
flags such as `initiative list --store <id>`.
- A store can start as a local Git-backed folder. OpenSpec can help create the
folder, write metadata, register it locally, and optionally initialize Git.
- When setup does not receive `--path`, it should create or use `./<id>`. This
keeps the real shared store visible and avoids hiding it under global data.
- Using the current directory should require explicit `--path .`.
- If a user registers an existing folder or clone, the default store id can be
the repo or folder name.
- Portable `.openspec-store/store.yaml` metadata should be checked in and should
not include local paths.
- `.openspec-store/store.yaml` is the identity file itself, not a bundle beside
another checked-in metadata file. It should contain only `version` and `id`
for now.
- Future backend, sync, collection, permission, or policy config should not be
added to `store.yaml` by default.
- The local registry maps store ids to local paths on one machine.
- Remote-url clone/setup sugar is useful but can wait.
- `initiative list` should list all registered stores by default; `--store`
should filter.
- Interactive setup should prompt for Git initialization and default to yes
when no explicit Git flag is provided.
- Non-interactive, JSON, `--init-git`, and `--no-init-git` setup should not
prompt.
- `context-store register` should be idempotent for the same id/path and fail
for the same id with a different path until a future explicit replacement
option exists.
- `context-store list` should stay a simple registry index and should not show
health warnings.
- `context-store doctor` owns health diagnostics. The first slice should check
registry/path/metadata and cheap Git repository presence, not dirty state,
branch, remote, sync, pull/push, or conflicts.
- `initiative list` should allow partial success in all-store mode: show
initiatives from readable stores and print one small warning pointing to
`context-store doctor` when other registered stores cannot be read.
- Filtered `initiative list --store` and explicit `--store-path` should fail
directly when the selected store cannot be read.
- Partial success should exit 0 with warning diagnostics in JSON. Total failure
should exit nonzero.
- Register id inference should use the repo/folder name as-is with normal
context-store id validation. Do not add normalization in this slice.
- Setup should reject non-empty folders without context-store metadata for now.
- Registry conflicts should fail when the same id points at a different path or
the same path is already registered under a different id.
- Empty states should stay simple: no stores registered for `context-store list`
and `doctor`; no initiatives found because no stores are registered for
`initiative list`.
- Static shell completion metadata is now part of the shipped command surface;
dynamic store-id and initiative-id completions remain deferred.
## Risks To Check Before Implementation
- Existing command naming conventions may prefer verb-first flows, while
context-store commands are naturally noun namespaced.
- Shell completions are manually registered; keep future command additions in
`src/core/completions/command-registry.ts` with focused registry tests.
- Human output should match existing compact CLI output patterns.
- JSON output should be stable enough for agents without over-modeling future
sync or remote behavior.
## Implementation Evidence
- `src/commands/context-store.ts` adds the `context-store` command namespace
with setup, register, list, and doctor subcommands.
- `src/cli/index.ts` registers the context-store command.
- `src/commands/context-store.ts` keeps strict CLI setup/register policy in the
command layer while reusing context-store foundation helpers.
- `src/commands/initiative.ts` now lets `initiative list` search all registered
stores by default, keeps `--store` as a filter, preserves `--store-path`, and
reports all-store partial success with warning diagnostics.
- `src/core/completions/command-registry.ts` registers static completion
metadata for the context-store command surface.
- `test/commands/context-store.test.ts` covers setup, register, list, doctor,
conflict handling, non-empty setup rejection, and interactive Git init.
- `test/commands/initiative.test.ts` covers all-store initiative listing,
compact human output, empty registered-store state, partial success, and all
unreadable stores.
## Verification
- `pnpm run build`
- `pnpm exec vitest run test/commands/context-store.test.ts test/commands/initiative.test.ts`
- `pnpm exec vitest run test/core/context-store/foundation.test.ts
test/core/context-store/registry.test.ts
test/core/collections/initiatives/operations.test.ts`
- `pnpm run lint`
@@ -0,0 +1,333 @@
# Add Minimal Context Store UX
## Status
Minimal context-store CLI and all-store initiative listing implemented.
## Source Of Truth
Start from `../../direction.md`.
The current roadmap order is:
```text
Context stores sync truth.
Collections shape truth.
Initiatives coordinate work.
Workspaces open local views.
Changes implement repo-owned slices.
```
This item exists because agent-first initiative workflows need a usable shared
store before repo-local handoff and workspace opening can feel coherent.
## Goal
Let a user or agent create, register, list, and diagnose local context stores
without knowing the internal registry layout.
## Agent-First Framing
The expected user prompt is closer to:
```text
Using initiative billing-launch, explore the API work and create a proposal.
```
Before an agent can do that, it needs to answer:
- Which context stores are registered locally?
- Which store contains the named initiative?
- Is the registered store path valid?
- Is store metadata present and consistent?
- If no store exists yet, how should one be created?
This work item should provide those primitives. It should not implement
repo-local initiative linking, initiative resolution, workspace opening, or
progress/status dashboards.
## Locked Direction So Far
- Keep the user-facing term `store` for now; naming polish is deferred.
- Use `context-store` as the top-level CLI namespace for this slice. It is more
explicit for agents and avoids overloading a broad top-level `store` command.
Keep `store` as shorthand only when the context is already scoped, such as
`initiative list --store <id>`.
- `context-store setup <id>` should create or use a local folder, write portable
store metadata, register the local path, and optionally initialize Git.
- When `--path` is omitted, `context-store setup <id>` should default to
`./<id>`.
- Using the current directory should be explicit with `--path .`; setup should
not silently turn the current repo into a context store.
- The actual shared context store should be visible on disk, not hidden under
XDG/global data. XDG/global data is only for the machine-local registry.
- `context-store register <path>` should register an existing clone or folder.
- Registration means "this folder already exists on my machine; remember it as
a known context store." It should not create the folder, initialize Git, pull,
push, commit, or create remotes.
- Default the store id from the repo or folder name when metadata is missing.
- Portable store metadata is exactly `.openspec-store/store.yaml`. It should be
checked into the context-store repo and contain only portable identity for
now:
```yaml
version: 1
id: team-context
```
- Do not put backend config, local paths, remote URLs, collection config, sync
policy, or permissions in `store.yaml`.
- If future collection/store config is needed, add a separate explicit file
rather than expanding the identity file by default.
- Machine-local registry state should stay outside the checked-in store and map
store ids to local paths.
- Registration should not pull, push, commit, or create remote repositories.
- Remote-url registration or clone sugar can come later.
- `initiative list` should default to all registered stores. `--store` should
filter to one store, and `--store-path` should remain an explicit escape
hatch.
- Human output should stay compact and avoid a `Status` column for now.
## Suggested Command Shape
```bash
openspec context-store setup <id> [--path <path>] [--init-git|--no-init-git] [--json]
openspec context-store register <path> [--id <id>] [--json]
openspec context-store list [--json]
openspec context-store doctor [id] [--json]
openspec initiative list [--store <id>] [--store-path <path>] [--json]
```
## Command Behavior
### `context-store setup`
`context-store setup <id>` creates or uses a visible local store root and
registers it on the current machine.
Locked behavior:
- Default path is `./<id>` when `--path` is omitted.
- Current-directory setup is allowed only with explicit `--path .`.
- Missing folders are created.
- Existing folders are allowed when metadata is missing or matches the requested
id.
- Non-empty folders without context-store metadata are not supported for setup
in this slice.
- Existing metadata with a different id fails.
- File paths fail.
- `.openspec-store/store.yaml` is written when missing.
- The store is registered in the machine-local registry.
- Interactive TTY mode prompts for Git initialization when neither
`--init-git` nor `--no-init-git` is provided; the default answer is yes.
- `--json`, non-TTY execution, `--init-git`, and `--no-init-git` do not prompt.
- Git is initialized only when the prompt answer is yes or `--init-git` is
passed.
- Setup does not commit, push, pull, create remotes, or create hosted repos.
- If a user wants to initialize an existing non-empty folder, fail with a clear
message and suggest filing the use case or using `context-store register` for
an existing context store.
Suggested human output:
```text
Context store setup complete
ID: team-context
Location: /Users/me/work/team-context
Metadata: /Users/me/work/team-context/.openspec-store/store.yaml
Registry: /Users/me/.local/share/openspec/context-stores/registry.yaml
Git: initialized
```
### `context-store register`
`context-store register <path>` records an existing local folder or clone as a
known context store on the current machine.
Locked behavior:
- Path must already exist and be a directory.
- If `.openspec-store/store.yaml` exists, use its id.
- `--id` may confirm the metadata id but cannot conflict with it.
- If metadata is missing, infer the id from the folder or repo name unless
`--id` is passed.
- Inference uses the folder or repo name as-is and then applies normal context
store id validation. Do not do clever normalization in this slice.
- Missing metadata is written.
- The machine-local registry is updated.
- Same id and same path is an idempotent success.
- Same id and different path fails for now; a future `--replace` can make
replacement explicit.
- Same path already registered under a different id fails for now.
- Register does not create the folder, initialize Git, pull, push, commit,
create remotes, or clone.
Suggested human output:
```text
Context store registered
ID: team-context
Location: /Users/me/src/team-context
Metadata: /Users/me/src/team-context/.openspec-store/store.yaml
Registry: /Users/me/.local/share/openspec/context-stores/registry.yaml
```
### `context-store list`
`context-store list` is an index view of the local registry.
Locked behavior:
- Reads the local registry.
- Shows registered id and location only.
- Sorts by store id.
- Does not check metadata, path health, Git, sync, remote, dirty state, or
conflicts.
- Does not mutate anything.
- Prints no health warnings; health belongs to `context-store doctor`.
Suggested human output:
```text
OpenSpec context stores (2)
ID Location
platform /Users/me/src/platform-context
team-context /Users/me/src/team-context
```
Empty output:
```text
No context stores registered.
Next:
openspec context-store setup team-context
openspec context-store register /path/to/context-store
```
### `context-store doctor`
`context-store doctor [id]` is the non-mutating health and repair surface.
Locked behavior:
- Checks all registered stores by default.
- Checks one store when `id` is passed.
- Checks registry presence, path existence, directory shape, metadata presence,
metadata parsing, and metadata id matching.
- Includes a cheap Git repository presence check.
- Does not check dirty state, branch, remote, sync, pull/push, or conflicts in
this slice.
- Does not mutate anything.
Empty output:
```text
No context stores registered.
```
Suggested human output:
```text
Context store doctor
team-context
Location: /Users/me/src/team-context
Metadata: ok
Git: repository detected
Issues: none
```
### `initiative list`
`initiative list` becomes the agent-friendly discovery command across
registered stores.
Locked behavior:
- Without `--store` or `--store-path`, list initiatives from all readable
registered stores.
- If no context stores are registered, print a concise empty message.
- Sort by store id, then initiative id.
- Do not show a `Status` column in human output.
- Do not print detailed health diagnostics.
- If some stores cannot be read, still show initiatives from readable stores
and print one small warning that points to `context-store doctor`.
- If all registered stores are unreadable, print a concise failure/empty message
and point to `context-store doctor`.
- With `--store <id>`, filter to one registered store.
- With `--store-path <path>`, list from that explicit store path.
- Filtered `--store` or `--store-path` mode fails directly if that store cannot
be read, because there are no fallback stores.
Suggested all-store output:
```text
OpenSpec initiatives (3 across 2 stores)
ID Store Title
billing-launch platform Billing Launch
docs-refresh platform Docs Refresh
api-cleanup team API Cleanup
Some registered context stores could not be read.
Run: openspec context-store doctor
```
No registered stores output:
```text
No initiatives found because no context stores are registered.
```
Suggested filtered output:
```text
OpenSpec initiatives in platform (2)
ID Title
billing-launch Billing Launch
docs-refresh Docs Refresh
Location: /Users/me/src/platform-context
```
## Boundaries
Do not implement in this item:
- initiative `show`
- repo-local change metadata
- `new change --initiative`
- initiative local resolution
- workspace initiative opening
- sync, pull, push, remote repository creation, or conflict handling
## Remaining Decisions
None before implementation. JSON shapes can follow the existing command pattern:
top-level result objects plus a `status` diagnostics array. Partial success
returns exit code 0 with warning diagnostics; total failure returns nonzero.
## Implemented Slice
- Added `openspec context-store setup/register/list/doctor`.
- Registered the `context-store` command from the top-level CLI.
- Initially kept shell completion metadata out of scope; static metadata was
added later with the shipped command surface.
- Implemented strict CLI registration policy without changing the permissive
lower-level registry facade.
- Added setup behavior for default `./<id>`, explicit `--path .`, interactive
Git init prompt, non-interactive/JSON no-prompt behavior, non-empty directory
rejection, and metadata writing.
- Added register behavior for existing folders, id inference from folder name,
metadata writing, id/path conflict rejection, and registry updates.
- Added list behavior as a registry index only.
- Added doctor behavior for registry/path/metadata health and cheap Git
presence.
- Updated `initiative list` so no selector lists across registered stores,
`--store` filters, `--store-path` remains an escape hatch, human output is
compact, and all-store partial success returns warning diagnostics.
@@ -0,0 +1,29 @@
# Add Minimal Context Store UX Tasks
- [x] Create Item 6 work-item tracking notes.
- [x] Capture agent-first setup and discovery direction.
- [x] Decide `context-store` is the first CLI namespace.
- [x] Decide setup defaults to `./<id>` when `--path` is omitted.
- [x] Decide current-directory setup requires explicit `--path .`.
- [x] Record that checked-in store metadata stays minimal.
- [x] Decide checked-in store metadata is exactly `.openspec-store/store.yaml`
and contains portable identity only.
- [x] Record that machine-local registry state stays outside the store.
- [x] Record that `initiative list` should default across registered stores.
- [x] Decide setup interactive and non-interactive behavior.
- [x] Decide register behavior.
- [x] Decide context-store list is registry index only.
- [x] Decide doctor owns health checks.
- [x] Decide initiative list partial-success behavior.
- [x] Decide JSON and exit behavior for partial success and total failure.
- [x] Decide id inference uses folder/repo name as-is with normal validation.
- [x] Decide setup rejects non-empty folders without context-store metadata.
- [x] Decide registry path/id conflicts fail for now.
- [x] Decide empty states for list, doctor, and initiative list.
- [x] Initially defer completion metadata; later add static metadata with the
rest of the shipped command surface.
- [x] Finalize exact JSON payload fields for setup, register, list, doctor, and
all-store initiative list.
- [x] Implement `context-store setup/register/list/doctor`.
- [x] Update `initiative list` all-store behavior and output.
- [x] Add focused tests and verification evidence.
@@ -0,0 +1,97 @@
# Add Agent-First Initiative Discovery Evidence
## Conversation Decisions
- `initiative show <id>` should be a locator/discovery command for agents.
- The command should answer which initiative the user meant, where the
canonical context lives, and where the initiative metadata is.
- The command should not concatenate markdown, summarize initiative contents,
compute work progress, resolve local repos, list linked changes, or open a
workspace.
- Default lookup should search all registered context stores.
- `--store <id>` should disambiguate or filter to one registered store.
- `--store-path <path>` should remain the explicit local-path escape hatch.
- Duplicate initiative ids across stores should fail with an ambiguity error.
- Default all-store lookup should fail when any registered store is unreadable,
because uniqueness is unknowable.
- Explicit `--store` and `--store-path` lookup should only care about the
selected store.
- `initiative.status` should be omitted from the v1 output projection.
- `owners` should be omitted from the v1 output projection.
- Arbitrary `metadata` should be omitted from the v1 output projection.
- `version` and `created` should stay in the v1 initiative projection.
- `files` should be omitted from v1.
- `initiative.metadata_path` should point to the validated `initiative.yaml`.
- `initiative.root` is enough for an agent to inspect the folder with normal
filesystem tools.
- Top-level `matches` should be omitted. Ambiguity and incomplete-lookup
candidates should live under the diagnostic that needs them, for example
`status[0].details.matches`.
- `context_store.source` should be omitted from `initiative show` v1 because it
is selector provenance, not context-store identity.
- A top-level `resolution` field is not needed in v1.
- Existing `initiative create/list` output can keep `context_store.source` for
now; this item should not refactor old output shapes.
- `readInitiative` should return `null` when the exact initiative is absent and
throw when `initiative.yaml` exists but is invalid or has the wrong id.
- In default all-store lookup, any unreadable registered store should make the
primary error `initiative_lookup_incomplete`, even when readable stores have
partial matches.
- If `initiatives/<id>/initiative.yaml` exists but is invalid or has the wrong
id, `initiative show` should fail as broken initiative state instead of
treating that store as not found.
- Human output should be a compact locator view on success: title, id, summary,
context store, location, and canonical filenames.
- Human ambiguity and incomplete-lookup errors should show matching or partial
matching stores inline, then point to the next command.
- Static shell completion metadata should ship for `initiative show`.
- Dynamic completions for store ids and initiative ids should remain deferred.
## Research Notes
- Current initiative create/list output spreads the full parsed
`initiative.yaml` state, which is useful for MVP but too broad for the first
`show` contract.
- A focused per-initiative read operation is preferred over implementing `show`
through `listInitiatives`, because exact lookup should not fail due to an
unrelated malformed initiative folder.
- Other initiative files are schema/config dependent and should not be
hardcoded into `show`.
- Keeping candidates inside diagnostic details follows the same general shape as
GraphQL-style responses: successful data stays clean, while error-specific
context travels with the error.
- If selector provenance is needed later, add a separate explicit field such as
`resolution` rather than putting provenance inside `context_store`.
- Human output should stay compact: title, id, summary, context store,
location, and metadata path.
## Implementation Evidence
- `src/core/collections/initiatives/operations.ts` adds `readInitiative` for
exact initiative lookup.
- `src/commands/initiative.ts` adds `initiative show <id>` with all-store
default lookup, `--store`, `--store-path`, JSON output, compact human output,
ambiguity diagnostics, and incomplete-lookup diagnostics.
- `src/core/completions/command-registry.ts` adds static completion metadata for
`initiative show`.
- `test/core/collections/initiatives/operations.test.ts` covers exact read,
absent initiatives, invalid exact initiatives, id mismatches, and unrelated
invalid folders.
- `test/commands/initiative.test.ts` covers `initiative show` success,
`--store-path`, human output, ambiguity, incomplete lookup, not found,
invalid exact initiative state, no `context_store.source`, no `files`, no
top-level `matches`, and static completions.
## Verification
- `pnpm run build`
- `pnpm exec vitest run test/core/collections/initiatives/operations.test.ts`
- `pnpm exec vitest run test/commands/initiative.test.ts`
- `pnpm exec vitest run test/commands/context-store.test.ts
test/commands/initiative.test.ts test/core/context-store/foundation.test.ts
test/core/context-store/registry.test.ts
test/core/collections/initiatives/operations.test.ts`
- `pnpm run lint`
- `git diff --check`
- Markdown line-length check for the initiative roadmap, task tracker, and Item
7 work-item notes.
@@ -0,0 +1,184 @@
# Add Agent-First Initiative Discovery
## Status
Implementation complete; verification in progress.
## Source Of Truth
Start from `../../direction.md`.
This item exists because the expected workflow is agent-first:
```text
Using initiative billing-launch, explore the API work and create a proposal.
```
Before repo-local linking, local resolution, or workspace opening can work, the
agent needs a small command that answers:
- Which initiative did the user mean?
- Which context store contains the canonical initiative?
- Where is the initiative metadata, and what root should the agent inspect?
## Goal
Add agent-first initiative discovery without turning `show` into a reader,
progress dashboard, repo resolver, or workspace launcher.
## Locked Direction So Far
- `initiative show <id>` is a locator/discovery command.
- It should return identity, context-store location, initiative location, and
the initiative metadata path.
- It should not concatenate markdown, summarize file contents, compute progress,
resolve repos, list linked changes, or open workspaces.
- Default lookup searches all locally registered context stores.
- `--store <id>` filters to one registered store.
- `--store-path <path>` remains the explicit local-path escape hatch.
- Duplicate initiative ids across stores are ambiguous. The command should not
auto-pick a match.
- In default all-store lookup, unreadable stores make the lookup incomplete.
The command should fail rather than silently returning a possibly false
unique match.
- Explicit `--store` and `--store-path` modes only consider the selected store.
## Output Contract Direction
The first JSON contract should be a resolver/read-pointer projection, not a
full serialization of `initiative.yaml`.
Suggested success shape:
```json
{
"context_store": {
"id": "platform",
"root": "/path/to/platform-context"
},
"initiative": {
"version": 1,
"id": "billing-launch",
"title": "Billing Launch",
"summary": "Coordinate billing launch work.",
"created": "2026-05-21",
"root": "/path/to/platform-context/initiatives/billing-launch",
"store_path": "initiatives/billing-launch",
"metadata_path": "/path/to/platform-context/initiatives/billing-launch/initiative.yaml"
},
"status": []
}
```
Locked field decisions:
- Keep `initiative.version`.
- Keep `initiative.created`.
- Keep `initiative.id`, `title`, `summary`, `root`, `store_path`, and
`metadata_path`.
- Keep `context_store.id` and `root`.
- Omit `context_store.source` from `initiative show` v1. It is selector
provenance, not context-store identity. Existing create/list output can remain
unchanged for now.
- Omit a top-level `resolution` field from v1.
- Omit `initiative.status` from the v1 projection.
- Omit `initiative.owners` from the v1 projection.
- Omit arbitrary `initiative.metadata` from the v1 projection.
- Omit a `files` list from the v1 projection.
- Omit top-level `matches`.
- Put ambiguity and incomplete-lookup candidates under the relevant diagnostic
entry, such as `status[0].details.matches`.
- Keep top-level `status` as command diagnostics only, not initiative work
progress.
## Still To Decide
- Nothing for the minimal v1 slice.
## Human Output Direction
Success output should stay locator-focused:
```text
OpenSpec initiative: Billing Launch
ID: billing-launch
Summary: Coordinate billing launch work.
Context store: platform
Location: /path/to/platform-context/initiatives/billing-launch
Files:
Metadata: /path/to/platform-context/initiatives/billing-launch/initiative.yaml
```
Error output should stay plain:
- Not found: say the initiative was not found in registered context stores and
suggest `openspec initiative list`.
- Ambiguous: show matching stores and paths, then suggest
`openspec initiative show <id> --store <store>`.
- Incomplete lookup: say some context stores could not be read, include partial
matches when present, then suggest `openspec context-store doctor`.
## File Listing Direction
`initiative show` should not list initiative folder contents in v1.
Only `initiative.yaml` is required to identify and validate the initiative. All
other files are schema/config dependent and may differ across teams. Once the
command has resolved `initiative.root`, agents can use normal filesystem tools
to inspect the folder. Later schema-aware views can expose important files
without hardcoding today's default template filenames.
## Completion Direction
Add static shell completion metadata for:
```text
initiative show <id> --store <id> --store-path <path> --json
```
Do not add dynamic completions for registered store ids or initiative ids in
this slice.
## Core Read Operation Direction
Add a focused `readInitiative` operation for exact lookup.
Behavior:
- Return `null` when the initiative folder or `initiative.yaml` is absent.
- Throw when `initiative.yaml` exists but is invalid.
- Throw when the parsed `initiative.yaml` id does not match the folder id.
- Do not scan unrelated initiative folders.
## Lookup Error Precedence
For default all-store lookup, any unreadable registered store makes lookup
incomplete.
If one or more readable stores contain the initiative and one or more other
stores cannot be read, the primary error should still be
`initiative_lookup_incomplete`, not success or ambiguity. Include any readable
partial matches under the diagnostic details.
Explicit `--store` and `--store-path` modes are scoped to the selected store and
do not check unrelated registered stores.
Invalid exact initiative folders are broken shared state, not "not found".
If `initiatives/<id>/initiative.yaml` exists but is invalid or has a mismatched
id, `initiative show` should fail with an invalid-initiative diagnostic. In
default all-store lookup, unreadable stores still take precedence as
`initiative_lookup_incomplete` because the full candidate set is unknowable.
## Explicitly Out Of Scope
- Top-level `openspec show` integration.
- Markdown content bundles or generated context packs.
- Checked-in initiative snapshots in repo-local changes.
- Repo-local change linking.
- Local repo/workspace resolution.
- Workspace opening.
- Git sync status, dirty state, remotes, pull, push, or conflicts.
- Initiative progress or status dashboards.
@@ -0,0 +1,27 @@
# Add Agent-First Initiative Discovery Tasks
- [x] Create Item 7 work-item tracking notes.
- [x] Decide `initiative show <id>` is a locator/discovery command.
- [x] Decide default lookup searches all registered context stores.
- [x] Decide `--store` and `--store-path` remain the narrowing selectors.
- [x] Decide duplicate initiative ids are ambiguity errors.
- [x] Decide unreadable stores make default all-store lookup incomplete.
- [x] Decide the v1 projection omits `initiative.status`, `owners`, and
arbitrary `metadata`.
- [x] Decide the v1 projection keeps `initiative.version` and `created`.
- [x] Decide v1 omits `files` and only returns initiative root plus metadata
path.
- [x] Decide ambiguity and incomplete-lookup candidates live under diagnostic
details, not top-level `matches`.
- [x] Decide exact human output direction for success and error states.
- [x] Decide `initiative show` omits `context_store.source`.
- [x] Decide `initiative show` omits a top-level `resolution` field.
- [x] Decide static completion metadata ships with Item 7.
- [x] Decide `readInitiative` returns `null` for absent and throws for invalid.
- [x] Decide incomplete lookup takes precedence over success or ambiguity in
default all-store mode.
- [x] Decide invalid exact initiative folders are errors, not not-found.
- [x] Implement a focused per-initiative read operation.
- [x] Implement `initiative show`.
- [x] Register static completion metadata for `initiative show`.
- [x] Add focused tests and verification evidence.
@@ -0,0 +1,239 @@
# Connect Repo-Local Changes To Initiatives Evidence
## Decision 1: Initiative Link Location
The initiative link should live in the repo-local change `.openspec.yaml`.
Example:
```yaml
schema: spec-driven
created: 2026-05-22
initiative:
store: platform
id: billing-launch
```
This keeps repo implementation ownership in the repo while preserving a durable
reference to canonical initiative context.
The link should not include local paths, copied initiative prose, or backlinks
inside the initiative store.
## Research Notes
- `createChange()` already writes `.openspec.yaml` for every change.
- `ChangeMetadataSchema` currently allows schema, created, goal, and
affected-area fields. Item 8 can extend that schema with `initiative`.
- Archive moves the whole change directory, so the initiative link will move
with archived changes.
- Apply, validate, and archive should not require context-store availability in
this slice.
## Decision 2: Create Command Shape
Initiative-linked creation should use `openspec new change` with `--initiative`.
Supported first-slice forms:
```bash
openspec new change add-billing-api --initiative billing-launch --json
openspec new change add-billing-api --initiative platform/billing-launch --json
openspec new change add-billing-api --initiative billing-launch --store platform --json
```
This keeps the operation repo-owned. The initiative is a reference on the
change, not the actor that creates or owns the change.
The first slice should also add `--json` to `new change` so agents can capture
the created change path, metadata path, and initiative reference.
## Decision 3: Initiative Lookup Behavior
Bare `--initiative <id>` should reuse `initiative show` lookup semantics.
It searches all registered context stores and succeeds only when the lookup is
complete and exactly one readable store contains the initiative.
Explicit store selectors narrow lookup:
```bash
openspec new change add-billing-api --initiative platform/billing-launch
openspec new change add-billing-api --initiative billing-launch --store platform
openspec new change add-billing-api --initiative billing-launch --store-path ./context
```
`--store-path` validates the explicit path and reads its store id, but does not
auto-register the store. Metadata still stores only the portable store id and
initiative id.
Repo-local metadata should not be written until initiative lookup is complete
and unambiguous.
## Decision 4: Repo-Local Only For V1
Item 8 should support initiative links only on repo-local changes.
If `openspec new change <id> --initiative ...` runs from a workspace planning
home, v1 should refuse and tell the user to run the command from the repo that
owns the implementation plan.
Existing workspace-planning changes remain compatibility behavior and should not
gain initiative linkage in this slice.
This preserves the boundary that initiatives coordinate shared context,
repo-local changes own implementation plans, and workspaces open local views.
## Decision 5: No Repo Ownership Matching In V1
Item 8 should not verify that the current repo is named by, owned by, or inferred
from the initiative.
Creating a repo-local change with an initiative link records participation in the
initiative. It does not prove ownership, repo impact, or coverage of an
initiative area.
Repo ownership matching can be revisited after initiative resolution or explicit
initiative metadata has a real repo/area model.
## Decision 6: JSON And Human Output
Create output should stay factual and minimal.
Human output should confirm:
- the created change id and location
- the schema
- the initiative link `{ store, id }`
JSON output should include:
```json
{
"change": {
"id": "add-billing-api",
"path": "/repo/openspec/changes/add-billing-api",
"metadataPath": "/repo/openspec/changes/add-billing-api/.openspec.yaml",
"schema": "spec-driven"
},
"initiative": {
"store": "platform",
"id": "billing-launch"
}
}
```
The output should not include `next` or other suggested workflow actions. API
responses should report operation results or errors; choosing the next action is
the agent's responsibility and depends on broader context.
## Decision 7: Existing Change Recovery
Item 8 should include a friendly recovery command for existing repo-local
changes:
```bash
openspec set change add-billing-api --initiative billing-launch --json
openspec set change add-billing-api --initiative platform/billing-launch --json
openspec set change add-billing-api --initiative billing-launch --store platform --json
openspec set change add-billing-api --initiative billing-launch --store-path ../context --json
```
This command is a validated setter for checked-in repo-local change metadata. In
Item 8, the only supported settable field is the initiative link, and the only
file it may mutate is `openspec/changes/<id>/.openspec.yaml`.
The command should not edit proposal, design, tasks, specs, or initiative-store
files. It should not store local paths or write backlinks into the initiative.
If the requested initiative link already exists, the command should succeed as
an idempotent no-op. If a different initiative link already exists, the command
should fail without writing. Replacement, relink, unlink, and dry-run behavior
are deferred.
Rationale:
- Agents can forget to link a change during creation, so a first-class recovery
path is useful.
- `set change` matches the actual side effect: writing validated change metadata
to `.openspec.yaml`.
- Keeping the command scoped to `.openspec.yaml` avoids creating a broad change
editing surface.
- `openspec change ...` is currently deprecated, `edit` implies opening an
editor, and `update` already means refreshing local OpenSpec tooling or
guidance.
## Decision 8: Status And Instructions Visibility
Status and instructions should surface that the repo-local change is linked to
an initiative, but should not display or resolve the initiative itself.
Human status output should show the stored initiative reference, and JSON status
output should include the stored initiative `{ store, id }`. Instructions output
should include a concise factual note that the change is linked to the
initiative.
Status and instructions should not read, summarize, validate, or resolve the
initiative from the context store in v1. Missing or unavailable context stores
should not make repo-local status or instructions fail.
This keeps the relationship visible during ordinary repo-local workflows while
preserving the boundary that initiative lookup and context reading belong to
initiative-specific commands.
## Latest Open-Decision Notes
Date: 2026-05-23.
All decisions for Item 8 are now confirmed for implementation.
Implementation should keep the first slice small:
- The light release should test whether initiative-linked repo-local changes are
useful before adding gating, ownership inference, or broader workflow
integration.
- Standalone `initiative resolve` was later rejected; workspace local-view state
owns local path mapping.
- Source provenance, history/export, contract maps, and target-bound
initiative-hosted changes remain useful future discussion points, but should
not block this initial slice.
## Implementation Evidence
Date: 2026-05-23.
Implemented:
- `openspec new change <id> --initiative ...` for repo-local changes, with
`--json`, `--store`, and `--store-path` support.
- `openspec set change <id> --initiative ...` for existing repo-local changes.
- Portable checked-in metadata under `initiative: { store, id }`.
- Status and instructions visibility from stored metadata only.
- Workspace refusal, lookup-failure no-write behavior, same-link idempotency,
and different-link conflict protection.
Verification:
```bash
pnpm run build
```
Result: passed.
```bash
pnpm exec eslint src/commands/workflow/new-change.ts src/commands/workflow/set-change.ts src/commands/workflow/initiative-link.ts src/commands/workflow/instructions.ts src/commands/workflow/status.ts src/commands/workflow/shared.ts src/commands/initiative.ts src/core/artifact-graph/types.ts src/core/artifact-graph/instruction-loader.ts src/utils/change-utils.ts src/cli/index.ts
```
Result: passed.
```bash
pnpm exec vitest run test/utils/change-metadata.test.ts test/commands/change-initiative-link.test.ts
```
Result: passed, 39 tests.
```bash
pnpm exec vitest run test/commands/artifact-workflow.test.ts test/commands/initiative.test.ts test/core/artifact-graph/instruction-loader.test.ts
```
Result: passed, 110 tests.
@@ -0,0 +1,279 @@
# Connect Repo-Local Changes To Initiatives
## Status
Implemented. The original decision text below is preserved as design record;
current completion evidence lives in `tasks.md` and `evidence.md`.
## Source Of Truth
Start from `../../direction.md` and the Item 8 roadmap entry.
The relevant boundary is:
```text
Initiatives coordinate shared context.
Repo-local changes own implementation plans.
Workspaces open local views.
```
## Goal
Let an agent create or link a repo-local OpenSpec change to a shared
initiative without copying initiative prose, storing machine-local paths, or
making the initiative own repo implementation artifacts.
Example user prompt:
```text
Using initiative billing-launch, create a proposal for API work.
```
## Decisions
### 1. Initiative Link Location
Decision: Store the initiative link in the repo-local change `.openspec.yaml`.
Suggested metadata shape:
```yaml
schema: spec-driven
created: 2026-05-22
initiative:
store: platform
id: billing-launch
```
Rules:
- Store only the context store id and initiative id.
- Do not store local context-store paths.
- Do not store local repo paths.
- Do not create a checked-in `initiative.md` snapshot by default.
- Do not write backlinks into the initiative.
Rationale:
- `.openspec.yaml` is already the per-change machine-readable metadata file.
- The link is durable repo context and should be checked in with the change.
- The canonical initiative context remains in the context store.
- The metadata stays portable across teammates and machines.
### 2. Create Command Shape
Decision: Add initiative linking to the repo-local change creation command with
`--initiative`.
Supported first-slice forms:
```bash
openspec new change add-billing-api --initiative billing-launch --json
openspec new change add-billing-api --initiative platform/billing-launch --json
openspec new change add-billing-api --initiative billing-launch --store platform --json
```
Rules:
- The command starts from `new change` because the change is repo-owned.
- `--initiative` modifies repo-local change creation; it does not make the
initiative create or own the change.
- `--json` should be added to `new change` for agent-readable handoff output.
- A separate initiative-owned create command is not part of the first slice.
Rationale:
- The expected user flow is agent-first: "using initiative X, create a proposal
for repo work."
- Agents need one normal repo-local create command that can also write the
initiative reference.
- Keeping the verb rooted in `new change` preserves the boundary that changes
implement repo-owned slices.
### 3. Initiative Lookup Behavior
Decision: Reuse `initiative show` lookup semantics for `--initiative`.
Rules:
- Bare `--initiative <id>` searches all registered context stores.
- Bare lookup succeeds only when exactly one readable registered store contains
the initiative id.
- Duplicate initiative ids across stores fail as ambiguous.
- Any unreadable registered store makes bare lookup incomplete and fails before
writing change metadata.
- `--initiative <store>/<id>` selects one registered store by id.
- `--initiative <id> --store <store>` also selects one registered store by id.
- `--initiative <id> --store-path <path>` validates the explicit local context
store path, reads its store id, and writes only `{ store, id }` to metadata.
- `--store-path` does not auto-register the context store.
- Do not write repo-local initiative metadata until lookup is complete and
unambiguous.
Rationale:
- Agents can use the short form when it is safe.
- Durable repo-local links should not be created from partial knowledge.
- The behavior matches existing agent-first discovery semantics.
### 4. Repo-Local Only For V1
Decision: Item 8 supports initiative links only on repo-local changes.
Rules:
- `openspec new change <id> --initiative ...` creates an initiative-linked
change only when the current planning home is repo-local.
- If the command runs from a workspace planning home, v1 refuses with clear
guidance to run the command from the repo that owns the implementation plan.
- Existing workspace-planning changes remain compatibility behavior and are not
extended with initiative linkage in this slice.
Rationale:
- The current product boundary assigns implementation plans to repo-local
OpenSpec changes.
- Workspaces are local views, not the durable planning owner for initiative
work.
- Extending workspace-planning changes would revive the superseded
workspace-owns-the-plan model.
### 5. Repo Ownership Matching
Decision: Do not attempt repo ownership matching in v1.
Rules:
- Creating a repo-local change with an initiative link records participation in
the initiative.
- The link does not claim that OpenSpec verified repo ownership, repo impact, or
initiative area coverage.
- The command should not block or warn solely because the current repo is absent
from initiative content.
Rationale:
- Item 8 should not invent repo ownership or monorepo area semantics.
- Ownership matching belongs with later initiative resolution or explicit
initiative metadata.
- Keeping v1 small lets teams test whether linked repo-local changes are useful
before adding policy gates.
### 6. JSON And Human Output
Decision: Keep create output factual and minimal.
Rules:
- Output should report what the command did, not recommend workflow next steps.
- Human output should confirm the created change location, schema, and initiative
link.
- JSON output should include stable fields for the created change and initiative
link.
- JSON output should not include a `next` command or suggested workflow action.
- Output should not include initiative summaries, repo ownership claims,
resolved local context-store paths, or progress/status-like fields.
Suggested JSON shape:
```json
{
"change": {
"id": "add-billing-api",
"path": "/repo/openspec/changes/add-billing-api",
"metadataPath": "/repo/openspec/changes/add-billing-api/.openspec.yaml",
"schema": "spec-driven"
},
"initiative": {
"store": "platform",
"id": "billing-launch"
}
}
```
Rationale:
- CLI/API-style responses should state operation results or errors.
- Accurately choosing the next action depends on agent context and should remain
the agent's responsibility.
- Keeping output factual avoids coupling change creation to later lifecycle
design.
### 7. Existing Change Recovery
Decision: Include a recovery command for setting the initiative link on an
existing repo-local change.
Command shape:
```bash
openspec set change add-billing-api --initiative billing-launch --json
openspec set change add-billing-api --initiative platform/billing-launch --json
openspec set change add-billing-api --initiative billing-launch --store platform --json
openspec set change add-billing-api --initiative billing-launch --store-path ../context --json
```
Rules:
- `openspec set change <id> --initiative ...` is a validated setter for
repo-local change metadata.
- In Item 8, the only supported settable field is the initiative link.
- The command only mutates `openspec/changes/<id>/.openspec.yaml`.
- The command does not edit proposal, design, tasks, specs, or initiative-store
files.
- The command uses the same initiative lookup semantics as
`openspec new change <id> --initiative ...`.
- If the same initiative link already exists, the command succeeds as an
idempotent no-op.
- If a different initiative link already exists, the command fails without
writing. Replacement, relink, unlink, and dry-run behavior are not part of v1.
- If the command runs from a workspace planning home, it refuses for the same
reason as initiative-linked `new change`.
Rationale:
- Agents can forget to pass `--initiative` during change creation; v1 needs a
friendly recovery path.
- `set change` describes the real operation: setting checked-in change metadata,
not creating an initiative-owned relationship.
- Keeping the command limited to `.openspec.yaml` avoids a broad edit surface.
- Avoid `openspec change ...` because that namespace is currently deprecated.
- Avoid `edit` because it implies opening an editor, and avoid `update` because
OpenSpec already uses update for local guidance/tool refresh.
### 8. Status And Instructions Visibility
Decision: Surface the initiative link in status and instructions output without
resolving or displaying the initiative itself.
Rules:
- Human status output should show that the change is linked to an initiative.
- JSON status output should include the stored initiative `{ store, id }`.
- Instructions output should include a concise factual note that the change is
linked to the initiative.
- Status and instructions must not read, summarize, validate, or resolve the
initiative from the context store in v1.
- Missing or unavailable context stores must not make repo-local status or
instructions fail.
- Output should not add next-step recommendations.
Rationale:
- The initiative link should be visible in normal repo-local workflow output so
users and agents do not miss the relationship.
- Keeping visibility to stored metadata avoids introducing context-store
availability as a dependency for repo-local workflow commands.
- Initiative resolution belongs to initiative-specific commands, not status or
instructions in this slice.
## Open Decisions
None. Decision pass complete; confirm the decisions before implementation.
## Latest Suggested Resolutions
These were the suggested answers carried into implementation:
- Surface the stored initiative link in status and instructions without reading
or displaying the initiative itself.
@@ -0,0 +1,22 @@
# Connect Repo-Local Changes To Initiatives Tasks
## Decisions
- [x] Decide where the initiative link lives.
- [x] Decide command shape for creating initiative-linked changes.
- [x] Decide initiative lookup behavior for `--initiative`.
- [x] Decide whether workspace-scoped changes are allowed in this slice.
- [x] Decide whether repo ownership matching is attempted in v1.
- [x] Decide JSON and human output shape.
- [x] Decide whether Item 8 includes linking existing changes.
- [x] Decide whether status/instructions surface initiative links.
- [x] Confirm latest suggested resolutions in `plan.md` before implementation.
## Implementation
- [x] Extend change metadata schema with an optional initiative link.
- [x] Persist initiative metadata when creating repo-local changes.
- [x] Add command support for creating initiative-linked changes.
- [x] Add tests for metadata validation and persistence.
- [x] Add tests for command output and lookup failures.
- [x] Add status/instruction visibility for stored initiative links.
@@ -0,0 +1,64 @@
# Item 9 Decision: Reject Initiative Resolve
## Final Decision
Do not implement a standalone `openspec initiative resolve <id>` command, now
or later.
The command is unnecessary because it tries to do work that already belongs to
other concepts:
- `initiative show` finds the canonical initiative.
- A workspace is the local view over repos and folders.
- Repo-local changes link themselves to initiatives.
- Repo-local status reports work progress.
## Decision 1: No Command
No separate initiative command is needed.
If the user only has a context store, `initiative show` is enough. If the user
has a workspace, the local view is already represented by that workspace. If the
user is inside a repo, repo-local commands are enough.
## Decision 2: Local Resolution Belongs To Workspace
A workspace maps local repos and folders to paths on one machine. Future
initiative-aware local opening belongs in workspace behavior.
## Decision 3: Agent Behavior
Agents should:
- Use `openspec initiative show <id> --json` for shared context.
- Use the current workspace view when the user is working in a workspace.
- Use repo-local commands when the user is working in a repo.
- Let the user decide which repos are present locally.
## Decision 4: Rejected Scope
Remove all standalone resolve behavior:
- no `initiative resolve`
- no all-repo scan
- no all-workspace scan
- no `--path` search roots
- no Git remote matching
- no cloning
- no worktree or branch creation
- no initiative backlinks
- no local availability dashboard
## Decision 5: Roadmap Update
Convert Item 9 into a decision-only checkpoint.
Replacement:
```text
Item 9. Reject Initiative Resolve
Decision: do not add `openspec initiative resolve`, now or later. Initiative
discovery belongs to `initiative show`; local path mapping belongs to
workspaces; implementation progress belongs to repo-local changes.
```
@@ -0,0 +1,106 @@
# Reject Initiative Resolve Evidence
## Decision Summary
Date: 2026-05-25.
After review, the standalone `openspec initiative resolve <id>` command should
not be implemented, now or later.
The useful distinction is already covered by existing concepts:
- `initiative show` resolves canonical shared initiative context.
- A workspace is the local view over repos and folders.
- Repo-local changes link themselves to initiatives through checked-in metadata.
- Repo-local status reports implementation progress.
A standalone resolve command would mostly duplicate workspace local-view state
or provide weak output when no workspace is present.
## Pressure Test
Scenario:
```bash
git clone git@github.com:acme/context.git
openspec context-store register ./context --id platform
openspec initiative show billing-launch --json
```
This can locate:
```text
platform/billing-launch
./context/initiatives/billing-launch
./context/initiatives/billing-launch/initiative.yaml
```
It cannot know:
```text
which implementation repos should exist locally
where those repos are on this machine
which repos the user intends to work in
which repos should be cloned
which workspace view the user wants
```
That knowledge belongs to the user and the workspace, not the initiative.
## Why Workspace Changes The Answer
When a user has a workspace, the local view is already resolved by the
workspace:
```text
workspace -> link names -> machine-local paths
```
The agent can operate from the workspace context. A separate
`initiative resolve` command would add another layer that mostly reprints what
the workspace already owns.
If future UX needs initiative-aware opening, it should be part of workspace
behavior, such as opening or preparing a workspace around a selected initiative.
It should not be a standalone initiative command pretending to infer local repo
availability.
## Research Notes Retained
The earlier investigation is still useful as background:
- `initiative show` already has correct context-store lookup behavior,
ambiguity handling, incomplete lookup handling, and JSON locator output.
- Item 8 stores initiative links in repo-local `.openspec.yaml` as
`{ store, id }`.
- Workspace state owns local path mappings and generated open surfaces.
- Existing repo-local status and instructions expose initiative links but do not
resolve or summarize the initiative.
Those findings support the final decision: do not add a standalone command; keep
each responsibility in its existing owner.
## Rejected Scope
Rejected for Item 9:
- `openspec initiative resolve <id>`
- path-resolution dashboards
- progress dashboards
- all-workspace scans
- all-repo scans
- explicit path scanning as an initiative command
- Git remote matching
- repo ownership inference
- cloning or branch/worktree orchestration
- initiative backlinks
## Verification
This pass updates decision artifacts only.
```bash
git diff --check
```
Result: passed after this revision.
@@ -0,0 +1,141 @@
# Reject Initiative Resolve
## Status
Final decision: do not implement a standalone `openspec initiative resolve`
command, now or later.
## Source Of Truth
Start from `../../direction.md` and the boundary:
```text
Context stores sync truth.
Collections shape truth.
Initiatives coordinate work.
Workspaces open local views.
Changes implement repo-owned slices.
```
Item 8 already established that repo-local changes may reference initiatives
through portable checked-in metadata:
```yaml
initiative:
store: platform
id: billing-launch
```
## Final Decision
Do not ship `openspec initiative resolve <id>` as a user-facing command in this
slice or any future slice.
The earlier command framing was too broad. It tried to join initiative identity,
workspace local paths, explicit repo roots, and linked repo-local changes into a
new CLI surface. That makes the command look authoritative even though the
initiative does not own local repo paths, repo participation, or implementation
state.
## Why The Command Is Not Needed
If a user only has a context store clone, OpenSpec can already resolve the
canonical initiative with:
```bash
openspec initiative show billing-launch --json
```
That answers:
```text
What initiative is this, which context store contains it, and where is the
canonical initiative folder?
```
It cannot answer:
```text
Which local implementation repos should exist on this machine?
```
because that information is not in the context store.
If a user has a workspace, the workspace is already the local view. It already
maps local repos and folders to paths on this machine. A separate
`initiative resolve` command would mostly re-describe the workspace the user is
already using.
If a user is in a repo, the repo-local change commands and status commands
already operate from that repo. The user or agent can inspect the current repo's
changes directly.
## Product Rule
Do not create a new command whose main job is to discover local paths that the
workspace already represents.
Rules:
- `initiative show` remains the command for canonical initiative discovery.
- Workspaces remain the local view over repos, folders, context stores, and
initiatives.
- Repo-local changes remain the implementation artifacts.
- Agents should use the current workspace or current repo context rather than
asking a standalone initiative command to infer local availability.
- OpenSpec should not infer repo ownership, scan arbitrary repos, clone repos,
create worktrees, or write backlinks to make resolve appear smarter than it
is.
## What To Do Instead
Keep the pieces separate:
- Use `openspec initiative show <id> --json` to locate canonical shared context.
- Use workspace commands to set up, link, relink, list, open, update, and doctor
local views.
- Use repo-local `openspec new change ... --initiative ...` and
`openspec set change ... --initiative ...` to create durable links from repo
work to initiative context.
- Use `openspec status --change <id> --json` inside the owning repo to inspect
implementation progress.
If a future workspace workflow needs to open an initiative-specific view, it
should be designed under workspace behavior, not as a standalone initiative
resolve command.
## Deferred Or Replaced Scope
The following ideas are not part of Item 9 implementation:
- `openspec initiative resolve <id>`
- scanning all registered workspaces
- scanning all repos on disk
- explicit `--path` based initiative resolution
- Git remote matching
- repo ownership inference
- cloning, fetching, pulling, pushing
- branch or worktree creation
- initiative backlinks
- progress dashboards
- local availability dashboards
## Roadmap Disposition
Item 9 is a decision-only checkpoint. It records that standalone initiative
resolution is rejected permanently.
Roadmap framing:
```text
Item 9. Reject Initiative Resolve
Decision: do not add `openspec initiative resolve`, now or later. Initiative
discovery belongs to `initiative show`; local path mapping belongs to
workspaces; implementation progress belongs to repo-local changes.
```
## Next Useful Work
The next useful implementation slice is workspace initiative opening, without a
standalone resolve prerequisite.
@@ -0,0 +1,22 @@
# Reject Initiative Resolve Tasks
## Decisions
- [x] Create Item 9 work-item tracking notes.
- [x] Pressure-test whether a standalone `initiative resolve` command is needed.
- [x] Decide that a standalone user-facing `initiative resolve` command should
not be implemented now or later.
- [x] Decide `initiative show` remains sufficient for canonical initiative
discovery.
- [x] Decide workspace local-view state is the right place for local repo/path
mapping.
- [x] Decide repo-local status remains the right place for work progress.
- [x] Decide not to add all-repo scanning, all-workspace scanning, Git remote
matching, cloning, worktree creation, or initiative backlinks.
## Follow-Up
- [x] Update the central roadmap entry for Item 9.
- [x] Update the initiative task tracker.
- [x] Record workspace initiative opening as the next useful implementation
slice.
@@ -0,0 +1,430 @@
# Let Workspaces Open Initiatives
## Status
Product decisions are locked. The remaining work is implementation design and
delivery.
## Source Of Truth
Start from `../../direction.md` and the boundary:
```text
Context stores sync truth.
Collections shape truth.
Initiatives coordinate work.
Workspaces open local views.
Changes implement repo-owned slices.
```
Item 9 rejected standalone initiative resolution. Initiative discovery belongs
to `initiative show`; local path mapping belongs to workspace local-view state.
## Locked Direction
A workspace does not contain the work. It remembers how this runtime opens the
work.
```text
private local view record
-> generated runtime files
-> opener-specific launch
-> initiative context + selected local repos/folders
```
The durable part is the user's private local view choice. The generated part is
runtime support for agents and editors.
## Product Goal
Let a user open a shared initiative in their own local runtime with the context
and repos they care about.
Examples:
- A Team A developer opens `platform/billing-launch` with local Repo A and Repo
B.
- A Team B developer opens the same initiative with local Repo C only.
- A user opens the initiative context only, links repos later, and still gets
useful agent guidance.
## Non-Goals
- Do not clone repos.
- Do not create branches or worktrees.
- Do not use Git submodules as the workspace primitive.
- Do not infer all participating repos from Git remotes or disk scans.
- Do not write generated agent files into linked repos or context stores.
- Do not make workspace-level `changes/` the durable planning model.
- Do not enforce edit permissions in Item 10.
## Decision Register
### Command UX
Status: decided.
Use `workspace open` for initiative local-view realization:
```bash
openspec workspace open --initiative platform/billing-launch
openspec workspace open --initiative billing-launch --store platform
openspec workspace open --initiative billing-launch
openspec workspace open team-a-billing --initiative platform/billing-launch
```
Rationale: the action being performed is local view realization, so the command
belongs under `workspace open` rather than `initiative open`.
Lookup behavior:
- If the user provides `<store>/<initiative>`, use that exact store selector.
- If the user provides `<initiative> --store <store>`, use that exact store
selector.
- If the user provides only `<initiative>`, search registered context stores and
proceed when there is exactly one exact match.
- If multiple stores contain the same initiative id, stop and show the matching
stores with a hint to retry using `<store>/<initiative>` or `--store`.
- If no exact match exists, do not silently open the closest match. Show a small
list of likely matches when available, plus a hint to run `openspec
initiative list`.
- If some registered stores cannot be read, keep the result conservative. Do not
choose a match that could be ambiguous behind an unreadable store unless the
user supplied an explicit store selector.
Interactive UX may let a human choose from suggestions. JSON and non-interactive
UX should return structured errors and suggestions without prompting.
Workspace-name behavior:
- The optional positional workspace name remains the local view identity.
- If the user provides a workspace name with `--initiative`, create or reuse that
named local view.
- If the user omits a workspace name, create or reuse a friendly default derived
from the initiative id when that is unambiguous.
- On name collisions or multiple existing local views for the same initiative,
let the human choose interactively or require an explicit workspace name in
non-interactive mode.
### Open Target
Status: decided.
Default to opening the initiative directory, not the whole context store.
User-facing behavior:
```bash
openspec workspace open --initiative billing-launch
```
opens a focused local view:
```text
generated files in the workspace root
context-store/initiatives/billing-launch/
selected local repos/folders
```
It should not open the entire context store by default.
Rationale:
- The user asked for one initiative, so the opened context should be focused on
that initiative.
- Agents receive less unrelated shared context.
- Unrelated initiatives and shared files are not exposed by default.
- The local view stays easier to understand: generated workspace root plus this
initiative plus selected implementation roots.
Generated guidance and JSON output should still report the context store root
and that broader context exists. A later explicit option may open the full
context store, for example `--context-scope store` or `--include-store`, but
broad store scope is not the default for Item 10.
### Local View Record
Status: decided.
Use one private local view record: the root `workspace.yaml` file.
```yaml
version: 1
name: billing-launch
context:
kind: initiative
store:
id: platform
selector:
kind: registry
id: platform
initiative:
id: billing-launch
links:
repo-a: /Users/me/repos/repo-a
repo-b: /Users/me/repos/repo-b
preferred_opener: codex
tools:
- codex
```
This decision covers the conceptual record shape and the fact that generated
runtime files are not durable state.
If the user selected a context store by local path, the private workspace record
can keep that runtime-local selector without changing checked-in repo metadata:
```yaml
context:
kind: initiative
store:
id: platform
selector:
kind: path
path: /Users/me/context/platform
observed_id: platform
initiative:
id: billing-launch
```
The context binding is optional. A user can also create a workspace that is not
linked to any initiative:
```yaml
version: 1
name: team-a-local
context: null
links:
repo-a: /Users/me/repos/repo-a
repo-b: /Users/me/repos/repo-b
preferred_opener: codex
tools:
- codex
```
This is a first-class workspace shape, not only an edge case for initiative
opening. Item 10 should preserve custom non-initiative workspaces while adding
initiative-aware opening.
### Workspace Storage And Generated Files
Status: decided.
Store each private workspace view under the user's OpenSpec global data
directory, keyed by workspace name:
```text
getGlobalDataDir()/workspaces/<workspace-name>/
```
The workspace name is the local identity. The selected store and initiative, if
any, are data inside the private record; they do not define the storage path.
This keeps the workspace API generic enough for custom local views that are not
initiative-linked.
Initial shape:
```text
getGlobalDataDir()/workspaces/<workspace-name>/
workspace.yaml
AGENTS.md
<workspace-name>.code-workspace
.codex/
skills/
.claude/
skills/
```
`workspace.yaml` is the durable private view record and the only view file in
Item 10. The other files are generated runtime support owned by OpenSpec. They
may be overwritten by `workspace open`, `workspace update`, or a future explicit
preparation surface.
Do not add a separate generated-output directory for Item 10. The managed
workspace root is already the private generated view.
Initiative open defaults:
- If the user provides a workspace name and no workspace exists, create that
workspace bound to the selected initiative.
- If the user provides a workspace name and it already points at the same
initiative, reuse it and regenerate runtime files.
- If the user provides a workspace name and it has no context binding, bind it
to the selected initiative only after clear user confirmation; in
non-interactive mode, fail and require an explicit future rebind/update
surface.
- If the user provides a workspace name and it points at a different initiative
or context, do not silently repoint it. Stop with a clear error and require an
explicit future rebind/update surface.
- If the user omits a workspace name and exactly one existing workspace points at
the selected initiative, reuse it.
- If the user omits a workspace name and no existing workspace points at the
selected initiative, create a friendly default workspace name derived from the
initiative id only when that name is unused.
- If the derived workspace name collides with another workspace, ask for an
explicit workspace name or show matching workspace choices instead of hiding
the collision behind a path convention.
- If multiple workspaces point at the same initiative, let the user choose or
require an explicit workspace name in non-interactive mode.
### Generated Runtime Files
Status: decided.
Generate runtime files at the workspace root, next to `workspace.yaml`.
```text
getGlobalDataDir()/workspaces/<workspace-name>/
```
The generated files can contain `AGENTS.md`, skills, launch prompts, and
generated editor workspace files.
Regeneration behavior:
- `workspace open` regenerates the managed runtime files before launching the
opener.
- `workspace update` regenerates the managed runtime files without changing
durable local view choices unless the user asked for a state change.
- Generated files are OpenSpec-owned and may be overwritten each time.
- `workspace.yaml` is not generated output and should not be overwritten except
when the local view record itself changes.
### Runtime Identity
Status: decided.
Use `getGlobalDataDir()` as the runtime-local boundary. It is already
cross-platform and resolves to the appropriate user data directory for macOS,
Linux, Windows, Codespaces, WSL, SSH hosts, and containers.
Local paths in `workspace.yaml` are valid only in the runtime that wrote them.
If the same user opens the same initiative from another runtime, they create or
relink that runtime's workspace there. Item 10 should not add path translation,
shared machine identities, or an extra `<runtime-id>` path segment.
### Prepare/JSON Surface
Status: decided.
Keep `workspace open --json` as a machine-facing receipt for the same open
operation. Do not add `--prepare-only` for Item 10.
The JSON response should be useful to agents and desktop integrations, not just
a success boolean. It should include the workspace name, workspace root,
generated file paths, selected context, opened roots, skipped or missing roots,
opener, launch status, and warnings.
Human-facing behavior remains the normal `workspace open` output. JSON mode is
for tools that need structured facts after OpenSpec has prepared the workspace
root and attempted the requested open.
### Missing Paths At Open Time
Status: decided.
Workspace opening should be strict about the selected initiative/context and
forgiving about optional linked local paths.
- If the selected initiative cannot be resolved, fail before launch.
- If the context store or initiative path is unavailable, fail before launch and
point to context-store registration/doctor guidance.
- If a linked repo or folder is missing, warn and skip that root; do not block a
context-only or partially linked open.
- Human output should name skipped links and suggest `workspace doctor` or
relink guidance.
- JSON output should include skipped or missing roots and warnings.
### Codex Desktop
Status: decided.
Open the generated workspace root as the Codex Desktop project. Surface the
attached initiative path and linked repo/folder paths through generated guidance
and the `workspace open --json` response.
Do not depend on Desktop multi-root automation for Item 10. If Desktop later has
a clearer multi-root contract, it can become an enhancement without changing the
workspace storage model.
### Edit Boundaries
Status: decided.
Item 10 emits advisory boundaries only. Generated context should distinguish
coordination context from implementation targets, but it should not enforce
write restrictions.
The generated view should label initiative/context-store files as shared
coordination context and linked repos/folders as local implementation context
when selected. Strong enforcement can come later.
## First-Run UX Sketch
Status: deferred beyond the first implementation slice.
This sketch captures the eventual human interactive flow. Item 10 should not
depend on building a full guided setup wizard; the first implementation may use
explicit flags and structured errors first.
```text
Found initiative: platform/billing-launch
No local workspace view exists for this runtime.
Create a local view?
> Open context only
Link existing local repos/folders
Cancel
```
No option in this first-run flow should clone, branch, create worktrees, or
create submodules.
## Machine-Readable Open Contract
`workspace open --json` is the machine-readable contract for the generated
runtime context. Item 10 should not create a separate machine-readable view
file; the durable view record is `workspace.yaml`.
The JSON response should tell agents:
- schema version
- workspace name and workspace root
- selected initiative id, title, and path
- selected context store id and path
- generated file paths
- opened roots
- skipped or missing roots
- linked repo-local changes when known
- advisory edit boundaries
- next repair commands
- warnings and launch status when produced by `workspace open --json`
If no implementation target is selected, `allowedEditRoots` should be empty or
explicitly advisory.
The exact schema can evolve during implementation, but the JSON response should
make the generated view self-describing enough for agents and desktop
integrations without scraping human output.
## Forward Compatibility
The initial `context` record supports the selected context store and initiative.
Do not design the YAML parser so narrowly that future records cannot add fields
for configurable change homes, artifact homes, target bindings, or other
collection/view metadata.
## Compatibility Notes
The current beta workspace implementation creates a managed root with
`changes/`, `AGENTS.md`, `.gitignore`,
`.openspec-workspace/workspace.yaml`, `.openspec-workspace/local.yaml`, and a
durable `.code-workspace` file.
Item 10's intended new shape is a root `workspace.yaml` plus generated runtime
files at the managed workspace root. Existing beta workspaces should be treated
as compatibility inputs. Migration or removal of all beta internals is deferred
unless the implementation slice intentionally scopes that migration.
For the initiative-opening model, generated runtime files are derived artifacts,
not workspace truth.
@@ -0,0 +1,43 @@
# Let Workspaces Open Initiatives Tasks
## Decisions
- [x] Create Item 10 work-item tracking notes.
- [x] Lock the high-level direction: private local view record plus generated
runtime files.
- [x] Decide command UX.
- [x] Decide default open target.
- [x] Decide private local view record shape.
- [x] Decide private local view record storage namespace and keying.
- [x] Decide generated runtime file location and lifetime.
- [x] Decide runtime identity rules.
- [x] Decide prepare/JSON surface.
- [x] Decide Codex Desktop behavior.
- [x] Decide Item 10 edit-boundary semantics.
## Implementation Scope To Confirm Later
- [x] Add or adapt workspace local-view state for initiative opening.
- [x] Preserve non-initiative custom workspaces as first-class local views.
- [x] Resolve initiative context through existing `initiative show` semantics.
- [x] Implement workspace-name reuse and collision behavior for initiative open.
- [x] Generate opener-specific runtime files.
- [x] Return explicit machine-readable view context from `workspace open --json`.
- [x] Launch agent/editor with generated workspace root plus initiative context and
selected local repos/folders.
- [x] Warn and skip missing linked repos/folders at open time while failing on
missing selected initiative/context.
- [x] Add doctor guidance for missing context stores, missing local links, stale
view records, and advisory edit boundaries.
- [x] Ensure Item 10 opens known local paths only and does not clone, branch,
create worktrees, or use submodules.
## Deferred
- [ ] Multiple saved views per initiative.
- [ ] Shared/exported workspace templates.
- [ ] Repo auto-discovery or Git remote matching.
- [ ] Strong edit-boundary enforcement.
- [ ] Codex Desktop multi-root automation if the Desktop contract is not clear
enough for Item 10.
- [ ] Migration or removal of all existing beta workspace root artifacts.

Some files were not shown because too many files have changed in this diff Show More