mirror of
https://github.com/Fission-AI/OpenSpec.git
synced 2026-10-03 22:13:19 +08:00
Compare commits
32
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
79a45ac043 | ||
|
|
80f61a5550 | ||
|
|
f529b25968 | ||
|
|
93f7b797cf | ||
|
|
7d07101363 | ||
|
|
c0f29044f9 | ||
|
|
7fe45ca330 | ||
|
|
c8e2072e3a | ||
|
|
cd5e49346f | ||
|
|
a18d992fa1 | ||
|
|
4df6a4889b | ||
|
|
9b5007dbc3 | ||
|
|
cce787ec40 | ||
|
|
94d651de8c | ||
|
|
040e382d64 | ||
|
|
caafd7c9bf | ||
|
|
144528257d | ||
|
|
af0b3418d0 | ||
|
|
7fd5417ed0 | ||
|
|
5ac1e12b83 | ||
|
|
fd7ad273c7 | ||
|
|
ea6f380fea | ||
|
|
765df47ad3 | ||
|
|
64d476f8b9 | ||
|
|
afdca0d5da | ||
|
|
61eb999f7c | ||
|
|
3d3bf96061 | ||
|
|
d199dfa407 | ||
|
|
d7d186088e | ||
|
|
6a3a1263fe | ||
|
|
1e94443a35 | ||
|
|
a0608d0bab |
@@ -3,6 +3,8 @@ name: CI
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
merge_group:
|
||||
branches: [main]
|
||||
push:
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
@@ -42,7 +44,7 @@ jobs:
|
||||
name: Test
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
if: github.event_name == 'pull_request'
|
||||
if: github.event_name == 'pull_request' || github.event_name == 'merge_group'
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
@@ -81,7 +83,7 @@ jobs:
|
||||
name: Test (${{ matrix.label }})
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 15
|
||||
if: github.event_name != 'pull_request'
|
||||
if: github.event_name == 'push'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -242,7 +244,7 @@ jobs:
|
||||
validate-changesets:
|
||||
name: Validate Changesets
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'pull_request'
|
||||
if: github.event_name == 'pull_request' || github.event_name == 'merge_group'
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
@@ -275,7 +277,7 @@ jobs:
|
||||
name: All checks passed
|
||||
runs-on: ubuntu-latest
|
||||
needs: [test_pr, lint, nix-flake-validate]
|
||||
if: always() && github.event_name == 'pull_request'
|
||||
if: always() && (github.event_name == 'pull_request' || github.event_name == 'merge_group')
|
||||
steps:
|
||||
- name: Verify all checks passed
|
||||
run: |
|
||||
@@ -301,7 +303,7 @@ jobs:
|
||||
name: All checks passed
|
||||
runs-on: ubuntu-latest
|
||||
needs: [test_matrix, lint, nix-flake-validate]
|
||||
if: always() && github.event_name != 'pull_request'
|
||||
if: always() && github.event_name == 'push'
|
||||
steps:
|
||||
- name: Verify all checks passed
|
||||
run: |
|
||||
|
||||
@@ -153,3 +153,9 @@ result
|
||||
# OpenCode
|
||||
.opencode/
|
||||
opencode.json
|
||||
|
||||
# Codex
|
||||
.codex/
|
||||
|
||||
# Bob
|
||||
.bob/
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
## Product Thinking
|
||||
|
||||
When discussing workflows, documentation, onboarding, or product behavior, start from the user's goal and lived interaction. Do not translate the problem into CLI commands, config flags, file formats, or internal implementation steps as the primary answer unless the user explicitly asks for that level.
|
||||
|
||||
Default framing:
|
||||
|
||||
- What is the user trying to accomplish?
|
||||
- Where are they starting from?
|
||||
- What should they say or do in the product experience?
|
||||
- What should the agent/system do on their behalf?
|
||||
- What outcome should they see?
|
||||
|
||||
Only after that, mention commands, files, APIs, or implementation mechanics as supporting detail. Treat these as backing mechanisms, not the user journey.
|
||||
|
||||
Bad pattern:
|
||||
|
||||
```text
|
||||
Run command X, then command Y, then command Z.
|
||||
```
|
||||
|
||||
Better pattern:
|
||||
|
||||
```text
|
||||
Open the relevant experience and tell the agent what outcome you want. The system should guide the workflow and may use command X/Y/Z internally.
|
||||
```
|
||||
|
||||
If the user is critiquing UX, docs, or workflow design, do not answer with a bare CLI recipe. First restate the intended human workflow, then identify where the current product forces implementation details onto the user.
|
||||
|
||||
@@ -1,5 +1,48 @@
|
||||
# @fission-ai/openspec
|
||||
|
||||
## 1.3.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#952](https://github.com/Fission-AI/OpenSpec/pull/952) [`cce787e`](https://github.com/Fission-AI/OpenSpec/commit/cce787ec4083da2b27781f6786f5ce0002909a7b) Thanks [@TabishB](https://github.com/TabishB)! - ### New Features
|
||||
|
||||
- **Junie support** — Added tool and command generation for JetBrains Junie
|
||||
- **Lingma IDE support** — Added configuration support for Lingma IDE
|
||||
- **ForgeCode support** — Added tool support for ForgeCode
|
||||
- **IBM Bob support** — Added support for IBM Bob coding assistant
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **Shell completions opt-in** — Completion install is now opt-in, fixing PowerShell encoding corruption
|
||||
- **Copilot auto-detection** — Prevented false GitHub Copilot detection from a bare `.github/` directory
|
||||
- **pi.dev command generation** — Fixed command reference transforms and template argument passing
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#760](https://github.com/Fission-AI/OpenSpec/pull/760) [`61eb999`](https://github.com/Fission-AI/OpenSpec/commit/61eb999f7c6c0fc98d2e7f3678756fce6a3f4378) Thanks [@fsilvaortiz](https://github.com/fsilvaortiz)! - fix: OpenCode adapter now uses `.opencode/commands/` (plural) to match OpenCode's official directory convention. Fixes #748.
|
||||
|
||||
- [#759](https://github.com/Fission-AI/OpenSpec/pull/759) [`afdca0d`](https://github.com/Fission-AI/OpenSpec/commit/afdca0d5dab1aa109cfd8848b2512333ccad60c3) Thanks [@fsilvaortiz](https://github.com/fsilvaortiz)! - fix: `openspec status` now exits gracefully when no changes exist instead of throwing a fatal error. Fixes #714.
|
||||
|
||||
## 1.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#747](https://github.com/Fission-AI/OpenSpec/pull/747) [`1e94443`](https://github.com/Fission-AI/OpenSpec/commit/1e94443a3551b228eecbc89e95d96d3b9600a192) Thanks [@TabishB](https://github.com/TabishB)! - ### New Features
|
||||
|
||||
- **Profile system** — Choose between `core` (4 essential workflows) and `custom` (pick any subset) profiles to control which skills get installed. Manage profiles with the new `openspec config profile` command
|
||||
- **Propose workflow** — New one-step workflow creates a complete change proposal with design, specs, and tasks from a single request — no need to run `new` then `ff` separately
|
||||
- **AI tool auto-detection** — `openspec init` now scans your project for existing tool directories (`.claude/`, `.cursor/`, etc.) and pre-selects detected tools
|
||||
- **Pi (pi.dev) support** — Pi coding agent is now a supported tool with prompt and skill generation
|
||||
- **Kiro support** — AWS Kiro IDE is now a supported tool with prompt and skill generation
|
||||
- **Sync prunes deselected workflows** — `openspec update` now removes command files and skill directories for workflows you've deselected, keeping your project clean
|
||||
- **Config drift warning** — `openspec config list` warns when global config is out of sync with the current project
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fixed onboard preflight giving a false "not initialized" error on freshly initialized projects
|
||||
- Fixed archive workflow stopping mid-way when syncing — it now properly resumes after sync completes
|
||||
- Added Windows PowerShell alternatives for onboard shell commands
|
||||
|
||||
## 1.1.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -36,27 +36,20 @@ Our philosophy:
|
||||
> [!TIP]
|
||||
> **New workflow now available!** We've rebuilt OpenSpec with a new artifact-guided workflow.
|
||||
>
|
||||
> Run `/opsx:onboard` to get started. → [Learn more here](docs/opsx.md)
|
||||
> Run `/opsx:propose "your idea"` to get started. → [Learn more here](docs/opsx.md)
|
||||
|
||||
<p align="center">
|
||||
Follow <a href="https://x.com/0xTab">@0xTab on X</a> for updates · Join the <a href="https://discord.gg/YctCnvvshC">OpenSpec Discord</a> for help and questions.
|
||||
</p>
|
||||
|
||||
### Teams
|
||||
|
||||
Using OpenSpec in a team? [Email here](mailto:teams@openspec.dev) for access to our Slack channel.
|
||||
|
||||
<!-- TODO: Add GIF demo of /opsx:new → /opsx:archive workflow -->
|
||||
<!-- TODO: Add GIF demo of /opsx:propose → /opsx:archive workflow -->
|
||||
|
||||
## See it in action
|
||||
|
||||
```text
|
||||
You: /opsx:new add-dark-mode
|
||||
You: /opsx:propose add-dark-mode
|
||||
AI: Created openspec/changes/add-dark-mode/
|
||||
Ready to create: proposal
|
||||
|
||||
You: /opsx:ff # "fast-forward" - generate all planning docs
|
||||
AI: ✓ proposal.md — why we're doing this, what's changing
|
||||
✓ proposal.md — why we're doing this, what's changing
|
||||
✓ specs/ — requirements and scenarios
|
||||
✓ design.md — technical approach
|
||||
✓ tasks.md — implementation checklist
|
||||
@@ -101,10 +94,12 @@ cd your-project
|
||||
openspec init
|
||||
```
|
||||
|
||||
Now tell your AI: `/opsx:new <what-you-want-to-build>`
|
||||
Now tell your AI: `/opsx:propose <what-you-want-to-build>`
|
||||
|
||||
If you want the expanded workflow (`/opsx:new`, `/opsx:continue`, `/opsx:ff`, `/opsx:verify`, `/opsx:sync`, `/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 20+ tools and growing.
|
||||
> Not sure if your tool is supported? [View the full list](docs/supported-tools.md) – we support 25+ tools and growing.
|
||||
>
|
||||
> Also works with pnpm, yarn, bun, and nix. [See installation options](docs/installation.md).
|
||||
|
||||
@@ -114,6 +109,8 @@ Now tell your AI: `/opsx:new <what-you-want-to-build>`
|
||||
→ **[Workflows](docs/workflows.md)**: combos and patterns<br>
|
||||
→ **[Commands](docs/commands.md)**: slash commands & skills<br>
|
||||
→ **[CLI](docs/cli.md)**: terminal reference<br>
|
||||
→ **[Workspace Mode](docs/workspace.md)**: when to use cross-repo workspaces, starting with `openspec workspace setup`<br>
|
||||
→ **[Workspace Demo](docs/workspace-demo.md)**: a real-user workspace tutorial you can run against your actual local repos<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>
|
||||
|
||||
+846
@@ -0,0 +1,846 @@
|
||||
# Workspace POC Roadmap
|
||||
|
||||
## Goal
|
||||
|
||||
Deliver a lean but real Workspace POC that follows the intended user flow:
|
||||
|
||||
`workspace create` -> `workspace add-repo` -> `new change --targets` -> `workspace open --change` -> `apply --change --repo` -> workspace-aware `status` -> explicit workspace completion/archive.
|
||||
|
||||
The roadmap is deliberately execution-ordered. Early phases establish the entrypoint and filesystem model first, then add repo registration, then cross-repo planning, then execution handoff, then roll-up and completion semantics.
|
||||
|
||||
## POC Guardrails
|
||||
|
||||
- Centralize planning in the workspace, not canonical truth.
|
||||
- Keep canonical specs in the owning repo.
|
||||
- Keep repo-local execution repo-local.
|
||||
- Reuse `change` as the primary user-facing primitive.
|
||||
- Keep workspace metadata under `.openspec/` at the workspace root.
|
||||
- Do not create an extra inner `openspec/` directory inside a dedicated workspace.
|
||||
- Store stable aliases in committed workspace metadata and absolute paths only in the local overlay.
|
||||
- Make repo attachment change-scoped, not workspace-wide.
|
||||
- Reuse the workspace change ID when materializing repo-local changes.
|
||||
- Start with create-only materialization unless a research phase explicitly chooses otherwise.
|
||||
- Keep mocks narrow. Prefer real temp directories, real file IO, and real CLI execution.
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
- Reuse the existing Vitest setup, `runCLI()` helper, and temp-directory pattern already used across the repo.
|
||||
- Add one reusable `workspaceSandbox()` helper instead of many bespoke test setups.
|
||||
- Add a small fixture set under `test/fixtures/workspace-poc/` and clone it into temp roots per test with `fs.cp` and `mkdtemp`.
|
||||
- Add shared assertions for the core invariants: no nested `openspec/` under the workspace root; no absolute repo paths in committed files; materialized repo-local change IDs match workspace change IDs; change-scoped attach only includes targeted repos.
|
||||
- Mock only prompt boundaries, telemetry, and agent-launch adapters. Do not mock filesystem behavior, path canonicalization, materialization logic, or status roll-up rules unless the test is specifically about an adapter boundary.
|
||||
- Keep three reusable filesystem shapes: empty workspace sandbox, happy-path workspace with three repos, and dirty workspace with stale aliases, partial materialization, and incomplete tasks.
|
||||
|
||||
## Output Convention
|
||||
|
||||
Every phase writes a `SUMMARY.md` to its phase directory.
|
||||
|
||||
- Build and test phases write to `notes/workspace-poc/phase-XX-<slug>/SUMMARY.md`, `notes/workspace-poc/phase-XX-<slug>/VERIFY.md`, and `notes/workspace-poc/phase-XX-<slug>/MANUAL_TEST.md`
|
||||
- Research phases write to `notes/workspace-poc/phase-XX-<slug>/SUMMARY.md`, `notes/workspace-poc/phase-XX-<slug>/DECISION.md`, `notes/workspace-poc/phase-XX-<slug>/VERIFY.md`, and `notes/workspace-poc/phase-XX-<slug>/MANUAL_TEST.md`
|
||||
- Task and acceptance-check checkboxes are phase-scoped and numbered sequentially, for example `01.1`, `01.2`, `01.3`.
|
||||
|
||||
The summary should capture:
|
||||
|
||||
- what was changed
|
||||
- what tests were run
|
||||
- what passed or failed
|
||||
- open issues for the next phase
|
||||
|
||||
The verification note should capture:
|
||||
|
||||
- what was independently checked in a fresh context
|
||||
- what issues were found
|
||||
- what fixes were applied
|
||||
- what residual risks remain, if any
|
||||
|
||||
The manual test note should capture:
|
||||
|
||||
- what user-visible or smoke scenarios were exercised in a fresh context
|
||||
- what passed or failed
|
||||
- what fixes were applied
|
||||
- what residual risks remain, if any
|
||||
|
||||
## Phase 00 - Testing Infrastructure Foundation
|
||||
|
||||
Type: Build
|
||||
|
||||
Usable outcome: A lean test harness exists for workspace work, so later phases can use real workspace and repo state without inventing new infrastructure each time.
|
||||
|
||||
Output summary directory: `notes/workspace-poc/phase-00-test-harness/`
|
||||
|
||||
Completion checklist:
|
||||
|
||||
- [x] Tasks completed
|
||||
- [x] Acceptance tests satisfied
|
||||
- [x] Independent verification complete
|
||||
- [x] Manual testing complete
|
||||
- [x] Phase complete
|
||||
|
||||
Tasks:
|
||||
|
||||
- [x] 00.1 Add `test/helpers/workspace-sandbox.ts` to create a temp managed workspace root plus attached repos.
|
||||
- [x] 00.2 Add fixture seeds under `test/fixtures/workspace-poc/` for `empty`, `happy-path`, and `dirty`.
|
||||
- [x] 00.3 Add shared assertion helpers for path leakage, workspace layout, target membership, and materialization invariants.
|
||||
- [x] 00.4 Reserve test suite locations for new coverage: `test/core/workspace/`, `test/commands/workspace/`, and `test/cli-e2e/workspace/`.
|
||||
- [x] 00.5 Keep the harness compatible with the current `runCLI()` helper and forked Vitest workers.
|
||||
|
||||
Acceptance tests:
|
||||
|
||||
- [x] 00.6 `workspaceSandbox()` creates a workspace root with `.openspec/` and `changes/`, and no inner `openspec/`.
|
||||
- [x] 00.7 Cloned fixtures can be mutated independently without cross-test bleed.
|
||||
- [x] 00.8 Committed fixture files never contain absolute repo paths.
|
||||
- [x] 00.9 CLI tests can run against the sandbox and keep JSON output free of spinner noise.
|
||||
|
||||
## Phase 01 - Workspace Create Entrypoint
|
||||
|
||||
Type: Build
|
||||
|
||||
Usable outcome: A user can create a persistent workspace root through `openspec workspace create <name>`.
|
||||
|
||||
Output summary directory: `notes/workspace-poc/phase-01-workspace-create/`
|
||||
|
||||
Completion checklist:
|
||||
|
||||
- [x] Tasks completed
|
||||
- [x] Acceptance tests satisfied
|
||||
- [x] Independent verification complete
|
||||
- [x] Manual testing complete
|
||||
- [x] Phase complete
|
||||
|
||||
Tasks:
|
||||
|
||||
- [x] 01.1 Add the `workspace` command group and the `workspace create` entrypoint.
|
||||
- [x] 01.2 Reuse the current init/setup path rather than inventing a second bootstrap system.
|
||||
- [x] 01.3 Implement managed workspace root creation.
|
||||
- [x] 01.4 Create `.openspec/workspace.yaml`, `.openspec/local.yaml`, and top-level `changes/`.
|
||||
- [x] 01.5 Ensure `.openspec/local.yaml` is treated as local-only state.
|
||||
- [x] 01.6 Make the created layout clearly distinct from repo-local `openspec/` roots.
|
||||
|
||||
Acceptance tests:
|
||||
|
||||
- [x] 01.7 Creating a workspace produces `.openspec/workspace.yaml`, `.openspec/local.yaml`, and `changes/`.
|
||||
- [x] 01.8 The workspace root does not contain `openspec/changes`.
|
||||
- [x] 01.9 Re-running against an existing workspace fails or behaves idempotently in one explicit, documented way.
|
||||
- [x] 01.10 Invalid or duplicate workspace names fail with actionable errors.
|
||||
|
||||
## Phase 02 - Validate Workspace Create
|
||||
|
||||
Type: Test
|
||||
|
||||
Usable outcome: `workspace create` is covered at unit, command, and CLI layers before other workspace behavior builds on it.
|
||||
|
||||
Output summary directory: `notes/workspace-poc/phase-02-test-workspace-create/`
|
||||
|
||||
Completion checklist:
|
||||
|
||||
- [x] Tasks completed
|
||||
- [x] Acceptance tests satisfied
|
||||
- [x] Independent verification complete
|
||||
- [x] Manual testing complete
|
||||
- [x] Phase complete
|
||||
|
||||
Tasks:
|
||||
|
||||
- [x] 02.1 Add unit tests for managed path resolution and workspace metadata initialization.
|
||||
- [x] 02.2 Add command-level tests for create behavior and failure modes.
|
||||
- [x] 02.3 Add CLI e2e coverage for `workspace create`, help text, exit codes, and layout assertions.
|
||||
|
||||
Acceptance tests:
|
||||
|
||||
- [x] 02.4 Help output documents `workspace create`.
|
||||
- [x] 02.5 Successful CLI creation yields a usable workspace root on disk.
|
||||
- [x] 02.6 JSON output remains clean if a machine-readable mode is added.
|
||||
- [x] 02.7 Duplicate create attempts do not corrupt the workspace root.
|
||||
|
||||
## Phase 03 - Repo Registry and Doctor
|
||||
|
||||
Type: Build
|
||||
|
||||
Usable outcome: A workspace can register repo aliases and validate them with `workspace add-repo` and `workspace doctor`.
|
||||
|
||||
Output summary directory: `notes/workspace-poc/phase-03-repo-registry/`
|
||||
|
||||
Completion checklist:
|
||||
|
||||
- [x] Tasks completed
|
||||
- [x] Acceptance tests satisfied
|
||||
- [x] Independent verification complete
|
||||
- [x] Manual testing complete
|
||||
- [x] Phase complete
|
||||
|
||||
Tasks:
|
||||
|
||||
- [x] 03.1 Implement committed alias storage in `.openspec/workspace.yaml`.
|
||||
- [x] 03.2 Implement absolute path storage in `.openspec/local.yaml`.
|
||||
- [x] 03.3 Validate that registered paths exist and contain repo-local OpenSpec state.
|
||||
- [x] 03.4 Canonicalize stored local paths.
|
||||
- [x] 03.5 Implement `workspace doctor` to check alias resolution, missing repos, and overlay drift.
|
||||
|
||||
Acceptance tests:
|
||||
|
||||
- [x] 03.6 `workspace add-repo <alias> <path>` stores the alias in committed metadata and the path only in local metadata.
|
||||
- [x] 03.7 Missing paths and duplicate aliases fail cleanly.
|
||||
- [x] 03.8 Paths are canonicalized before persistence.
|
||||
- [x] 03.9 `workspace doctor` reports stale or missing repos without mutating state.
|
||||
- [x] 03.10 No absolute path leaks into committed workspace files.
|
||||
|
||||
## Phase 04 - Validate Repo Registry and Doctor
|
||||
|
||||
Type: Test
|
||||
|
||||
Usable outcome: Repo registration becomes trustworthy enough for targeted changes and later agent attachment.
|
||||
|
||||
Output summary directory: `notes/workspace-poc/phase-04-test-repo-registry/`
|
||||
|
||||
Completion checklist:
|
||||
|
||||
- [x] Tasks completed
|
||||
- [x] Acceptance tests satisfied
|
||||
- [x] Independent verification complete
|
||||
- [x] Manual testing complete
|
||||
- [x] Phase complete
|
||||
|
||||
Tasks:
|
||||
|
||||
- [x] 04.1 Add pure tests for alias parsing, path canonicalization, committed-vs-local serialization, and doctor diagnostics.
|
||||
- [x] 04.2 Add command tests for add-repo and doctor using the workspace sandbox.
|
||||
- [x] 04.3 Add CLI e2e coverage for happy path and stale path scenarios.
|
||||
|
||||
Acceptance tests:
|
||||
|
||||
- [x] 04.4 Doctor detects missing repo roots, missing `openspec/`, and alias/path drift.
|
||||
- [x] 04.5 Committed metadata remains stable across local path changes.
|
||||
- [x] 04.6 Repairing a stale path in `local.yaml` restores doctor success.
|
||||
- [x] 04.7 The registry remains readable after multiple repo additions in one workspace.
|
||||
|
||||
## Phase 05 - Target-Aware Workspace Change Creation
|
||||
|
||||
Type: Build
|
||||
|
||||
Usable outcome: A workspace can create a central cross-repo change with `openspec new change <id> --targets <a,b,c>`.
|
||||
|
||||
Output summary directory: `notes/workspace-poc/phase-05-targeted-change-create/`
|
||||
|
||||
Completion checklist:
|
||||
|
||||
- [x] Tasks completed
|
||||
- [x] Acceptance tests satisfied
|
||||
- [x] Independent verification complete
|
||||
- [x] Manual testing complete
|
||||
- [x] Phase complete
|
||||
|
||||
Tasks:
|
||||
|
||||
- [x] 05.1 Extend change creation to support workspace topology.
|
||||
- [x] 05.2 Record explicit targets in workspace change metadata.
|
||||
- [x] 05.3 Scaffold central planning artifacts in the workspace change: proposal, design, coordination tasks, and per-target draft task/spec partitions.
|
||||
- [x] 05.4 Hard-fail if a requested target alias is unknown.
|
||||
- [x] 05.5 Ensure no repo-local artifacts are created yet.
|
||||
|
||||
Acceptance tests:
|
||||
|
||||
- [x] 05.6 Creating a targeted workspace change records the exact target set.
|
||||
- [x] 05.7 Per-target planning directories are created under the workspace change.
|
||||
- [x] 05.8 Unknown or duplicate targets fail with actionable errors.
|
||||
- [x] 05.9 Repo-local repos remain untouched until `apply`.
|
||||
- [x] 05.10 Duplicate change IDs still fail predictably.
|
||||
|
||||
## Phase 06 - Validate Target-Aware Change Creation
|
||||
|
||||
Type: Test
|
||||
|
||||
Usable outcome: The central planning object is stable before any agent-open or materialization work begins.
|
||||
|
||||
Output summary directory: `notes/workspace-poc/phase-06-test-targeted-change-create/`
|
||||
|
||||
Completion checklist:
|
||||
|
||||
- [x] Tasks completed
|
||||
- [x] Acceptance tests satisfied
|
||||
- [x] Independent verification complete
|
||||
- [x] Manual testing complete
|
||||
- [x] Phase complete
|
||||
|
||||
Tasks:
|
||||
|
||||
- [x] 06.1 Add unit tests for target parsing and workspace change metadata rules.
|
||||
- [x] 06.2 Add command tests for targeted change creation against a registered workspace.
|
||||
- [x] 06.3 Add CLI e2e coverage for successful creation, unknown aliases, and untouched repo-local roots.
|
||||
|
||||
Acceptance tests:
|
||||
|
||||
- [x] 06.4 `new change --targets` rejects aliases not present in the workspace registry.
|
||||
- [x] 06.5 The workspace change layout matches the chosen topology.
|
||||
- [x] 06.6 The workspace change contains central planning artifacts and per-target partitions only.
|
||||
- [x] 06.7 Running status or doctor after creation still sees the workspace as healthy.
|
||||
|
||||
## Phase 07 - Research Minimum `workspace open` Contract
|
||||
|
||||
Type: Research
|
||||
|
||||
Usable outcome: The team decides the smallest honest v0 behavior for `workspace open --change` without overcommitting to multi-root agent support that may not be real.
|
||||
|
||||
Output summary directory: `notes/workspace-poc/phase-07-open-contract-research/`
|
||||
|
||||
Completion checklist:
|
||||
|
||||
- [x] Tasks completed
|
||||
- [x] Acceptance tests satisfied
|
||||
- [x] Independent verification complete
|
||||
- [x] Manual testing complete
|
||||
- [x] Phase complete
|
||||
|
||||
Tasks:
|
||||
|
||||
- [x] 07.1 Write the research note in `notes/workspace-poc/phase-07-open-contract-research/DECISION.md`.
|
||||
- [x] 07.2 Decide the minimum v0 behavior for planning-only mode, change-scoped attached mode, supported agent targets for the demo path, and failure behavior when one or more targeted repos are unresolved.
|
||||
- [x] 07.3 Choose whether non-primary agents are supported, partial, or explicitly out of scope in v0.
|
||||
|
||||
Acceptance tests:
|
||||
|
||||
- [x] 07.4 The research note names one recommended contract and at least one rejected alternative.
|
||||
- [x] 07.5 The note defines exact user-visible behavior for `workspace open --change <id>` and `workspace open` with no change.
|
||||
- [x] 07.6 The note lists testable success and failure cases for the next phase.
|
||||
|
||||
## Phase 08 - Workspace Open
|
||||
|
||||
Type: Build
|
||||
|
||||
Usable outcome: A user can open the workspace in planning-only mode or open a specific change with only its target repos attached.
|
||||
|
||||
Output summary directory: `notes/workspace-poc/phase-08-workspace-open/`
|
||||
|
||||
Completion checklist:
|
||||
|
||||
- [x] Tasks completed
|
||||
- [x] Acceptance tests satisfied
|
||||
- [x] Independent verification complete
|
||||
- [x] Manual testing complete
|
||||
- [x] Phase complete
|
||||
|
||||
Tasks:
|
||||
|
||||
- [x] 08.1 Implement `workspace open --change <id> [--agent <tool>]`.
|
||||
- [x] 08.2 Implement planning-only mode when no change is supplied.
|
||||
- [x] 08.3 Ensure change-scoped open resolves only the change’s targeted repos.
|
||||
- [x] 08.4 Integrate with the existing command-generation/tooling path rather than inventing a new one.
|
||||
- [x] 08.5 Fail with actionable diagnostics when targeted repos are unresolved.
|
||||
|
||||
Acceptance tests:
|
||||
|
||||
- [x] 08.6 `workspace open` without `--change` does not attach repo roots.
|
||||
- [x] 08.7 `workspace open --change <id>` attaches only targeted repos, not all registered repos.
|
||||
- [x] 08.8 Open fails clearly when a targeted repo path is stale or missing.
|
||||
- [x] 08.9 The chosen primary agent path produces a usable session launch or instruction surface.
|
||||
|
||||
## Phase 09 - Validate Workspace Open
|
||||
|
||||
Type: Test
|
||||
|
||||
Usable outcome: The open contract is pinned down with real fixture state before materialization depends on it.
|
||||
|
||||
Output summary directory: `notes/workspace-poc/phase-09-test-workspace-open/`
|
||||
|
||||
Completion checklist:
|
||||
|
||||
- [x] Tasks completed
|
||||
- [x] Acceptance tests satisfied
|
||||
- [x] Independent verification complete
|
||||
- [x] Manual testing complete
|
||||
- [x] Phase complete
|
||||
|
||||
Tasks:
|
||||
|
||||
- [x] 09.1 Add tests for planning-only vs change-scoped mode.
|
||||
- [x] 09.2 Add tests that verify only the expected repo aliases are attached.
|
||||
- [x] 09.3 Add tests for unresolved target paths and unsupported agent/tool combinations.
|
||||
- [x] 09.4 Add CLI e2e coverage for the selected primary demo path.
|
||||
|
||||
Acceptance tests:
|
||||
|
||||
- [x] 09.5 Planning-only open never exposes attached repo roots.
|
||||
- [x] 09.6 Change-scoped open never attaches unrelated repos.
|
||||
- [x] 09.7 Open diagnostics point to `workspace doctor` or the alias that needs repair.
|
||||
- [x] 09.8 Test coverage does not depend on real multi-root writes.
|
||||
|
||||
## Phase 10 - Research Materialization Contract
|
||||
|
||||
Type: Research
|
||||
|
||||
Usable outcome: The materialization contract is explicit before `apply --change --repo` is implemented.
|
||||
|
||||
Output summary directory: `notes/workspace-poc/phase-10-materialization-contract-research/`
|
||||
|
||||
Completion checklist:
|
||||
|
||||
- [x] Tasks completed
|
||||
- [x] Acceptance tests satisfied
|
||||
- [x] Independent verification complete
|
||||
- [x] Manual testing complete
|
||||
- [x] Phase complete
|
||||
|
||||
Tasks:
|
||||
|
||||
- [x] 10.1 Write the research note in `notes/workspace-poc/phase-10-materialization-contract-research/DECISION.md`.
|
||||
- [x] 10.2 Decide the v0 rule for create-only vs refresh, overwrite behavior, rerun behavior, conflict handling, and the minimum metadata written during materialization.
|
||||
- [x] 10.3 Prefer the simplest honest contract for the POC, even if refresh is deferred.
|
||||
|
||||
Acceptance tests:
|
||||
|
||||
- [x] 10.4 The research note chooses one v0 contract and names explicit non-goals.
|
||||
- [x] 10.5 The note defines what counts as a successful materialization.
|
||||
- [x] 10.6 The note defines the expected behavior for repeat `apply` calls.
|
||||
|
||||
## Phase 11 - Target Materialization via `apply`
|
||||
|
||||
Type: Build
|
||||
|
||||
Usable outcome: A selected target can be materialized into its repo with `openspec apply --change <id> --repo <alias>`.
|
||||
|
||||
Output summary directory: `notes/workspace-poc/phase-11-apply-materialization/`
|
||||
|
||||
Completion checklist:
|
||||
|
||||
- [x] Tasks completed
|
||||
- [x] Acceptance tests satisfied
|
||||
- [x] Independent verification complete
|
||||
- [x] Manual testing complete
|
||||
- [x] Phase complete
|
||||
|
||||
Tasks:
|
||||
|
||||
- [x] 11.1 Extend `apply` to understand workspace topology.
|
||||
- [x] 11.2 Materialize only the selected target slice into the target repo.
|
||||
- [x] 11.3 Reuse the same change ID in the target repo.
|
||||
- [x] 11.4 Keep workspace planning artifacts intact after materialization.
|
||||
- [x] 11.5 Make the authority handoff explicit: workspace draft before `apply`, repo-local execution after `apply`.
|
||||
- [x] 11.6 Write the minimum trace metadata needed for later status roll-up.
|
||||
|
||||
Acceptance tests:
|
||||
|
||||
- [x] 11.7 Materialization creates a repo-local change with the same change ID.
|
||||
- [x] 11.8 Only the selected target repo is modified.
|
||||
- [x] 11.9 Untargeted aliases and unknown aliases fail clearly.
|
||||
- [x] 11.10 Repeating `apply` follows the v0 contract from Phase 10.
|
||||
- [x] 11.11 Workspace drafts remain intact after successful materialization.
|
||||
|
||||
## Phase 12 - Validate Materialization
|
||||
|
||||
Type: Test
|
||||
|
||||
Usable outcome: The execution handoff is proven against real repos before status and completion semantics are layered on top.
|
||||
|
||||
Output summary directory: `notes/workspace-poc/phase-12-test-apply-materialization/`
|
||||
|
||||
Completion checklist:
|
||||
|
||||
- [x] Tasks completed
|
||||
- [x] Acceptance tests satisfied
|
||||
- [x] Independent verification complete
|
||||
- [x] Manual testing complete
|
||||
- [x] Phase complete
|
||||
|
||||
Tasks:
|
||||
|
||||
- [x] 12.1 Add unit tests for materialization plan construction and target resolution.
|
||||
- [x] 12.2 Add command tests for apply success, apply failure, and repeat-apply behavior.
|
||||
- [x] 12.3 Add CLI e2e coverage for selective materialization into one repo out of many.
|
||||
- [x] 12.4 Add dirty-workspace coverage for stale aliases and pre-existing target change collisions.
|
||||
|
||||
Acceptance tests:
|
||||
|
||||
- [x] 12.5 The repo-local change ID exactly matches the workspace change ID.
|
||||
- [x] 12.6 Apply never writes to repos outside the selected alias.
|
||||
- [x] 12.7 Apply surfaces collisions and stale-path failures without partial silent success.
|
||||
- [x] 12.8 The happy-path fixture supports `create -> add-repo -> new change -> apply`.
|
||||
|
||||
## Phase 13 - Research Status Roll-Up and Reverse Links
|
||||
|
||||
Type: Research
|
||||
|
||||
Usable outcome: Status semantics are concrete enough to implement without inventing misleading lifecycle labels.
|
||||
|
||||
Output summary directory: `notes/workspace-poc/phase-13-status-research/`
|
||||
|
||||
Completion checklist:
|
||||
|
||||
- [x] Tasks completed
|
||||
- [x] Acceptance tests satisfied
|
||||
- [x] Independent verification complete
|
||||
- [x] Manual testing complete
|
||||
- [x] Phase complete
|
||||
|
||||
Tasks:
|
||||
|
||||
- [x] 13.1 Write the research note in `notes/workspace-poc/phase-13-status-research/DECISION.md`.
|
||||
- [x] 13.2 Define the minimum v0 workspace states and their derivation rules: planned, materialized, in progress, blocked, complete, soft-done, and hard-done.
|
||||
- [x] 13.3 Decide whether repo-local changes need reverse links back to the workspace change in v0.
|
||||
- [x] 13.4 Define the minimum JSON status shape that tests can lock down.
|
||||
|
||||
Acceptance tests:
|
||||
|
||||
- [x] 13.5 The research note gives one precise derivation rule per state.
|
||||
- [x] 13.6 The note defines which states rely on repo-local inspection and which rely on workspace state alone.
|
||||
- [x] 13.7 The note resolves whether reverse links are required, optional, or deferred.
|
||||
|
||||
## Phase 14 - Workspace Status Roll-Up
|
||||
|
||||
Type: Build
|
||||
|
||||
Usable outcome: Running status from the workspace tells the user what is planned, materialized, active, blocked, complete, soft-done, and hard-done.
|
||||
|
||||
Output summary directory: `notes/workspace-poc/phase-14-workspace-status/`
|
||||
|
||||
Completion checklist:
|
||||
|
||||
- [x] Tasks completed
|
||||
- [x] Acceptance tests satisfied
|
||||
- [x] Independent verification complete
|
||||
- [x] Manual testing complete
|
||||
- [x] Phase complete
|
||||
|
||||
Tasks:
|
||||
|
||||
- [x] 14.1 Extend status behavior to recognize workspace topology.
|
||||
- [x] 14.2 Roll up central coordination state plus per-target execution state.
|
||||
- [x] 14.3 Keep output honest and minimal.
|
||||
- [x] 14.4 Add stable JSON output for workspace status.
|
||||
- [x] 14.5 Do not infer more than the underlying workspace and repo-local state can actually support.
|
||||
|
||||
Acceptance tests:
|
||||
|
||||
- [x] 14.6 Workspace status distinguishes planning-only targets from materialized targets.
|
||||
- [x] 14.7 Status can report blocked states for stale repo paths or missing materializations when appropriate.
|
||||
- [x] 14.8 Soft-done only appears when all known coordination and target work is complete.
|
||||
- [x] 14.9 Hard-done only appears after explicit workspace archive/completion in a later phase.
|
||||
- [x] 14.10 JSON status output is stable and free of spinner contamination.
|
||||
|
||||
## Phase 15 - Validate Workspace Status
|
||||
|
||||
Type: Test
|
||||
|
||||
Usable outcome: Roll-up semantics are verified with deterministic scenarios rather than manual interpretation.
|
||||
|
||||
Output summary directory: `notes/workspace-poc/phase-15-test-workspace-status/`
|
||||
|
||||
Completion checklist:
|
||||
|
||||
- [x] Tasks completed
|
||||
- [x] Acceptance tests satisfied
|
||||
- [x] Independent verification complete
|
||||
- [x] Manual testing complete
|
||||
- [x] Phase complete
|
||||
|
||||
Tasks:
|
||||
|
||||
- [x] 15.1 Add pure tests for state derivation logic.
|
||||
- [x] 15.2 Add command tests for workspace-aware status output.
|
||||
- [x] 15.3 Add CLI e2e coverage for mixed states across three repos.
|
||||
- [x] 15.4 Add regression tests for JSON shape and spinner-free output.
|
||||
|
||||
Acceptance tests:
|
||||
|
||||
- [x] 15.5 Status correctly reports a mix of planned, materialized, archived, and blocked targets in one workspace.
|
||||
- [x] 15.6 Status remains readable when one repo is missing or stale.
|
||||
- [x] 15.7 JSON output can be parsed directly by an agent or automation.
|
||||
- [x] 15.8 The dirty fixture supports interruption and resume scenarios.
|
||||
|
||||
## Phase 16 - Workspace Completion and Archive Semantics
|
||||
|
||||
Type: Build
|
||||
|
||||
Usable outcome: The workspace has an explicit top-level completion/hard-done path while repo-local archive remains repo-local.
|
||||
|
||||
Output summary directory: `notes/workspace-poc/phase-16-workspace-archive/`
|
||||
|
||||
Completion checklist:
|
||||
|
||||
- [x] Tasks completed
|
||||
- [x] Acceptance tests satisfied
|
||||
- [x] Independent verification complete
|
||||
- [x] Manual testing complete
|
||||
- [x] Phase complete
|
||||
|
||||
Tasks:
|
||||
|
||||
- [x] 16.1 Decide the minimal command path for explicit workspace completion/archive using the existing archive surface where practical.
|
||||
- [x] 16.2 Preserve repo-local archive behavior and canonical spec ownership.
|
||||
- [x] 16.3 Ensure top-level hard-done is explicit and never implied by repo-local activity alone.
|
||||
- [x] 16.4 Record enough workspace-level completion state for status to report hard-done.
|
||||
|
||||
Acceptance tests:
|
||||
|
||||
- [x] 16.5 Archiving a repo-local change does not automatically archive the workspace change.
|
||||
- [x] 16.6 Workspace hard-done requires explicit top-level user action.
|
||||
- [x] 16.7 Repo-local archive continues to operate against repo-local canonical specs.
|
||||
- [x] 16.8 Mixed repo cadences are allowed without invalidating workspace state.
|
||||
|
||||
## Phase 17 - Validate Workspace Completion and Archive
|
||||
|
||||
Type: Test
|
||||
|
||||
Usable outcome: Completion semantics are proven and do not collapse repo ownership boundaries.
|
||||
|
||||
Output summary directory: `notes/workspace-poc/phase-17-test-workspace-archive/`
|
||||
|
||||
Completion checklist:
|
||||
|
||||
- [x] Tasks completed
|
||||
- [x] Acceptance tests satisfied
|
||||
- [x] Independent verification complete
|
||||
- [x] Manual testing complete
|
||||
- [x] Phase complete
|
||||
|
||||
Tasks:
|
||||
|
||||
- [x] 17.1 Add command and CLI tests for workspace hard-done behavior.
|
||||
- [x] 17.2 Add tests for partial repo archive, staggered repo archive, and explicit workspace archive.
|
||||
- [x] 17.3 Add regression tests to ensure repo-local archive behavior is unchanged outside workspace flows.
|
||||
|
||||
Acceptance tests:
|
||||
|
||||
- [x] 17.4 One repo can archive while another remains in progress without forcing top-level done.
|
||||
- [x] 17.5 Status shows soft-done before hard-done when the documented conditions are met.
|
||||
- [x] 17.6 Existing repo-local archive tests still pass without workspace regressions.
|
||||
|
||||
## Phase 18 - Deferred Research: Shared-Contract Promotion and Stable IDs
|
||||
|
||||
Type: Research
|
||||
|
||||
Usable outcome: Deferred questions are captured cleanly without bloating the POC implementation.
|
||||
|
||||
Output summary directory: `notes/workspace-poc/phase-18-deferred-research/`
|
||||
|
||||
Completion checklist:
|
||||
|
||||
- [x] Tasks completed
|
||||
- [x] Acceptance tests satisfied
|
||||
- [x] Independent verification complete
|
||||
- [x] Manual testing complete
|
||||
- [x] Phase complete
|
||||
|
||||
Tasks:
|
||||
|
||||
- [x] 18.1 Write the research note in `notes/workspace-poc/phase-18-deferred-research/DECISION.md`.
|
||||
- [x] 18.2 Capture the recommended next-step design for shared-contract promotion into canonical owner repos, migration from local alias/path overlays to stable project IDs, and whether any team-shared workspace semantics should exist after the POC.
|
||||
- [x] 18.3 Keep this phase explicitly non-blocking for the working POC.
|
||||
|
||||
Acceptance tests:
|
||||
|
||||
- [x] 18.4 The research note separates deferred concerns from the shipped POC contract.
|
||||
- [x] 18.5 The note identifies which future changes would break current tests or fixture shape.
|
||||
- [x] 18.6 The note names at least one migration seam that preserves backward compatibility.
|
||||
|
||||
## Phase 19 - End-to-End POC Acceptance
|
||||
|
||||
Type: Test
|
||||
|
||||
Usable outcome: The whole POC is proven with a small number of realistic, repeatable scenarios.
|
||||
|
||||
Output summary directory: `notes/workspace-poc/phase-19-e2e-acceptance/`
|
||||
|
||||
Completion checklist:
|
||||
|
||||
- [x] Tasks completed
|
||||
- [x] Acceptance tests satisfied
|
||||
- [x] Independent verification complete
|
||||
- [x] Manual testing complete
|
||||
- [x] Phase complete
|
||||
|
||||
Tasks:
|
||||
|
||||
- [x] 19.1 Add one golden happy-path e2e scenario covering: create workspace, register three repos, create one targeted change, open the change, materialize one repo, inspect status, archive repo-local work, and explicitly complete/archive the workspace.
|
||||
- [x] 19.2 Add one interruption/re-entry scenario covering: an existing workspace, one materialized target, one stale target, and status/doctor output that points to the next action.
|
||||
- [x] 19.3 Add one failure-recovery scenario covering: duplicate aliases, unknown targets, repeat apply, stale repo paths, and partial completion.
|
||||
|
||||
Acceptance tests:
|
||||
|
||||
- [x] 19.4 The happy-path scenario can run end-to-end with real filesystem state and no broad mocks.
|
||||
- [x] 19.5 The interruption scenario can be resumed without reconstructing context manually.
|
||||
- [x] 19.6 The failure-recovery scenario produces actionable errors and no silent corruption.
|
||||
- [x] 19.7 The final suite demonstrates the product promise: plan centrally, execute locally, preserve repo ownership.
|
||||
|
||||
## Phase 20 - PRD Satisfaction Audit
|
||||
|
||||
Type: Test
|
||||
|
||||
Usable outcome: The implementation is checked directly against `WORKSPACE_POC_PRD.md` rather than only against the roadmap or inferred intent.
|
||||
|
||||
Output summary directory: `notes/workspace-poc/phase-20-prd-audit/`
|
||||
|
||||
Completion checklist:
|
||||
|
||||
- [x] Tasks completed
|
||||
- [x] Acceptance tests satisfied
|
||||
- [x] Independent verification complete
|
||||
- [x] Manual testing complete
|
||||
- [x] Phase complete
|
||||
|
||||
Tasks:
|
||||
|
||||
- [x] 20.1 Compare the full implementation, docs, tests, and user-facing behavior against `WORKSPACE_POC_PRD.md`.
|
||||
- [x] 20.2 Identify every unmet, partially met, or ambiguous PRD requirement.
|
||||
- [x] 20.3 Validate that the implementation still respects the key guardrails from the PRD and decision record.
|
||||
- [x] 20.4 If any PRD gaps remain, insert concrete remediation phases immediately after this phase, each with acceptance tests and output directories, before allowing final signoff to proceed.
|
||||
|
||||
Acceptance tests:
|
||||
|
||||
- [x] 20.5 Every meaningful PRD requirement is mapped to implemented behavior, explicit non-goal, or a documented gap.
|
||||
- [x] 20.6 Any remaining gaps result in newly inserted remediation phases, not a vague TODO list.
|
||||
- [x] 20.7 The audit output is concrete enough for a fresh agent session to act on immediately.
|
||||
|
||||
## Phase 21 - Workspace Guidance and Owner Visibility
|
||||
|
||||
Type: Build
|
||||
|
||||
Usable outcome: A fresh user can tell when workspace mode fits the job, capture owner or handoff information per repo, and see that information from the existing workspace surfaces.
|
||||
|
||||
Output summary directory: `notes/workspace-poc/phase-21-workspace-guidance-and-owners/`
|
||||
|
||||
Completion checklist:
|
||||
|
||||
- [x] Tasks completed
|
||||
- [x] Acceptance tests satisfied
|
||||
- [x] Independent verification complete
|
||||
- [x] Manual testing complete
|
||||
- [x] Phase complete
|
||||
|
||||
Tasks:
|
||||
|
||||
- [x] 21.1 Extend committed workspace repo metadata to capture optional owner or handoff information without storing machine-specific paths.
|
||||
- [x] 21.2 Add a backward-compatible CLI path to record or update owner or handoff information for a registered repo alias.
|
||||
- [x] 21.3 Surface owner or handoff information anywhere the workspace already shows affected repos and next actions, at minimum workspace-aware `status` and `workspace open`.
|
||||
- [x] 21.4 Add shipped user-facing guidance that explains when to use workspace mode versus stay repo-local, the supported end-to-end CLI flow, and how to re-enter or hand off an in-flight workspace change.
|
||||
|
||||
Acceptance tests:
|
||||
|
||||
- [x] 21.5 Fresh users can discover from shipped docs or help when workspace mode is the right tool and what the supported CLI flow is.
|
||||
- [x] 21.6 When owner or handoff information is configured, workspace status and open surfaces expose it without leaking local paths into committed metadata.
|
||||
- [x] 21.7 Existing workspaces remain valid and readable when owner or handoff information is absent.
|
||||
|
||||
## Phase 22 - Validate Guidance and Owner Visibility
|
||||
|
||||
Type: Test
|
||||
|
||||
Usable outcome: Guidance and owner or handoff visibility are proven on real workspace state and remain backward-compatible with the shipped POC.
|
||||
|
||||
Output summary directory: `notes/workspace-poc/phase-22-test-workspace-guidance-and-owners/`
|
||||
|
||||
Completion checklist:
|
||||
|
||||
- [x] Tasks completed
|
||||
- [x] Acceptance tests satisfied
|
||||
- [x] Independent verification complete
|
||||
- [x] Manual testing complete
|
||||
- [x] Phase complete
|
||||
|
||||
Tasks:
|
||||
|
||||
- [x] 22.1 Add unit, command, and CLI coverage for owner or handoff metadata plus the updated docs or help surface.
|
||||
- [x] 22.2 Verify older workspace fixtures and workspaces without owner or handoff metadata still pass unchanged.
|
||||
- [x] 22.3 Run manual CLI checks for docs or help, `workspace open`, and workspace-aware `status` from a fresh workspace.
|
||||
|
||||
Acceptance tests:
|
||||
|
||||
- [x] 22.4 Shipped docs or help no longer require the PRD or roadmap to explain when workspace mode is appropriate.
|
||||
- [x] 22.5 Workspace text and JSON surfaces show configured owner or handoff information consistently.
|
||||
- [x] 22.6 Existing ownerless workspaces and the Phase 19 acceptance flow continue to pass.
|
||||
|
||||
## Phase 23 - Workspace Target Set Adjustment
|
||||
|
||||
Type: Build
|
||||
|
||||
Usable outcome: Users can adjust the target set on a workspace change after creation without manual file edits or silent authority drift.
|
||||
|
||||
Output summary directory: `notes/workspace-poc/phase-23-workspace-target-set-adjustment/`
|
||||
|
||||
Completion checklist:
|
||||
|
||||
- [x] Tasks completed
|
||||
- [x] Acceptance tests satisfied
|
||||
- [x] Independent verification complete
|
||||
- [x] Manual testing complete
|
||||
- [x] Phase complete
|
||||
|
||||
Tasks:
|
||||
|
||||
- [x] 23.1 Add a minimal explicit command path to add or remove target aliases from an existing workspace change.
|
||||
- [x] 23.2 Keep workspace change metadata, per-target draft artifacts, and workspace registry validation coherent when targets are added or removed.
|
||||
- [x] 23.3 Define and implement safe guardrails for removing a target that has already been materialized or otherwise moved into repo-local execution.
|
||||
- [x] 23.4 Update workspace `open`, `apply`, and workspace-aware `status` to respect the adjusted target set.
|
||||
|
||||
Acceptance tests:
|
||||
|
||||
- [x] 23.5 Adding a target updates the workspace change metadata and scaffolds the new per-target draft slice.
|
||||
- [x] 23.6 Removing an unmaterialized target updates the workspace cleanly without corrupting other targets.
|
||||
- [x] 23.7 Removing or mutating a materialized target fails or requires an explicit documented safety path instead of silently breaking authority handoff.
|
||||
|
||||
## Phase 24 - Validate Target Set Adjustment
|
||||
|
||||
Type: Test
|
||||
|
||||
Usable outcome: Target-set edits behave safely under real workspace conditions and do not regress the shipped POC flow.
|
||||
|
||||
Output summary directory: `notes/workspace-poc/phase-24-test-workspace-target-set-adjustment/`
|
||||
|
||||
Completion checklist:
|
||||
|
||||
- [x] Tasks completed
|
||||
- [x] Acceptance tests satisfied
|
||||
- [x] Independent verification complete
|
||||
- [x] Manual testing complete
|
||||
- [x] Phase complete
|
||||
|
||||
Tasks:
|
||||
|
||||
- [x] 24.1 Add unit, command, and CLI coverage for target-add and target-remove behavior, including materialized-target guardrails.
|
||||
- [x] 24.2 Run manual re-entry, `status`, `workspace open`, and `apply` checks after target-set edits in a fresh workspace.
|
||||
- [x] 24.3 Re-run the workspace acceptance slice to confirm target adjustment does not regress the existing happy path or interruption flow.
|
||||
|
||||
Acceptance tests:
|
||||
|
||||
- [x] 24.4 Adjusted target sets are reflected consistently in workspace metadata, `workspace open`, `apply`, and workspace-aware `status`.
|
||||
- [x] 24.5 Guardrails prevent silent divergence for already materialized targets.
|
||||
- [x] 24.6 The existing Phase 19 acceptance scenario still passes after target-set support lands.
|
||||
|
||||
## Phase 25 - Final PRD Recheck and Signoff
|
||||
|
||||
Type: Test
|
||||
|
||||
Usable outcome: After any remediation phases have run, the codebase is rechecked against the PRD and the POC can be considered complete.
|
||||
|
||||
Output summary directory: `notes/workspace-poc/phase-25-prd-signoff/`
|
||||
|
||||
Completion checklist:
|
||||
|
||||
- [x] Tasks completed
|
||||
- [x] Acceptance tests satisfied
|
||||
- [x] Independent verification complete
|
||||
- [x] Manual testing complete
|
||||
- [x] Phase complete
|
||||
|
||||
Tasks:
|
||||
|
||||
- [x] 25.1 Re-run the PRD satisfaction check after all remediation phases are complete.
|
||||
- [x] 25.2 Confirm the final implementation, documentation, and tests satisfy the PRD.
|
||||
- [x] 25.3 Confirm the roadmap itself has no incomplete required phases left behind.
|
||||
- [x] 25.4 Produce a final signoff summary that states whether the POC is complete and what residual risks remain.
|
||||
|
||||
Acceptance tests:
|
||||
|
||||
- [x] 25.5 The final signoff references `WORKSPACE_POC_PRD.md` directly and confirms whether it is satisfied.
|
||||
- [x] 25.6 If the PRD is still not satisfied, the phase does not sign off and instead inserts further remediation phases before trying again.
|
||||
- [x] 25.7 The final signoff is explicit about any residual risks, but it does not leave known fixable PRD gaps unresolved.
|
||||
|
||||
## Recommended First Shipping Slice
|
||||
|
||||
If the POC needs the smallest credible milestone before full roll-up and completion semantics, ship through Phase 12:
|
||||
|
||||
- test harness
|
||||
- workspace create
|
||||
- repo registry + doctor
|
||||
- targeted workspace changes
|
||||
- minimum researched `workspace open`
|
||||
- create-only materialization through `apply`
|
||||
|
||||
That is the first point where the product is honest for real cross-repo work. Phases 13 through 25 then harden status, completion semantics, end-to-end resilience, PRD completeness, and final signoff.
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,293 @@
|
||||
# Workspace POC PRD
|
||||
|
||||
- Status: Signed Off
|
||||
- Date: 2026-04-17
|
||||
- Audience: OpenSpec maintainers and future implementers
|
||||
- Derived from: [WORKSPACE_POC_DECISION_RECORD.md](/Users/tabishbidiwale/fission/repos/openspec/WORKSPACE_POC_DECISION_RECORD.md)
|
||||
|
||||
## Summary
|
||||
|
||||
The Workspace POC gives OpenSpec a lightweight way to coordinate work that spans multiple repositories without forcing planning into a single repo or introducing a separate planning primitive for users to learn.
|
||||
|
||||
A workspace is a persistent coordination home. Inside it, users create feature-scoped changes, plan the work once, and then materialize repo-specific execution artifacts into the affected repos when implementation is ready to begin.
|
||||
|
||||
The POC is intentionally opinionated:
|
||||
|
||||
- planning is centralized in the workspace
|
||||
- canonical specs remain in the owning repo
|
||||
- repo-local execution remains repo-local
|
||||
- the primary user-facing primitive stays `change`
|
||||
- the existing `spec-driven` methodology is reused rather than forked into a separate workspace schema
|
||||
|
||||
This document describes what we are building for the POC. It does not try to break the work into implementation phases yet.
|
||||
|
||||
## Problem
|
||||
|
||||
OpenSpec currently behaves like a single-root tool:
|
||||
|
||||
- commands assume one local root
|
||||
- changes are authored locally under one repo
|
||||
- specs and delta specs are resolved locally
|
||||
- `apply` and `archive` are repo-local lifecycle steps
|
||||
|
||||
That works for normal single-repo use, but it breaks down when one feature spans multiple services, clients, or owner repos.
|
||||
|
||||
Users need one place to:
|
||||
|
||||
- write a single proposal and design
|
||||
- see the full cross-repo change
|
||||
- assign and track repo-specific work
|
||||
- reason about shared behavior across repos
|
||||
|
||||
At the same time, repos still need to remain the source of truth for:
|
||||
|
||||
- canonical specs
|
||||
- implementation work
|
||||
- review and shipping
|
||||
- archive semantics
|
||||
|
||||
The product problem is to provide centralized planning without collapsing repo ownership.
|
||||
|
||||
## Who This Is For
|
||||
|
||||
The POC is aimed at users coordinating cross-boundary work, including:
|
||||
|
||||
- an engineer changing behavior across multiple repos
|
||||
- a lead or staff engineer coordinating a feature across teams
|
||||
- a team that needs one planning surface but still executes in separate repos
|
||||
|
||||
## When Users Reach For Workspace
|
||||
|
||||
Users should reach for a workspace when repo-local OpenSpec stops being an honest representation of the work.
|
||||
|
||||
Typical trigger situations:
|
||||
|
||||
- one feature spans two or more repos
|
||||
- the canonical spec owner is different from one or more implementation repos
|
||||
- different repos or teams need to move on different cadences
|
||||
- one person needs to coordinate work that will later be handed off to several repo owners
|
||||
- the user needs one place to pause and resume a cross-repo effort without reconstructing the full plan from scattered notes
|
||||
|
||||
## Jobs To Be Done
|
||||
|
||||
### Functional Jobs
|
||||
|
||||
Users hire the workspace POC to:
|
||||
|
||||
- start one cross-repo change from a neutral planning home
|
||||
- identify which repos are affected
|
||||
- author shared planning artifacts once
|
||||
- break the work into repo-specific slices for execution
|
||||
- materialize repo-local change artifacts when implementation should begin
|
||||
- track overall progress without losing repo ownership boundaries
|
||||
- resume a cross-repo change later and quickly understand what is planned, materialized, in progress, blocked, complete, or archived
|
||||
|
||||
### Social Jobs
|
||||
|
||||
Users also hire the workspace POC to:
|
||||
|
||||
- make the full cross-repo change legible to repo owners, reviewers, and leads
|
||||
- hand off the right slice of work to each repo owner without duplicating planning docs
|
||||
- show what is planned centrally versus what is already executing locally
|
||||
- reduce coordination overhead that would otherwise live in Slack threads, meetings, and ad hoc documents
|
||||
|
||||
### Emotional Jobs
|
||||
|
||||
The workspace POC should help users feel confident that:
|
||||
|
||||
- there is one clear planning home for the overall change
|
||||
- canonical repo ownership is preserved
|
||||
- materialization will not create confusing dual authority
|
||||
- they can tell what is authoritative at each step
|
||||
- they can recover safely from interruption, partial rollout, or divergence between workspace drafts and repo-local execution
|
||||
|
||||
### Adoption And Operations Jobs
|
||||
|
||||
For teams using this repeatedly, the workspace POC should also support:
|
||||
|
||||
- a repeatable way to start cross-repo work
|
||||
- a clear way to decide when to use workspace mode versus stay repo-local
|
||||
- onboarding another engineer into an in-flight cross-repo change
|
||||
- re-entering an existing workspace after time away
|
||||
- adjusting targets and continuing even when some repos are not ready at the same time
|
||||
|
||||
## Product Goals
|
||||
|
||||
The Workspace POC should:
|
||||
|
||||
1. Provide a credible cross-repo coordination experience for real work.
|
||||
2. Make the workspace a persistent coordination home rather than a disposable feature folder.
|
||||
3. Keep planning centralized while preserving canonical spec ownership in repos.
|
||||
4. Reuse the existing `change` primitive and `spec-driven` methodology.
|
||||
5. Minimize disruption to existing repo-local OpenSpec workflows.
|
||||
6. Support a simple, explicit CLI flow for creating workspaces, registering repos, opening a change, and materializing repo-local work.
|
||||
7. Avoid leaking machine-specific repo paths into committed workspace state.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
The POC does not attempt to solve the full long-term workspace model.
|
||||
|
||||
Out of scope:
|
||||
|
||||
- a fully multi-root-aware CLI across every command
|
||||
- a new top-level `initiative` primitive
|
||||
- a separate workspace-only methodology schema
|
||||
- stable remote repo identifiers or shared project IDs
|
||||
- automatic escalation from local work into a workspace
|
||||
- a full sync engine between workspace drafts and repo-local changes
|
||||
- final governance for shared-contract ownership
|
||||
- arbitrary user-chosen workspace locations as the default v0 behavior
|
||||
|
||||
## Product Shape
|
||||
|
||||
### Workspace
|
||||
|
||||
A workspace is a persistent coordination root used for cross-repo planning.
|
||||
|
||||
For the POC:
|
||||
|
||||
- it lives in a managed location by default
|
||||
- workspace metadata lives under `.openspec/`
|
||||
- the workspace does not add an extra inner `openspec/` directory
|
||||
- the workspace can contain many feature-scoped changes over time
|
||||
|
||||
### Workspace Change
|
||||
|
||||
A workspace change is the central planning object for one cross-repo feature or initiative-sized piece of work.
|
||||
|
||||
For the POC:
|
||||
|
||||
- users still think in terms of `change`
|
||||
- a workspace change records its target repos explicitly
|
||||
- proposal, design, coordination tasks, and per-target draft work live in the workspace until materialization
|
||||
|
||||
### Target Repos
|
||||
|
||||
Target repos are registered in the workspace by alias.
|
||||
|
||||
For the POC:
|
||||
|
||||
- stable repo aliases are stored in committed workspace metadata
|
||||
- machine-specific absolute paths are stored only in a gitignored local overlay
|
||||
- repo attachment should be change-scoped by default, not workspace-wide
|
||||
|
||||
### Repo-Local Changes
|
||||
|
||||
Repo-local changes are the execution artifacts created from a workspace change.
|
||||
|
||||
For the POC:
|
||||
|
||||
- a materialized repo-local change reuses the same change ID as the workspace change by default
|
||||
- repo-local execution remains local to that repo
|
||||
- repo-local archive remains local to that repo
|
||||
|
||||
## Core Principles
|
||||
|
||||
### Centralize The View, Not The Truth
|
||||
|
||||
The workspace is the shared planning surface. It is not the permanent home of canonical specs or repo execution state.
|
||||
|
||||
### Methodology And Topology Stay Separate
|
||||
|
||||
The POC reuses `spec-driven`. Workspace behavior is a topology concern, not a new methodology family.
|
||||
|
||||
### Planning First, Materialization Second
|
||||
|
||||
Users should be able to author the cross-repo plan in one place before copying the relevant slice into a repo for execution.
|
||||
|
||||
### Clear Authority Handoff
|
||||
|
||||
Before materialization, the workspace target slice is the planning truth for that repo.
|
||||
|
||||
After a successful `apply --change <id> --repo <alias>`, the repo-local change becomes the execution truth for that repo.
|
||||
|
||||
### Manual Completion At The Top Level
|
||||
|
||||
A workspace change becomes:
|
||||
|
||||
- soft-done when all known coordination work and tracked target work are complete
|
||||
- hard-done only when the user manually archives the workspace change
|
||||
|
||||
## User Experience
|
||||
|
||||
The intended POC flow is:
|
||||
|
||||
1. A user creates a workspace using the normal OpenSpec setup path.
|
||||
2. The user registers repo aliases against local repo paths.
|
||||
3. The user creates a workspace change with explicit targets.
|
||||
4. Planning happens centrally in the workspace:
|
||||
- proposal
|
||||
- design
|
||||
- coordination tasks
|
||||
- per-target draft tasks
|
||||
- per-target draft delta specs
|
||||
5. When execution should begin in a repo, the user runs `openspec apply --change <id> --repo <alias>`.
|
||||
6. OpenSpec materializes the selected repo’s local change using the same change ID.
|
||||
7. Repo-local implementation and archive proceed in that repo.
|
||||
8. The workspace continues to show overall coordination and completion state.
|
||||
|
||||
This is meant to feel like one change with multiple execution surfaces, not like separate unrelated changes stitched together manually.
|
||||
|
||||
## POC Command Surface
|
||||
|
||||
The minimum command shape for the POC is:
|
||||
|
||||
- `openspec workspace create <name>`
|
||||
- `openspec workspace add-repo <alias> <path>`
|
||||
- `openspec workspace doctor`
|
||||
- `openspec new change <id> --targets <a,b,c>`
|
||||
- `openspec workspace open --change <id> [--agent <tool>]`
|
||||
- `openspec apply --change <id> --repo <alias>`
|
||||
|
||||
These commands are enough to support:
|
||||
|
||||
- persistent workspace creation
|
||||
- repo registration and validation
|
||||
- explicit targeted change creation
|
||||
- change-scoped agent opening
|
||||
- deterministic materialization into a target repo
|
||||
|
||||
## Agent Story
|
||||
|
||||
The POC should optimize for the cleanest demo path rather than promise identical behavior across all tools.
|
||||
|
||||
Current expectation:
|
||||
|
||||
- Claude Code is the headline multi-root demo path
|
||||
- Codex is secondary if it remains straightforward
|
||||
- Copilot is partial or manual support, not the primary story
|
||||
|
||||
Because agent multi-root write behavior is uneven, `openspec apply --change --repo` is the safest POC default for moving from planning into repo execution.
|
||||
|
||||
## Success Criteria
|
||||
|
||||
The POC is successful if users can:
|
||||
|
||||
- recognize when workspace mode is the right tool for the job
|
||||
- create one canonical plan for a cross-repo change without forcing it into a dishonest home repo
|
||||
- identify affected repos, owners, and next actions from one planning surface
|
||||
- hand off repo-specific work cleanly without duplicating the same plan across multiple repos or side documents
|
||||
- understand which work is planned, materialized, in progress, blocked, complete, and archived
|
||||
- resume an interrupted cross-repo change without reconstructing context from Slack, PRs, or notes
|
||||
- preserve canonical spec ownership in repos while still coordinating the overall effort centrally
|
||||
- trust what is authoritative at each stage of the workflow
|
||||
- avoid committing local absolute repo paths into shared state
|
||||
|
||||
## Open Questions
|
||||
|
||||
These are intentionally left open for roadmap and implementation planning:
|
||||
|
||||
- Should materialization be create-only at first, or support explicit refresh?
|
||||
- If re-materialization exists, what can be overwritten and what must be preserved?
|
||||
- How should workspace status roll up repo-local progress?
|
||||
- Should repo-local changes keep a reverse link back to the workspace change?
|
||||
- What is the minimum supported `workspace open --change` behavior in v0?
|
||||
- How should shared contract drafts be promoted into canonical owner repos?
|
||||
|
||||
## Appendix: Working Mental Model
|
||||
|
||||
The POC is built around one simple idea:
|
||||
|
||||
> Plan centrally, execute locally, preserve repo ownership.
|
||||
|
||||
That is the product promise the roadmap should now flesh out.
|
||||
@@ -0,0 +1,454 @@
|
||||
# Workspace Reimplementation Direction
|
||||
|
||||
Date: 2026-04-30
|
||||
|
||||
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
|
||||
create workspace
|
||||
-> add repos
|
||||
-> open workspace
|
||||
-> explore across repos
|
||||
-> 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 create an OpenSpec workspace.
|
||||
I open it with my agent.
|
||||
The agent can see the registered repos.
|
||||
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 workspace overlays.
|
||||
I need to manage target metadata separately from proposal files.
|
||||
```
|
||||
|
||||
The core product rule is:
|
||||
|
||||
```text
|
||||
Repository visibility is not change commitment.
|
||||
```
|
||||
|
||||
Registered repos are the workspace working set. Creating a change is a planning commitment. Applying a change is an implementation workflow.
|
||||
|
||||
## Build Order
|
||||
|
||||
### 1. Workspace Creation
|
||||
|
||||
First make workspace creation boring and solid.
|
||||
|
||||
User goal:
|
||||
|
||||
```text
|
||||
Create a place where cross-repo planning lives.
|
||||
```
|
||||
|
||||
Expected surface:
|
||||
|
||||
```bash
|
||||
openspec workspace create my-workspace
|
||||
openspec workspace add-repo openspec /path/to/openspec
|
||||
openspec workspace add-repo landing /path/to/openspec-landing
|
||||
```
|
||||
|
||||
Expected outcome:
|
||||
|
||||
```text
|
||||
workspace/
|
||||
AGENTS.md
|
||||
changes/
|
||||
.openspec-workspace/
|
||||
```
|
||||
|
||||
Product decisions:
|
||||
|
||||
- Use `.openspec-workspace/`, not `.openspec/`, for workspace metadata.
|
||||
- Keep `changes/` visible at the workspace root.
|
||||
- Treat registered repos as the workspace working set.
|
||||
- Make `doctor` show human-readable repo names and resolved paths.
|
||||
|
||||
Defer:
|
||||
|
||||
- Branches.
|
||||
- Worktrees.
|
||||
- Apply.
|
||||
- Archive.
|
||||
- Complex target lifecycle.
|
||||
|
||||
Done when a user can create a workspace, register repos, and run `doctor` to see exactly what OpenSpec knows.
|
||||
|
||||
### 2. Workspace Open
|
||||
|
||||
Next make the workspace openable in the way users expect.
|
||||
|
||||
User goal:
|
||||
|
||||
```text
|
||||
Open this multi-repo working set 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 registered repos.
|
||||
- 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 root
|
||||
registered repo A
|
||||
registered repo B
|
||||
```
|
||||
|
||||
For Claude and Codex, attach the registered repo 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 registered repos.
|
||||
|
||||
### 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 registered repos, but do not implement yet.
|
||||
```
|
||||
|
||||
Agent behavior:
|
||||
|
||||
- Understand it is in workspace mode.
|
||||
- Inspect registered repos.
|
||||
- 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.
|
||||
- Registered repo 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 create
|
||||
-> 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 create the workspace?
|
||||
2. Can I see my repos?
|
||||
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 = central planning source of truth
|
||||
registered repos = visible working set
|
||||
proposal = scoped planning commitment
|
||||
repo target = one affected repo 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.
|
||||
```
|
||||
@@ -0,0 +1,316 @@
|
||||
|
||||
---
|
||||
|
||||
## Request `request_79caa9a0-bb0e-4cb4-bf91-4ce6456ad26a`
|
||||
|
||||
**Timestamp:** 2026-04-28 11:59:49 AEST
|
||||
|
||||
**Agent:** GitHubCopilot
|
||||
|
||||
### User
|
||||
|
||||
Follow instructions in [SKILL.md](file:///Users/tabishbidiwale/.local/share/openspec/workspaces/poc-workspace/.agents/skills/openspec-explore/SKILL.md).
|
||||
How could we get the docs from openspec repo to show up in the landing page
|
||||
|
||||
### Assistant / Events
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Request `request_79caa9a0-bb0e-4cb4-bf91-4ce6456ad26a`
|
||||
|
||||
**Timestamp:** 2026-04-28 11:59:49 AEST
|
||||
|
||||
**Agent:** GitHubCopilot
|
||||
|
||||
### User
|
||||
|
||||
Follow instructions in [SKILL.md](file:///Users/tabishbidiwale/.local/share/openspec/workspaces/poc-workspace/.agents/skills/openspec-explore/SKILL.md).
|
||||
How could we get the docs from openspec repo to show up in the landing page
|
||||
|
||||
### Assistant / Events
|
||||
|
||||
I'm in explore mode. Let me think through this with you.
|
||||
|
||||
First, let me understand what you're working with:
|
||||
|
||||
**The setup:**
|
||||
- You have
|
||||
|
||||
---
|
||||
|
||||
## Request `request_79caa9a0-bb0e-4cb4-bf91-4ce6456ad26a`
|
||||
|
||||
**Timestamp:** 2026-04-28 11:59:49 AEST
|
||||
|
||||
**Agent:** GitHubCopilot
|
||||
|
||||
### User
|
||||
|
||||
Follow instructions in [SKILL.md](file:///Users/tabishbidiwale/.local/share/openspec/workspaces/poc-workspace/.agents/skills/openspec-explore/SKILL.md).
|
||||
How could we get the docs from openspec repo to show up in the landing page
|
||||
|
||||
### Assistant / Events
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Request `request_79caa9a0-bb0e-4cb4-bf91-4ce6456ad26a`
|
||||
|
||||
**Timestamp:** 2026-04-28 11:59:49 AEST
|
||||
|
||||
**Agent:** GitHubCopilot
|
||||
|
||||
### User
|
||||
|
||||
Follow instructions in [SKILL.md](file:///Users/tabishbidiwale/.local/share/openspec/workspaces/poc-workspace/.agents/skills/openspec-explore/SKILL.md).
|
||||
How could we get the docs from openspec repo to show up in the landing page
|
||||
|
||||
### Assistant / Events
|
||||
|
||||
repo (the core product/system)
|
||||
- You have `/openspec-landing` (the landing page)
|
||||
- You want docs from openspec to appear on the landing page
|
||||
|
||||
**Before I dig into the code, some clarifying questions:**
|
||||
|
||||
1. **What docs are we talking about?** Are these:
|
||||
- API documentation (auto-generated from code)?
|
||||
- Guides and tutorials (hand-written markdown)?
|
||||
- Specs and architecture docs?
|
||||
- All of the above?
|
||||
|
||||
2. **How should they appear on the landing page?**
|
||||
- Embedded directly (copy/sync)?
|
||||
- Linked to (openspec repo becomes the source of truth)?
|
||||
- A combination (some docs embedded, some linked)?
|
||||
|
||||
3. **Single source of truth?** Should the landing page reflect the *current* state of docs in openspec automatically, or is it okay if they drift?
|
||||
|
||||
4. **User experience angle**: When someone lands on the landing page, what should they see/do? Is the landing page meant to be:
|
||||
- An entry point that says "here's what this is" + links to full docs elsewhere?
|
||||
- Self-contained docs that happen to be synced from the repo?
|
||||
- Something else?
|
||||
|
||||
Let me also check what's actually in these repos right now - that'll ground the thinking:
|
||||
|
||||
```bash
|
||||
# What docs exist in openspec?
|
||||
find /Users/tabishbidiwale/fission/repos/openspec -name "*.md" -type f | head -20
|
||||
|
||||
# What's the landing page structure?
|
||||
ls -la /Users/tabishbidiwale/fission/repos/openspec-landing/
|
||||
```
|
||||
|
||||
Once I see the actual structure and understand your intent, the solution becomes clearer. Could be anything from a static build step that copies markdown, to a dynamic system that fetches docs at runtime, to a link-and-let-them-navigate approach.
|
||||
|
||||
What resonates most with how you're thinking about this?
|
||||
|
||||
---
|
||||
|
||||
## Request `request_b6e88cd6-d531-43eb-904b-6225c3981934`
|
||||
|
||||
**Timestamp:** 2026-04-28 12:00:32 AEST
|
||||
|
||||
**Agent:** agent
|
||||
|
||||
### User
|
||||
|
||||
go search and ground before asking questions
|
||||
|
||||
### Assistant / Events
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Request `request_b6e88cd6-d531-43eb-904b-6225c3981934`
|
||||
|
||||
**Timestamp:** 2026-04-28 12:00:32 AEST
|
||||
|
||||
**Agent:** agent
|
||||
|
||||
### User
|
||||
|
||||
go search and ground before asking questions
|
||||
|
||||
### Assistant / Events
|
||||
|
||||
|
||||
**Visible Thinking**
|
||||
|
||||
The user is right - I should explore the codebase first before asking clarifying questions. They're in explore mode and I should ground my thinking in what actually exists. Let me search and read the actual structure of both repos.
|
||||
|
||||
Let me:
|
||||
1. Look at the docs in the openspec repo
|
||||
2. Look at the structure of openspec-landing
|
||||
3. See if there's any existing mechanism for sharing docs
|
||||
4. Then come back with grounded thinking
|
||||
|
||||
I should use tools to explore the codebase first.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Request `request_b6e88cd6-d531-43eb-904b-6225c3981934`
|
||||
|
||||
**Timestamp:** 2026-04-28 12:00:32 AEST
|
||||
|
||||
**Agent:** agent
|
||||
|
||||
### User
|
||||
|
||||
go search and ground before asking questions
|
||||
|
||||
### Assistant / Events
|
||||
|
||||
|
||||
**Tool Call** `run_in_terminal`
|
||||
|
||||
```bash
|
||||
find /Users/tabishbidiwale/fission/repos/openspec/docs -type f -name "*.md" | head -20
|
||||
```
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Request `request_d515673c-cd78-483d-b0c7-139dfbe0f4b7`
|
||||
|
||||
**Timestamp:** 2026-04-28 12:09:16 AEST
|
||||
|
||||
**Agent:** agent
|
||||
|
||||
### User
|
||||
|
||||
choose best defaults and create a change proposal
|
||||
|
||||
### Assistant / Events
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Request `request_c020834d-3218-4ba4-b3ac-0fe8d8a292db`
|
||||
|
||||
**Timestamp:** 2026-04-28 12:32:26 AEST
|
||||
|
||||
**Agent:** agent
|
||||
|
||||
### User
|
||||
|
||||
what was this session id?
|
||||
|
||||
### Assistant / Events
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Request `request_c020834d-3218-4ba4-b3ac-0fe8d8a292db`
|
||||
|
||||
**Timestamp:** 2026-04-28 12:32:26 AEST
|
||||
|
||||
**Agent:** agent
|
||||
|
||||
### User
|
||||
|
||||
what was this session id?
|
||||
|
||||
### Assistant / Events
|
||||
|
||||
|
||||
**Visible Thinking**
|
||||
|
||||
The user is asking about the session ID. I need to check what session ID was used or assigned during this exploration/proposal creation. Let me look back at what happened.
|
||||
|
||||
Looking at the context, I don't see a specific session ID mentioned anywhere. The user might be asking about:
|
||||
1. The OpenSpec change ID (which is "integrate-docs")
|
||||
2. Some kind of terminal session ID
|
||||
3. Some other identifier
|
||||
|
||||
The change we created is called "integrate-docs" and it's located at:
|
||||
`/Users/tabishbidiwale/.local/share/openspec/workspaces/poc-workspace/changes/integrate-docs/`
|
||||
|
||||
I should clarify what they're asking about. The most likely answer is the change name/ID, which is "integrate-docs".
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Request `request_c020834d-3218-4ba4-b3ac-0fe8d8a292db`
|
||||
|
||||
**Timestamp:** 2026-04-28 12:32:26 AEST
|
||||
|
||||
**Agent:** agent
|
||||
|
||||
### User
|
||||
|
||||
what was this session id?
|
||||
|
||||
### Assistant / Events
|
||||
|
||||
The change ID is **`integrate-docs`**.
|
||||
|
||||
It's located at:
|
||||
```
|
||||
/Users/tabishbidiwale/.local/share/openspec/workspaces/poc-workspace/changes/integrate-docs/
|
||||
```
|
||||
|
||||
You can reference it in commands with `--change integrate-docs`.
|
||||
|
||||
---
|
||||
|
||||
## Request `request_632f186b-58f8-4301-8b64-a29b5005d8bf`
|
||||
|
||||
**Timestamp:** 2026-04-28 12:32:41 AEST
|
||||
|
||||
**Agent:** agent
|
||||
|
||||
### User
|
||||
|
||||
nah chat session ID
|
||||
|
||||
### Assistant / Events
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Request `request_632f186b-58f8-4301-8b64-a29b5005d8bf`
|
||||
|
||||
**Timestamp:** 2026-04-28 12:32:41 AEST
|
||||
|
||||
**Agent:** agent
|
||||
|
||||
### User
|
||||
|
||||
nah chat session ID
|
||||
|
||||
### Assistant / Events
|
||||
|
||||
|
||||
**Visible Thinking**
|
||||
|
||||
The user is asking for the chat session ID - not the OpenSpec change ID. They want to know the session ID for this conversation.
|
||||
|
||||
However, I don't have a built-in way to retrieve the chat session ID from the context provided to me. The context includes information about the workspace, files, and environment, but not the chat session ID.
|
||||
|
||||
I should be honest that I don't have access to that information.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Request `request_632f186b-58f8-4301-8b64-a29b5005d8bf`
|
||||
|
||||
**Timestamp:** 2026-04-28 12:32:41 AEST
|
||||
|
||||
**Agent:** agent
|
||||
|
||||
### User
|
||||
|
||||
nah chat session ID
|
||||
|
||||
### Assistant / Events
|
||||
|
||||
I don't have access to the chat session ID from my context. That information isn't available to me in the tools and context I can see. You might be able to find it in your chat client's UI or logs.
|
||||
File diff suppressed because it is too large
Load Diff
+73
-21
@@ -1,6 +1,6 @@
|
||||
# CLI Reference
|
||||
|
||||
The OpenSpec CLI (`openspec`) provides terminal commands for project setup, validation, status inspection, and management. These commands complement the AI slash commands (like `/opsx:new`) documented in [Commands](commands.md).
|
||||
The OpenSpec CLI (`openspec`) provides terminal commands for project setup, validation, status inspection, and management. These commands complement the AI slash commands (like `/opsx:propose`) documented in [Commands](commands.md).
|
||||
|
||||
## Summary
|
||||
|
||||
@@ -11,6 +11,7 @@ The OpenSpec CLI (`openspec`) provides terminal commands for project setup, vali
|
||||
| **Validation** | `validate` | Check changes and specs for issues |
|
||||
| **Lifecycle** | `archive` | Finalize completed changes |
|
||||
| **Workflow** | `status`, `instructions`, `templates`, `schemas` | Artifact-driven workflow support |
|
||||
| **Workspace** | `workspace setup`, `workspace list`, `workspace create`, `workspace add-repo`, `workspace update-repo`, `workspace targets`, `workspace doctor`, `workspace open` | Coordinate cross-repo planning without collapsing repo ownership |
|
||||
| **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 |
|
||||
@@ -67,6 +68,8 @@ These options work with all commands:
|
||||
|
||||
Initialize OpenSpec in your project. Creates the folder structure and configures AI tool integrations.
|
||||
|
||||
Default behavior uses global config defaults: profile `core`, delivery `both`, workflows `propose, explore, apply, archive`.
|
||||
|
||||
```
|
||||
openspec init [path] [options]
|
||||
```
|
||||
@@ -83,8 +86,11 @@ openspec init [path] [options]
|
||||
|--------|-------------|
|
||||
| `--tools <list>` | Configure AI tools non-interactively. Use `all`, `none`, or comma-separated list |
|
||||
| `--force` | Auto-cleanup legacy files without prompting |
|
||||
| `--profile <profile>` | Override global profile for this init run (`core` or `custom`) |
|
||||
|
||||
**Supported tools:** `amazon-q`, `antigravity`, `auggie`, `claude`, `cline`, `codex`, `codebuddy`, `continue`, `costrict`, `crush`, `cursor`, `factory`, `gemini`, `github-copilot`, `iflow`, `kilocode`, `opencode`, `qoder`, `qwen`, `roocode`, `windsurf`
|
||||
`--profile custom` uses whatever workflows are currently selected in global config (`openspec config profile`).
|
||||
|
||||
**Supported tool IDs (`--tools`):** `amazon-q`, `antigravity`, `auggie`, `claude`, `cline`, `codex`, `codebuddy`, `continue`, `costrict`, `crush`, `cursor`, `factory`, `gemini`, `github-copilot`, `iflow`, `kilocode`, `kiro`, `opencode`, `pi`, `qoder`, `qwen`, `roocode`, `trae`, `windsurf`
|
||||
|
||||
**Examples:**
|
||||
|
||||
@@ -101,6 +107,9 @@ openspec init --tools claude,cursor
|
||||
# Configure for all supported tools
|
||||
openspec init --tools all
|
||||
|
||||
# Override profile for this run
|
||||
openspec init --profile core
|
||||
|
||||
# Skip prompts and auto-cleanup legacy files
|
||||
openspec init --force
|
||||
```
|
||||
@@ -113,8 +122,9 @@ openspec/
|
||||
├── changes/ # Proposed changes
|
||||
└── config.yaml # Project configuration
|
||||
|
||||
.claude/skills/ # Claude Code skill files (if claude selected)
|
||||
.cursor/rules/ # Cursor rules (if cursor selected)
|
||||
.claude/skills/ # Claude Code skills (if claude selected)
|
||||
.cursor/skills/ # Cursor skills (if cursor selected)
|
||||
.cursor/commands/ # Cursor OPSX commands (if delivery includes commands)
|
||||
... (other tool configs)
|
||||
```
|
||||
|
||||
@@ -122,7 +132,7 @@ openspec/
|
||||
|
||||
### `openspec update`
|
||||
|
||||
Update OpenSpec instruction files after upgrading the CLI. Re-generates AI tool configuration files.
|
||||
Update OpenSpec instruction files after upgrading the CLI. Re-generates AI tool configuration files using your current global profile, selected workflows, and delivery mode.
|
||||
|
||||
```
|
||||
openspec update [path] [options]
|
||||
@@ -428,29 +438,28 @@ openspec status --change add-dark-mode --json
|
||||
```
|
||||
Change: add-dark-mode
|
||||
Schema: spec-driven
|
||||
Progress: 2/4 artifacts complete
|
||||
|
||||
Artifacts:
|
||||
✓ proposal proposal.md exists
|
||||
✓ specs specs/ exists
|
||||
◆ design ready (requires: specs)
|
||||
○ tasks blocked (requires: design)
|
||||
|
||||
Next: Create design using /opsx:continue
|
||||
[x] proposal
|
||||
[ ] design
|
||||
[x] specs
|
||||
[-] tasks (blocked by: design)
|
||||
```
|
||||
|
||||
**Output (JSON):**
|
||||
|
||||
```json
|
||||
{
|
||||
"change": "add-dark-mode",
|
||||
"schema": "spec-driven",
|
||||
"changeName": "add-dark-mode",
|
||||
"schemaName": "spec-driven",
|
||||
"isComplete": false,
|
||||
"applyRequires": ["tasks"],
|
||||
"artifacts": [
|
||||
{"id": "proposal", "status": "complete", "path": "proposal.md"},
|
||||
{"id": "specs", "status": "complete", "path": "specs/"},
|
||||
{"id": "design", "status": "ready", "requires": ["specs"]},
|
||||
{"id": "tasks", "status": "blocked", "requires": ["design"]}
|
||||
],
|
||||
"next": "design"
|
||||
{"id": "proposal", "outputPath": "proposal.md", "status": "done"},
|
||||
{"id": "design", "outputPath": "design.md", "status": "ready"},
|
||||
{"id": "specs", "outputPath": "specs/**/*.md", "status": "done"},
|
||||
{"id": "tasks", "outputPath": "tasks.md", "status": "blocked", "missingDeps": ["design"]}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -583,6 +592,46 @@ Available schemas:
|
||||
|
||||
---
|
||||
|
||||
## Workspace Commands
|
||||
|
||||
Use workspace mode when one change spans multiple repos or you need a neutral planning home for cross-repo coordination. Stay repo-local when one repo owns the full change end to end.
|
||||
|
||||
For the supported v0 flow, re-entry path, and owner or handoff guidance, see [Workspace Mode](workspace.md).
|
||||
|
||||
Start with the guided setup path unless you already know the exact workspace shape you want:
|
||||
|
||||
- `openspec workspace setup`
|
||||
|
||||
The setup wizard is interactive and asks for:
|
||||
|
||||
- workspace name
|
||||
- repo paths
|
||||
- repo aliases
|
||||
- optional owner or handoff notes
|
||||
- whether to open the planning surface immediately
|
||||
|
||||
The current workspace command group includes:
|
||||
|
||||
- `openspec workspace setup`
|
||||
- `openspec workspace list`
|
||||
- `openspec workspace create <name>`
|
||||
- `openspec workspace add-repo <alias> <path> [--owner ...] [--handoff ...]`
|
||||
- `openspec workspace update-repo <alias> [--owner ...] [--handoff ...]`
|
||||
- `openspec workspace targets <id> [--add <a,b,c>] [--remove <x,y,z>]`
|
||||
- `openspec workspace doctor`
|
||||
- `openspec workspace open [--change <id>] [--name <workspace>] [--agent <claude|codex|github-copilot>] [--prepare-only]`
|
||||
|
||||
`openspec workspace targets` only mutates workspace-owned planning state. If the same change ID already exists or was already archived in a target repo, the command fails instead of silently rewriting the target set around repo-local authority handoff.
|
||||
|
||||
Workspace planning still uses the normal workflow commands around that command group:
|
||||
|
||||
- `openspec new change <id> --targets <a,b,c>`
|
||||
- `openspec apply --change <id> --repo <alias>`
|
||||
- `openspec status --change <id>`
|
||||
- `openspec archive <id> --workspace`
|
||||
|
||||
---
|
||||
|
||||
## Schema Commands
|
||||
|
||||
Commands for creating and managing custom workflow schemas.
|
||||
@@ -912,6 +961,8 @@ openspec completion uninstall
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `OPENSPEC_TELEMETRY` | Set to `0` to disable telemetry |
|
||||
| `DO_NOT_TRACK` | Set to `1` to disable telemetry (standard DNT signal) |
|
||||
| `OPENSPEC_CONCURRENCY` | Default concurrency for bulk validation (default: 6) |
|
||||
| `EDITOR` or `VISUAL` | Editor for `openspec config edit` |
|
||||
| `NO_COLOR` | Disable color output when set |
|
||||
@@ -920,7 +971,8 @@ openspec completion uninstall
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Commands](commands.md) - AI slash commands (`/opsx:new`, `/opsx:apply`, etc.)
|
||||
- [Commands](commands.md) - AI slash commands (`/opsx:propose`, `/opsx:apply`, etc.)
|
||||
- [Workflows](workflows.md) - Common patterns and when to use each command
|
||||
- [Workspace Mode](workspace.md) - When to use cross-repo workspaces and the supported CLI flow
|
||||
- [Customization](customization.md) - Create custom schemas and templates
|
||||
- [Getting Started](getting-started.md) - First-time setup guide
|
||||
|
||||
+61
-12
@@ -6,23 +6,70 @@ For workflow patterns and when to use each command, see [Workflows](workflows.md
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Default Quick Path (`core` profile)
|
||||
|
||||
| Command | Purpose |
|
||||
|---------|---------|
|
||||
| `/opsx:propose` | Create a change and generate planning artifacts in one step |
|
||||
| `/opsx:explore` | Think through ideas before committing to a change |
|
||||
| `/opsx:new` | Start a new change |
|
||||
| `/opsx:apply` | Implement tasks from the change |
|
||||
| `/opsx:archive` | Archive a completed change |
|
||||
|
||||
### Expanded Workflow Commands (custom workflow selection)
|
||||
|
||||
| Command | Purpose |
|
||||
|---------|---------|
|
||||
| `/opsx:new` | Start a new change scaffold |
|
||||
| `/opsx:continue` | Create the next artifact based on dependencies |
|
||||
| `/opsx:ff` | Fast-forward: create all planning artifacts at once |
|
||||
| `/opsx:apply` | Implement tasks from the change |
|
||||
| `/opsx:verify` | Validate implementation matches artifacts |
|
||||
| `/opsx:sync` | Merge delta specs into main specs |
|
||||
| `/opsx:archive` | Archive a completed change |
|
||||
| `/opsx:bulk-archive` | Archive multiple changes at once |
|
||||
| `/opsx:onboard` | Guided tutorial through the complete workflow |
|
||||
|
||||
The default global profile is `core`. To enable expanded workflow commands, run `openspec config profile`, select workflows, then run `openspec update` in your project.
|
||||
|
||||
---
|
||||
|
||||
## Command Reference
|
||||
|
||||
### `/opsx:propose`
|
||||
|
||||
Create a new change and generate planning artifacts in one step. This is the default start command in the `core` profile.
|
||||
|
||||
**Syntax:**
|
||||
```text
|
||||
/opsx:propose [change-name-or-description]
|
||||
```
|
||||
|
||||
**Arguments:**
|
||||
| Argument | Required | Description |
|
||||
|----------|----------|-------------|
|
||||
| `change-name-or-description` | No | Kebab-case name or plain-language change description |
|
||||
|
||||
**What it does:**
|
||||
- Creates `openspec/changes/<change-name>/`
|
||||
- Generates artifacts needed before implementation (for `spec-driven`: proposal, specs, design, tasks)
|
||||
- Stops when the change is ready for `/opsx:apply`
|
||||
|
||||
**Example:**
|
||||
```text
|
||||
You: /opsx:propose add-dark-mode
|
||||
|
||||
AI: Created openspec/changes/add-dark-mode/
|
||||
✓ proposal.md
|
||||
✓ specs/ui/spec.md
|
||||
✓ design.md
|
||||
✓ tasks.md
|
||||
Ready for implementation. Run /opsx:apply.
|
||||
```
|
||||
|
||||
**Tips:**
|
||||
- Use this for the fastest end-to-end path
|
||||
- If you want step-by-step artifact control, enable expanded workflows and use `/opsx:new` + `/opsx:continue`
|
||||
|
||||
---
|
||||
|
||||
### `/opsx:explore`
|
||||
|
||||
Think through ideas, investigate problems, and clarify requirements before committing to a change.
|
||||
@@ -42,7 +89,7 @@ Think through ideas, investigate problems, and clarify requirements before commi
|
||||
- Investigates the codebase to answer questions
|
||||
- Compares options and approaches
|
||||
- Creates visual diagrams to clarify thinking
|
||||
- Can transition to `/opsx:new` when insights crystallize
|
||||
- Can transition to `/opsx:propose` (default) or `/opsx:new` (expanded workflow) when insights crystallize
|
||||
|
||||
**Example:**
|
||||
```text
|
||||
@@ -66,7 +113,7 @@ AI: Let me investigate your current auth setup...
|
||||
|
||||
You: Let's go with JWT. Can we start a change for that?
|
||||
|
||||
AI: Ready when you are. Run /opsx:new add-jwt-auth to begin.
|
||||
AI: Ready when you are. Run /opsx:propose add-jwt-auth to begin.
|
||||
```
|
||||
|
||||
**Tips:**
|
||||
@@ -79,7 +126,9 @@ AI: Ready when you are. Run /opsx:new add-jwt-auth to begin.
|
||||
|
||||
### `/opsx:new`
|
||||
|
||||
Start a new change. Creates the change folder structure and scaffolds it with the selected schema.
|
||||
Start a new change scaffold. Creates the change folder and waits for you to generate artifacts with `/opsx:continue` or `/opsx:ff`.
|
||||
|
||||
This command is part of the expanded workflow set (not included in the default `core` profile).
|
||||
|
||||
**Syntax:**
|
||||
```
|
||||
@@ -565,13 +614,13 @@ Different AI tools use slightly different command syntax. Use the format that ma
|
||||
|
||||
| Tool | Syntax Example |
|
||||
|------|----------------|
|
||||
| Claude Code | `/opsx:new`, `/opsx:apply` |
|
||||
| Cursor | `/opsx-new`, `/opsx-apply` |
|
||||
| Windsurf | `/opsx-new`, `/opsx-apply` |
|
||||
| Copilot (IDE) | `/opsx-new`, `/opsx-apply` |
|
||||
| Trae | `/openspec-new-change`, `/openspec-apply-change` |
|
||||
| Claude Code | `/opsx:propose`, `/opsx:apply` |
|
||||
| Cursor | `/opsx-propose`, `/opsx-apply` |
|
||||
| Windsurf | `/opsx-propose`, `/opsx-apply` |
|
||||
| Copilot (IDE) | `/opsx-propose`, `/opsx-apply` |
|
||||
| Trae | Skill-based invocations such as `/openspec-propose`, `/openspec-apply-change` (no generated `opsx-*` command files) |
|
||||
|
||||
The functionality is identical regardless of syntax.
|
||||
The intent is the same across tools, but how commands are surfaced can differ by integration.
|
||||
|
||||
> **Note:** GitHub Copilot commands (`.github/prompts/*.prompt.md`) are only available in IDE extensions (VS Code, JetBrains, Visual Studio). GitHub Copilot CLI does not currently support custom prompt files — see [Supported Tools](supported-tools.md) for details and workarounds.
|
||||
|
||||
|
||||
+27
-27
@@ -7,10 +7,10 @@ This guide explains the core ideas behind OpenSpec and how they fit together. Fo
|
||||
OpenSpec is built around four principles:
|
||||
|
||||
```
|
||||
fluid not rigid — no phase gates, work on what makes sense
|
||||
fluid not rigid — no phase gates, work on what makes sense
|
||||
iterative not waterfall — learn as you build, refine as you go
|
||||
easy not complex — lightweight setup, minimal ceremony
|
||||
brownfield-first — works with existing codebases, not just greenfield
|
||||
easy not complex — lightweight setup, minimal ceremony
|
||||
brownfield-first — works with existing codebases, not just greenfield
|
||||
```
|
||||
|
||||
### Why These Principles Matter
|
||||
@@ -28,19 +28,19 @@ brownfield-first — works with existing codebases, not just greenfield
|
||||
OpenSpec organizes your work into two main areas:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ openspec/ │
|
||||
│ │
|
||||
│ ┌─────────────────────┐ ┌──────────────────────────────┐ │
|
||||
│ │ specs/ │ │ changes/ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ Source of truth │◄─────│ Proposed modifications │ │
|
||||
│ │ How your system │ merge│ Each change = one folder │ │
|
||||
│ │ currently works │ │ Contains artifacts + deltas │ │
|
||||
│ │ │ │ │ │
|
||||
│ └─────────────────────┘ └──────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
┌────────────────────────────────────────────────────────────────────┐
|
||||
│ openspec/ │
|
||||
│ │
|
||||
│ ┌─────────────────────┐ ┌───────────────────────────────┐ │
|
||||
│ │ specs/ │ │ changes/ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ Source of truth │◄─────│ Proposed modifications │ │
|
||||
│ │ How your system │ merge│ Each change = one folder │ │
|
||||
│ │ currently works │ │ Contains artifacts + deltas │ │
|
||||
│ │ │ │ │ │
|
||||
│ └─────────────────────┘ └───────────────────────────────┘ │
|
||||
│ │
|
||||
└────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Specs** are the source of truth — they describe how your system currently behaves.
|
||||
@@ -270,7 +270,7 @@ Delta specs describe **what's changing** relative to the current specs. See [Del
|
||||
|
||||
The design captures **technical approach** and **architecture decisions**.
|
||||
|
||||
```markdown
|
||||
````markdown
|
||||
# Design: Add Dark Mode
|
||||
|
||||
## Technical Approach
|
||||
@@ -306,7 +306,7 @@ CSS Variables (applied to :root)
|
||||
- `src/contexts/ThemeContext.tsx` (new)
|
||||
- `src/components/ThemeToggle.tsx` (new)
|
||||
- `src/styles/globals.css` (modified)
|
||||
```
|
||||
````
|
||||
|
||||
**When to update the design:**
|
||||
- Implementation reveals the approach won't work
|
||||
@@ -558,17 +558,17 @@ openspec/
|
||||
## How It All Fits Together
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
┌──────────────────────────────────────────────────────────────────────────────┐
|
||||
│ OPENSPEC FLOW │
|
||||
│ │
|
||||
│ ┌────────────────┐ │
|
||||
│ │ 1. START │ /opsx:new creates a change folder │
|
||||
│ │ 1. START │ /opsx:propose (core) or /opsx:new (expanded) │
|
||||
│ │ CHANGE │ │
|
||||
│ └───────┬────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌────────────────┐ │
|
||||
│ │ 2. CREATE │ /opsx:ff or /opsx:continue │
|
||||
│ │ 2. CREATE │ /opsx:ff or /opsx:continue (expanded workflow) │
|
||||
│ │ ARTIFACTS │ Creates proposal → specs → design → tasks │
|
||||
│ │ │ (based on schema dependencies) │
|
||||
│ └───────┬────────┘ │
|
||||
@@ -587,13 +587,13 @@ openspec/
|
||||
│ └───────┬────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌────────────────┐ ┌──────────────────────────────────────────────┐ │
|
||||
│ │ 5. ARCHIVE │────►│ Delta specs merge into main specs │ │
|
||||
│ │ CHANGE │ │ Change folder moves to archive/ │ │
|
||||
│ └────────────────┘ │ Specs are now the updated source of truth │ │
|
||||
│ └──────────────────────────────────────────────┘ │
|
||||
│ ┌────────────────┐ ┌──────────────────────────────────────────────┐ │
|
||||
│ │ 5. ARCHIVE │────►│ Delta specs merge into main specs │ │
|
||||
│ │ CHANGE │ │ Change folder moves to archive/ │ │
|
||||
│ └────────────────┘ │ Specs are now the updated source of truth │ │
|
||||
│ └──────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
└──────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**The virtuous cycle:**
|
||||
|
||||
+20
-40
@@ -4,33 +4,22 @@ This guide explains how OpenSpec works after you've installed and initialized it
|
||||
|
||||
## How It Works
|
||||
|
||||
OpenSpec helps you and your AI coding assistant agree on what to build before any code is written. The workflow follows a simple pattern:
|
||||
OpenSpec helps you and your AI coding assistant agree on what to build before any code is written.
|
||||
|
||||
**Default quick path (core profile):**
|
||||
|
||||
```text
|
||||
/opsx:propose ──► /opsx:apply ──► /opsx:archive
|
||||
```
|
||||
┌────────────────────┐
|
||||
│ Start a Change │ /opsx:new
|
||||
└────────┬───────────┘
|
||||
│
|
||||
▼
|
||||
┌────────────────────┐
|
||||
│ Create Artifacts │ /opsx:ff or /opsx:continue
|
||||
│ (proposal, specs, │
|
||||
│ design, tasks) │
|
||||
└────────┬───────────┘
|
||||
│
|
||||
▼
|
||||
┌────────────────────┐
|
||||
│ Implement Tasks │ /opsx:apply
|
||||
│ (AI writes code) │
|
||||
└────────┬───────────┘
|
||||
│
|
||||
▼
|
||||
┌────────────────────┐
|
||||
│ Archive & Merge │ /opsx:archive
|
||||
│ Specs │
|
||||
└────────────────────┘
|
||||
|
||||
**Expanded path (custom workflow selection):**
|
||||
|
||||
```text
|
||||
/opsx:new ──► /opsx:ff or /opsx:continue ──► /opsx:apply ──► /opsx:verify ──► /opsx:archive
|
||||
```
|
||||
|
||||
The default global profile is `core`, which includes `propose`, `explore`, `apply`, and `archive`. You can enable the expanded workflow commands with `openspec config profile` and then `openspec update`.
|
||||
|
||||
## What OpenSpec Creates
|
||||
|
||||
After running `openspec init`, your project has this structure:
|
||||
@@ -131,23 +120,12 @@ The change folder moves to `openspec/changes/archive/` for audit history.
|
||||
|
||||
Let's walk through adding dark mode to an application.
|
||||
|
||||
### 1. Start the Change
|
||||
### 1. Start the Change (Default)
|
||||
|
||||
```
|
||||
You: /opsx:new add-dark-mode
|
||||
```text
|
||||
You: /opsx:propose add-dark-mode
|
||||
|
||||
AI: Created openspec/changes/add-dark-mode/
|
||||
Ready to create: proposal
|
||||
```
|
||||
|
||||
### 2. Create Artifacts
|
||||
|
||||
Use `/opsx:ff` (fast-forward) to create all planning artifacts at once:
|
||||
|
||||
```
|
||||
You: /opsx:ff
|
||||
|
||||
AI: Creating artifacts for add-dark-mode...
|
||||
✓ proposal.md — why we're doing this, what's changing
|
||||
✓ specs/ — requirements and scenarios
|
||||
✓ design.md — technical approach
|
||||
@@ -155,7 +133,9 @@ AI: Creating artifacts for add-dark-mode...
|
||||
Ready for implementation!
|
||||
```
|
||||
|
||||
### 3. What Gets Created
|
||||
If you've enabled the expanded workflow profile, you can also do this as two steps: `/opsx:new` then `/opsx:ff` (or `/opsx:continue` incrementally).
|
||||
|
||||
### 2. What Gets Created
|
||||
|
||||
**proposal.md** - Captures the intent:
|
||||
|
||||
@@ -218,7 +198,7 @@ The system SHALL allow users to choose between light and dark themes.
|
||||
- [ ] 3.2 Update components to use CSS variables
|
||||
```
|
||||
|
||||
### 4. Implement
|
||||
### 3. Implement
|
||||
|
||||
```
|
||||
You: /opsx:apply
|
||||
@@ -234,7 +214,7 @@ AI: Working through tasks...
|
||||
|
||||
During implementation, if you discover the design needs adjustment, just update the artifact and continue.
|
||||
|
||||
### 5. Archive
|
||||
### 4. Archive
|
||||
|
||||
```
|
||||
You: /opsx:archive
|
||||
|
||||
+35
-15
@@ -8,7 +8,7 @@ OPSX replaces the old phase-locked workflow with a fluid, action-based approach.
|
||||
|
||||
| Aspect | Legacy | OPSX |
|
||||
|--------|--------|------|
|
||||
| **Commands** | `/openspec:proposal`, `/openspec:apply`, `/openspec:archive` | `/opsx:new`, `/opsx:continue`, `/opsx:apply`, and more |
|
||||
| **Commands** | `/openspec:proposal`, `/openspec:apply`, `/openspec:archive` | Default: `/opsx:propose`, `/opsx:apply`, `/opsx:archive` (expanded workflow commands optional) |
|
||||
| **Workflow** | Create all artifacts at once | Create incrementally or all at once—your choice |
|
||||
| **Going back** | Awkward phase gates | Natural—update any artifact anytime |
|
||||
| **Customization** | Fixed structure | Schema-driven, fully hackable |
|
||||
@@ -84,6 +84,9 @@ Don't worry about getting it perfect. We're still learning what works best here,
|
||||
|
||||
Both `openspec init` and `openspec update` detect legacy files and guide you through the same cleanup process. Use whichever fits your situation:
|
||||
|
||||
- New installs default to profile `core` (`propose`, `explore`, `apply`, `archive`).
|
||||
- Migrated installs preserve your previously installed workflows by writing a `custom` profile when needed.
|
||||
|
||||
### Using `openspec init`
|
||||
|
||||
Run this if you want to add new tools or reconfigure which tools are set up:
|
||||
@@ -141,7 +144,7 @@ Run this if you just want to migrate and refresh your existing tools to the late
|
||||
openspec update
|
||||
```
|
||||
|
||||
The update command also detects and cleans up legacy artifacts, then refreshes your skills to the latest version.
|
||||
The update command also detects and cleans up legacy artifacts, then refreshes generated skills/commands to match your current profile and delivery settings.
|
||||
|
||||
### Non-Interactive / CI Environments
|
||||
|
||||
@@ -275,30 +278,43 @@ The AI will help you identify what's essential vs. what can be trimmed.
|
||||
|
||||
## The New Commands
|
||||
|
||||
After migration, you have 9 OPSX commands instead of 3:
|
||||
Command availability is profile-dependent:
|
||||
|
||||
**Default (`core` profile):**
|
||||
|
||||
| Command | Purpose |
|
||||
|---------|---------|
|
||||
| `/opsx:propose` | Create a change and generate planning artifacts in one step |
|
||||
| `/opsx:explore` | Think through ideas with no structure |
|
||||
| `/opsx:new` | Start a new change |
|
||||
| `/opsx:continue` | Create the next artifact (one at a time) |
|
||||
| `/opsx:ff` | Fast-forward—create all planning artifacts at once |
|
||||
| `/opsx:apply` | Implement tasks from tasks.md |
|
||||
| `/opsx:verify` | Validate implementation matches specs |
|
||||
| `/opsx:sync` | Preview spec merge (optional—archive prompts if needed) |
|
||||
| `/opsx:archive` | Finalize and archive the change |
|
||||
|
||||
**Expanded workflow (custom selection):**
|
||||
|
||||
| Command | Purpose |
|
||||
|---------|---------|
|
||||
| `/opsx:new` | Start a new change scaffold |
|
||||
| `/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:bulk-archive` | Archive multiple changes at once |
|
||||
| `/opsx:onboard` | Guided end-to-end onboarding workflow |
|
||||
|
||||
Enable expanded commands with `openspec config profile`, then run `openspec update`.
|
||||
|
||||
### Command Mapping from Legacy
|
||||
|
||||
| Legacy | OPSX Equivalent |
|
||||
|--------|-----------------|
|
||||
| `/openspec:proposal` | `/opsx:new` then `/opsx:ff` |
|
||||
| `/openspec:proposal` | `/opsx:propose` (default) or `/opsx:new` then `/opsx:ff` (expanded) |
|
||||
| `/openspec:apply` | `/opsx:apply` |
|
||||
| `/openspec:archive` | `/opsx:archive` |
|
||||
|
||||
### New Capabilities
|
||||
|
||||
These capabilities are part of the expanded workflow command set.
|
||||
|
||||
**Granular artifact creation:**
|
||||
```
|
||||
/opsx:continue
|
||||
@@ -542,9 +558,10 @@ project/
|
||||
│ └── config.yaml # NEW: Project configuration
|
||||
├── .claude/
|
||||
│ └── skills/ # NEW: OPSX skills
|
||||
│ ├── openspec-propose/ # default core profile
|
||||
│ ├── openspec-explore/
|
||||
│ ├── openspec-new-change/
|
||||
│ └── ...
|
||||
│ ├── openspec-apply-change/
|
||||
│ └── ... # expanded profile adds new/continue/ff/etc.
|
||||
├── CLAUDE.md # OpenSpec markers removed, your content preserved
|
||||
└── AGENTS.md # OpenSpec markers removed, your content preserved
|
||||
```
|
||||
@@ -558,12 +575,15 @@ project/
|
||||
|
||||
### Command Cheatsheet
|
||||
|
||||
```
|
||||
/opsx:new Start a change
|
||||
/opsx:continue Create next artifact
|
||||
/opsx:ff Create all planning artifacts
|
||||
```text
|
||||
/opsx:propose Start quickly (default core profile)
|
||||
/opsx:apply Implement tasks
|
||||
/opsx:archive Finish and archive
|
||||
|
||||
# Expanded workflow (if enabled):
|
||||
/opsx:new Scaffold a change
|
||||
/opsx:continue Create next artifact
|
||||
/opsx:ff Create planning artifacts
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
+24
-9
@@ -65,6 +65,8 @@ openspec init
|
||||
|
||||
This creates skills in `.claude/skills/` (or equivalent) that AI coding assistants auto-detect.
|
||||
|
||||
By default, OpenSpec uses the `core` workflow profile (`propose`, `explore`, `apply`, `archive`). If you want the expanded workflow commands (`new`, `continue`, `ff`, `verify`, `sync`, `bulk-archive`, `onboard`), configure them with `openspec config profile` and apply with `openspec update`.
|
||||
|
||||
During setup, you'll be prompted to create a **project config** (`openspec/config.yaml`). This is optional but recommended.
|
||||
|
||||
## Project Configuration
|
||||
@@ -155,13 +157,17 @@ rules:
|
||||
|
||||
| Command | What it does |
|
||||
|---------|--------------|
|
||||
| `/opsx:propose` | Create a change and generate planning artifacts in one step (default quick path) |
|
||||
| `/opsx:explore` | Think through ideas, investigate problems, clarify requirements |
|
||||
| `/opsx:new` | Start a new change |
|
||||
| `/opsx:continue` | Create the next artifact (based on what's ready) |
|
||||
| `/opsx:ff` | Fast-forward — create all planning artifacts at once |
|
||||
| `/opsx:new` | Start a new change scaffold (expanded workflow) |
|
||||
| `/opsx:continue` | Create the next artifact (expanded workflow) |
|
||||
| `/opsx:ff` | Fast-forward planning artifacts (expanded workflow) |
|
||||
| `/opsx:apply` | Implement tasks, updating artifacts as needed |
|
||||
| `/opsx:sync` | Sync delta specs to main (optional—archive prompts if needed) |
|
||||
| `/opsx:verify` | Validate implementation against artifacts (expanded workflow) |
|
||||
| `/opsx:sync` | Sync delta specs to main (expanded workflow, optional) |
|
||||
| `/opsx:archive` | Archive when done |
|
||||
| `/opsx:bulk-archive` | Archive multiple completed changes (expanded workflow) |
|
||||
| `/opsx:onboard` | Guided walkthrough of an end-to-end change (expanded workflow) |
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -169,13 +175,21 @@ rules:
|
||||
```
|
||||
/opsx:explore
|
||||
```
|
||||
Think through ideas, investigate problems, compare options. No structure required - just a thinking partner. When insights crystallize, transition to `/opsx:new` or `/opsx:ff`.
|
||||
Think through ideas, investigate problems, compare options. No structure required - just a thinking partner. When insights crystallize, transition to `/opsx:propose` (default) or `/opsx:new`/`/opsx:ff` (expanded).
|
||||
|
||||
### Start a new change
|
||||
```
|
||||
/opsx:new
|
||||
/opsx:propose
|
||||
```
|
||||
Creates the change and generates planning artifacts needed before implementation.
|
||||
|
||||
If you've enabled expanded workflows, you can instead use:
|
||||
|
||||
```text
|
||||
/opsx:new # scaffold only
|
||||
/opsx:continue # create one artifact at a time
|
||||
/opsx:ff # create all planning artifacts at once
|
||||
```
|
||||
You'll be asked what you want to build and which workflow schema to use.
|
||||
|
||||
### Create artifacts
|
||||
```
|
||||
@@ -299,6 +313,7 @@ Think of it like git branches:
|
||||
## Architecture Deep Dive
|
||||
|
||||
This section explains how OPSX works under the hood and how it compares to the legacy workflow.
|
||||
Examples in this section use the expanded command set (`new`, `continue`, etc.); default `core` users can map the same flow to `propose → apply → archive`.
|
||||
|
||||
### Philosophy: Phases vs Actions
|
||||
|
||||
@@ -356,7 +371,7 @@ This section explains how OPSX works under the hood and how it compares to the l
|
||||
│ Hardcoded Templates (TypeScript strings) │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ Configurators (18+ classes, one per editor) │
|
||||
│ Tool-specific configurators/adapters │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ Generated Command Files (.claude/commands/openspec/*.md) │
|
||||
@@ -604,7 +619,7 @@ artifacts:
|
||||
| **State** | Phase-based mental model | Filesystem existence |
|
||||
| **Customization** | Edit source, rebuild | Create schema.yaml |
|
||||
| **Iteration** | Phase-locked | Fluid, edit anything |
|
||||
| **Editor Support** | 18+ configurator classes | Single skills directory |
|
||||
| **Editor Support** | Tool-specific configurator/adapters | Single skills directory |
|
||||
|
||||
## Schemas
|
||||
|
||||
|
||||
+69
-52
@@ -1,50 +1,61 @@
|
||||
# Supported Tools
|
||||
|
||||
OpenSpec works with 20+ AI coding assistants. When you run `openspec init`, you'll be prompted to select which tools you use, and OpenSpec will configure the appropriate integrations.
|
||||
OpenSpec works with many AI coding assistants. When you run `openspec init`, OpenSpec configures selected tools using your active profile/workflow selection and delivery mode.
|
||||
|
||||
## How It Works
|
||||
|
||||
For each tool you select, OpenSpec installs:
|
||||
For each selected tool, OpenSpec can install:
|
||||
|
||||
1. **Skills** — Reusable instruction files that power the `/opsx:*` workflow commands
|
||||
2. **Commands** — Tool-specific slash command bindings
|
||||
1. **Skills** (if delivery includes skills): `.../skills/openspec-*/SKILL.md`
|
||||
2. **Commands** (if delivery includes commands): tool-specific `opsx-*` command files
|
||||
|
||||
By default, OpenSpec uses the `core` profile, which includes:
|
||||
- `propose`
|
||||
- `explore`
|
||||
- `apply`
|
||||
- `archive`
|
||||
|
||||
You can enable expanded workflows (`new`, `continue`, `ff`, `verify`, `sync`, `bulk-archive`, `onboard`) via `openspec config profile`, then run `openspec update`.
|
||||
|
||||
## Tool Directory Reference
|
||||
|
||||
| Tool | Skills Location | Commands Location |
|
||||
|------|-----------------|-------------------|
|
||||
| Amazon Q Developer | `.amazonq/skills/` | `.amazonq/prompts/` |
|
||||
| Antigravity | `.agent/skills/` | `.agent/workflows/` |
|
||||
| Auggie (Augment CLI) | `.augment/skills/` | `.augment/commands/` |
|
||||
| Claude Code | `.claude/skills/` | `.claude/commands/opsx/` |
|
||||
| Cline | `.cline/skills/` | `.clinerules/workflows/` |
|
||||
| CodeBuddy | `.codebuddy/skills/` | `.codebuddy/commands/opsx/` |
|
||||
| Codex | `.codex/skills/` | `~/.codex/prompts/`\* |
|
||||
| Continue | `.continue/skills/` | `.continue/prompts/` |
|
||||
| CoStrict | `.cospec/skills/` | `.cospec/openspec/commands/` |
|
||||
| Crush | `.crush/skills/` | `.crush/commands/opsx/` |
|
||||
| Cursor | `.cursor/skills/` | `.cursor/commands/` |
|
||||
| Factory Droid | `.factory/skills/` | `.factory/commands/` |
|
||||
| Gemini CLI | `.gemini/skills/` | `.gemini/commands/opsx/` |
|
||||
| GitHub Copilot | `.github/skills/` | `.github/prompts/`\*\* |
|
||||
| iFlow | `.iflow/skills/` | `.iflow/commands/` |
|
||||
| Kilo Code | `.kilocode/skills/` | `.kilocode/workflows/` |
|
||||
| Kiro | `.kiro/skills/` | `.kiro/prompts/` |
|
||||
| OpenCode | `.opencode/skills/` | `.opencode/command/` |
|
||||
| Pi | `.pi/skills/` | `.pi/prompts/` |
|
||||
| Qoder | `.qoder/skills/` | `.qoder/commands/opsx/` |
|
||||
| Qwen Code | `.qwen/skills/` | `.qwen/commands/` |
|
||||
| RooCode | `.roo/skills/` | `.roo/commands/` |
|
||||
| Trae | `.trae/skills/` | `.trae/skills/` (via `/openspec-*`) |
|
||||
| Windsurf | `.windsurf/skills/` | `.windsurf/workflows/` |
|
||||
| Tool (ID) | Skills path pattern | Command path pattern |
|
||||
|-----------|---------------------|----------------------|
|
||||
| Amazon Q Developer (`amazon-q`) | `.amazonq/skills/openspec-*/SKILL.md` | `.amazonq/prompts/opsx-<id>.md` |
|
||||
| Antigravity (`antigravity`) | `.agent/skills/openspec-*/SKILL.md` | `.agent/workflows/opsx-<id>.md` |
|
||||
| Auggie (`auggie`) | `.augment/skills/openspec-*/SKILL.md` | `.augment/commands/opsx-<id>.md` |
|
||||
| IBM Bob Shell (`bob`) | `.bob/skills/openspec-*/SKILL.md` | `.bob/commands/opsx-<id>.md` |
|
||||
| Claude Code (`claude`) | `.claude/skills/openspec-*/SKILL.md` | `.claude/commands/opsx/<id>.md` |
|
||||
| Cline (`cline`) | `.cline/skills/openspec-*/SKILL.md` | `.clinerules/workflows/opsx-<id>.md` |
|
||||
| CodeBuddy (`codebuddy`) | `.codebuddy/skills/openspec-*/SKILL.md` | `.codebuddy/commands/opsx/<id>.md` |
|
||||
| Codex (`codex`) | `.codex/skills/openspec-*/SKILL.md` | `$CODEX_HOME/prompts/opsx-<id>.md`\* |
|
||||
| ForgeCode (`forgecode`) | `.forge/skills/openspec-*/SKILL.md` | Not generated (no command adapter; use skill-based `/openspec-*` invocations) |
|
||||
| Continue (`continue`) | `.continue/skills/openspec-*/SKILL.md` | `.continue/prompts/opsx-<id>.prompt` |
|
||||
| CoStrict (`costrict`) | `.cospec/skills/openspec-*/SKILL.md` | `.cospec/openspec/commands/opsx-<id>.md` |
|
||||
| Crush (`crush`) | `.crush/skills/openspec-*/SKILL.md` | `.crush/commands/opsx/<id>.md` |
|
||||
| Cursor (`cursor`) | `.cursor/skills/openspec-*/SKILL.md` | `.cursor/commands/opsx-<id>.md` |
|
||||
| Factory Droid (`factory`) | `.factory/skills/openspec-*/SKILL.md` | `.factory/commands/opsx-<id>.md` |
|
||||
| Gemini CLI (`gemini`) | `.gemini/skills/openspec-*/SKILL.md` | `.gemini/commands/opsx/<id>.toml` |
|
||||
| GitHub Copilot (`github-copilot`) | `.github/skills/openspec-*/SKILL.md` | `.github/prompts/opsx-<id>.prompt.md`\*\* |
|
||||
| iFlow (`iflow`) | `.iflow/skills/openspec-*/SKILL.md` | `.iflow/commands/opsx-<id>.md` |
|
||||
| Junie (`junie`) | `.junie/skills/openspec-*/SKILL.md` | `.junie/commands/opsx-<id>.md` |
|
||||
| Kilo Code (`kilocode`) | `.kilocode/skills/openspec-*/SKILL.md` | `.kilocode/workflows/opsx-<id>.md` |
|
||||
| Kiro (`kiro`) | `.kiro/skills/openspec-*/SKILL.md` | `.kiro/prompts/opsx-<id>.prompt.md` |
|
||||
| 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` |
|
||||
| Qwen Code (`qwen`) | `.qwen/skills/openspec-*/SKILL.md` | `.qwen/commands/opsx-<id>.toml` |
|
||||
| RooCode (`roocode`) | `.roo/skills/openspec-*/SKILL.md` | `.roo/commands/opsx-<id>.md` |
|
||||
| Trae (`trae`) | `.trae/skills/openspec-*/SKILL.md` | Not generated (no command adapter; use skill-based `/openspec-*` invocations) |
|
||||
| Windsurf (`windsurf`) | `.windsurf/skills/openspec-*/SKILL.md` | `.windsurf/workflows/opsx-<id>.md` |
|
||||
|
||||
\* Codex commands are installed to the global home directory (`~/.codex/prompts/` or `$CODEX_HOME/prompts/`), not the project directory.
|
||||
\* Codex commands are installed in the global Codex home (`$CODEX_HOME/prompts/` if set, otherwise `~/.codex/prompts/`), not your project directory.
|
||||
|
||||
\*\* GitHub Copilot's `.github/prompts/*.prompt.md` files are recognized as custom slash commands in **IDE extensions only** (VS Code, JetBrains, Visual Studio). GitHub Copilot CLI does not currently support custom prompts from this directory — see [github/copilot-cli#618](https://github.com/github/copilot-cli/issues/618). If you use Copilot CLI, you may need to manually set up [custom agents](https://docs.github.com/en/copilot/how-tos/use-copilot-agents/coding-agent/create-custom-agents) in `.github/agents/` as a workaround.
|
||||
\*\* GitHub Copilot prompt files are recognized as custom slash commands in IDE extensions (VS Code, JetBrains, Visual Studio). `openspec workspace open --agent github-copilot` targets VS Code Copilot and emits a managed `.code-workspace` file under `.openspec/workspace-open/github-copilot/`. Copilot CLI does not currently consume `.github/prompts/*.prompt.md` directly.
|
||||
|
||||
## Non-Interactive Setup
|
||||
|
||||
For CI/CD or scripted setup, use the `--tools` flag:
|
||||
For CI/CD or scripted setup, use `--tools` (and optionally `--profile`):
|
||||
|
||||
```bash
|
||||
# Configure specific tools
|
||||
@@ -55,34 +66,40 @@ openspec init --tools all
|
||||
|
||||
# Skip tool configuration
|
||||
openspec init --tools none
|
||||
|
||||
# Override profile for this init run
|
||||
openspec init --profile core
|
||||
```
|
||||
|
||||
**Available tool IDs:** `amazon-q`, `antigravity`, `auggie`, `claude`, `cline`, `codebuddy`, `codex`, `continue`, `costrict`, `crush`, `cursor`, `factory`, `gemini`, `github-copilot`, `iflow`, `kilocode`, `kiro`, `opencode`, `pi`, `qoder`, `qwen`, `roocode`, `trae`, `windsurf`
|
||||
**Available tool IDs (`--tools`):** `amazon-q`, `antigravity`, `auggie`, `bob`, `claude`, `cline`, `codex`, `codebuddy`, `continue`, `costrict`, `crush`, `cursor`, `factory`, `forgecode`, `gemini`, `github-copilot`, `iflow`, `junie`, `kilocode`, `kiro`, `opencode`, `pi`, `qoder`, `qwen`, `roocode`, `trae`, `windsurf`
|
||||
|
||||
## What Gets Installed
|
||||
## Workflow-Dependent Installation
|
||||
|
||||
For each tool, OpenSpec generates 10 skill files that power the OPSX workflow:
|
||||
OpenSpec installs workflow artifacts based on selected workflows:
|
||||
|
||||
| Skill | Purpose |
|
||||
|-------|---------|
|
||||
| `openspec-explore` | Thinking partner for exploring ideas |
|
||||
| `openspec-new-change` | Start a new change |
|
||||
| `openspec-continue-change` | Create the next artifact |
|
||||
| `openspec-ff-change` | Fast-forward through all planning artifacts |
|
||||
| `openspec-apply-change` | Implement tasks |
|
||||
| `openspec-verify-change` | Verify implementation completeness |
|
||||
| `openspec-sync-specs` | Sync delta specs to main (optional—archive prompts if needed) |
|
||||
| `openspec-archive-change` | Archive a completed change |
|
||||
| `openspec-bulk-archive-change` | Archive multiple changes at once |
|
||||
| `openspec-onboard` | Guided onboarding through a complete workflow cycle |
|
||||
- **Core profile (default):** `propose`, `explore`, `apply`, `archive`
|
||||
- **Custom selection:** any subset of all workflow IDs:
|
||||
`propose`, `explore`, `new`, `continue`, `apply`, `ff`, `sync`, `archive`, `bulk-archive`, `verify`, `onboard`
|
||||
|
||||
These skills are invoked via slash commands like `/opsx:new`, `/opsx:apply`, etc. See [Commands](commands.md) for the full list.
|
||||
In other words, skill/command counts are profile-dependent and delivery-dependent, not fixed.
|
||||
|
||||
## Adding a New Tool
|
||||
## Generated Skill Names
|
||||
|
||||
Want to add support for another AI coding assistant? Check out the [command adapter pattern](../CONTRIBUTING.md) or open an issue on GitHub.
|
||||
When selected by profile/workflow config, OpenSpec generates these skills:
|
||||
|
||||
---
|
||||
- `openspec-propose`
|
||||
- `openspec-explore`
|
||||
- `openspec-new-change`
|
||||
- `openspec-continue-change`
|
||||
- `openspec-apply-change`
|
||||
- `openspec-ff-change`
|
||||
- `openspec-sync-specs`
|
||||
- `openspec-archive-change`
|
||||
- `openspec-bulk-archive-change`
|
||||
- `openspec-verify-change`
|
||||
- `openspec-onboard`
|
||||
|
||||
See [Commands](commands.md) for command behavior and [CLI](cli.md) for `init`/`update` options.
|
||||
|
||||
## Related
|
||||
|
||||
|
||||
+33
-7
@@ -28,7 +28,32 @@ OPSX (fluid actions):
|
||||
|
||||
> **Customization:** OPSX workflows are driven by schemas that define artifact sequences. See [Customization](customization.md) for details on creating custom schemas.
|
||||
|
||||
## Workflow Patterns
|
||||
## Two Modes
|
||||
|
||||
### Default Quick Path (`core` profile)
|
||||
|
||||
New installs default to `core`, which provides:
|
||||
- `/opsx:propose`
|
||||
- `/opsx:explore`
|
||||
- `/opsx:apply`
|
||||
- `/opsx:archive`
|
||||
|
||||
Typical flow:
|
||||
|
||||
```text
|
||||
/opsx:propose ──► /opsx:apply ──► /opsx:archive
|
||||
```
|
||||
|
||||
### Expanded/Full Workflow (custom selection)
|
||||
|
||||
If you want explicit scaffold-and-build commands (`/opsx:new`, `/opsx:continue`, `/opsx:ff`, `/opsx:verify`, `/opsx:sync`, `/opsx:bulk-archive`, `/opsx:onboard`), enable them with:
|
||||
|
||||
```bash
|
||||
openspec config profile
|
||||
openspec update
|
||||
```
|
||||
|
||||
## Workflow Patterns (Expanded Mode)
|
||||
|
||||
### Quick Feature
|
||||
|
||||
@@ -408,15 +433,16 @@ 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:new` | Start a change | Beginning any new work |
|
||||
| `/opsx:continue` | Create next artifact | Step-by-step artifact creation |
|
||||
| `/opsx:ff` | Create all planning artifacts | Clear scope, ready to build |
|
||||
| `/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 |
|
||||
| `/opsx:apply` | Implement tasks | Ready to write code |
|
||||
| `/opsx:verify` | Validate implementation | Before archiving, catch mismatches |
|
||||
| `/opsx:sync` | Merge delta specs | Optional—archive prompts if needed |
|
||||
| `/opsx:verify` | Validate implementation | Expanded mode, before archiving |
|
||||
| `/opsx:sync` | Merge delta specs | Expanded mode, optional |
|
||||
| `/opsx:archive` | Complete the change | All work finished |
|
||||
| `/opsx:bulk-archive` | Archive multiple changes | Parallel work, batch completion |
|
||||
| `/opsx:bulk-archive` | Archive multiple changes | Expanded mode, parallel work |
|
||||
|
||||
## Next Steps
|
||||
|
||||
|
||||
@@ -0,0 +1,494 @@
|
||||
# Workspace Demo
|
||||
|
||||
This guide is for using workspace mode with **real repos on your machine**.
|
||||
|
||||
It is written as a dogfood tutorial:
|
||||
|
||||
- use the actual `openspec` repo checkout you already have
|
||||
- optionally add one or two more real repos if you want to exercise the multi-repo parts more fully
|
||||
- create a real managed workspace
|
||||
- try the commands in the order a real user would
|
||||
|
||||
If you only have the `openspec` repo available right now, you can still run the core flow. If you also have a second or third repo handy, the guide points out the extra things worth trying.
|
||||
|
||||
## What you will exercise
|
||||
|
||||
- creating a managed workspace
|
||||
- registering real repos with stable aliases
|
||||
- using `workspace doctor`
|
||||
- creating a workspace change with explicit targets
|
||||
- workspace-root and change-scoped `workspace open`
|
||||
- Codex and GitHub Copilot workspace-open flows
|
||||
- `status` as the coordination view
|
||||
- `apply` as the handoff into repo-local execution
|
||||
- optional target mutation before apply
|
||||
- optional guardrails after apply
|
||||
- optional workspace archive at the end
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- `openspec` is installed and available on your `PATH`
|
||||
- Node.js `20.19.0+`
|
||||
- `git` is available
|
||||
- optional: VS Code with GitHub Copilot if you want to try the Copilot path
|
||||
|
||||
If you are running from this repo checkout instead of a global install, replace `openspec` below with:
|
||||
|
||||
```bash
|
||||
node /absolute/path/to/openspec/bin/openspec.js
|
||||
```
|
||||
|
||||
## 1. Pick the real repos you want to coordinate
|
||||
|
||||
Start in the root of the real `openspec` repo you want to use:
|
||||
|
||||
```bash
|
||||
cd /path/to/your/openspec/repo
|
||||
pwd
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
- this repo path is the one repo this guide assumes you definitely have
|
||||
- additional repos are optional, but they make workspace mode much more interesting
|
||||
- You can use any real repos here, not just repos related to OpenSpec.
|
||||
|
||||
## 2. Make sure each repo has repo-local OpenSpec state
|
||||
|
||||
`workspace add-repo` only accepts repos that already contain repo-local OpenSpec state, which means the repo has an `openspec/` directory.
|
||||
|
||||
Check the `openspec` repo:
|
||||
|
||||
```bash
|
||||
test -d /path/to/your/openspec/repo/openspec && echo "openspec repo is ready"
|
||||
```
|
||||
|
||||
If you are adding other repos, initialize them if needed:
|
||||
|
||||
```bash
|
||||
openspec init /absolute/path/to/another/repo --tools none --force
|
||||
```
|
||||
|
||||
Only run that command for repos that do not already have `openspec/`.
|
||||
|
||||
## 3. Use the setup wizard the way a real user would
|
||||
|
||||
The recommended onboarding path is:
|
||||
|
||||
```bash
|
||||
openspec workspace setup
|
||||
```
|
||||
|
||||
Use these answers when prompted:
|
||||
|
||||
```text
|
||||
Workspace name: openspec-dogfood
|
||||
Repo path: /absolute/path/to/your/openspec/repo
|
||||
Repo alias: openspec
|
||||
Owner (optional): OpenSpec Core
|
||||
Handoff note (optional): Apply when the shared plan is ready
|
||||
Add another repo? n
|
||||
Open the workspace now? y
|
||||
Which agent should OpenSpec prepare for? codex
|
||||
```
|
||||
|
||||
If you also want to register more repos, answer `y` to `Add another repo?` and keep going until the wizard reaches the summary.
|
||||
|
||||
At the end of the wizard, `cd` into the created workspace. If you used the workspace name above, the default path is:
|
||||
|
||||
```bash
|
||||
cd "$HOME/.local/share/openspec/workspaces/openspec-dogfood"
|
||||
pwd
|
||||
```
|
||||
|
||||
What to check:
|
||||
|
||||
- you are now inside the managed workspace root
|
||||
- these files exist:
|
||||
- `.openspec/workspace.yaml`
|
||||
- `.openspec/local.yaml`
|
||||
- `changes/`
|
||||
|
||||
Quick inspection:
|
||||
|
||||
```bash
|
||||
find . -maxdepth 2 -type f | sort
|
||||
sed -n '1,200p' .gitignore
|
||||
```
|
||||
|
||||
What to notice:
|
||||
|
||||
- the workspace is separate from any one repo
|
||||
- `.openspec/local.yaml` is machine-local state
|
||||
- `/.openspec/workspace-open/` is ignored because workspace-open may generate local artifacts there
|
||||
|
||||
If you want to understand the lower-level equivalent, it is:
|
||||
|
||||
```bash
|
||||
openspec workspace create openspec-dogfood
|
||||
openspec workspace add-repo openspec /absolute/path/to/your/openspec/repo --owner "OpenSpec Core" --handoff "Apply when the shared plan is ready"
|
||||
cd "$HOME/.local/share/openspec/workspaces/openspec-dogfood"
|
||||
```
|
||||
|
||||
## 4. Register additional real repos if you want a broader test
|
||||
|
||||
If you only want to test the single-repo flow, you can skip this section because the wizard already registered `openspec`.
|
||||
|
||||
If you have more repos, register them now:
|
||||
|
||||
```bash
|
||||
openspec workspace add-repo consumer /absolute/path/to/another/repo --owner "Consumer Team" --handoff "Pick up once the core contract is stable"
|
||||
openspec workspace add-repo docs /absolute/path/to/a/docs-repo --owner "Docs Team" --handoff "Document the rollout after implementation lands"
|
||||
```
|
||||
|
||||
Now validate the workspace registry:
|
||||
|
||||
```bash
|
||||
openspec workspace doctor
|
||||
sed -n '1,200p' .openspec/workspace.yaml
|
||||
sed -n '1,200p' .openspec/local.yaml
|
||||
```
|
||||
|
||||
What to notice:
|
||||
|
||||
- `workspace.yaml` holds alias metadata you could share or commit
|
||||
- `local.yaml` holds machine-local repo paths
|
||||
- `workspace doctor` is the first thing to run if the registry feels wrong later
|
||||
|
||||
## 5. Create a real workspace change
|
||||
|
||||
Choose one of these commands based on the aliases you actually want to coordinate.
|
||||
|
||||
Single-repo flow:
|
||||
|
||||
```bash
|
||||
openspec new change workspace-dogfood --targets openspec
|
||||
```
|
||||
|
||||
Two-repo flow:
|
||||
|
||||
```bash
|
||||
openspec new change workspace-dogfood --targets openspec,consumer
|
||||
```
|
||||
|
||||
Three-repo flow:
|
||||
|
||||
```bash
|
||||
openspec new change workspace-dogfood --targets openspec,consumer,docs
|
||||
```
|
||||
|
||||
Inspect what was created:
|
||||
|
||||
```bash
|
||||
find changes/workspace-dogfood -maxdepth 3 -type f | sort
|
||||
sed -n '1,200p' changes/workspace-dogfood/proposal.md
|
||||
sed -n '1,200p' changes/workspace-dogfood/design.md
|
||||
sed -n '1,200p' changes/workspace-dogfood/tasks/coordination.md
|
||||
```
|
||||
|
||||
If you targeted more than one repo, also inspect the draft slices:
|
||||
|
||||
```bash
|
||||
find changes/workspace-dogfood/targets -maxdepth 2 -type f | sort
|
||||
```
|
||||
|
||||
What to notice:
|
||||
|
||||
- the workspace owns the shared planning artifacts
|
||||
- the target repo drafts live under `targets/<alias>/`
|
||||
- no repo-local change exists yet in any repo
|
||||
|
||||
Confirm that for the `openspec` repo:
|
||||
|
||||
```bash
|
||||
test ! -e /path/to/your/openspec/repo/openspec/changes/workspace-dogfood && echo "openspec repo not materialized yet"
|
||||
```
|
||||
|
||||
## 6. Try `workspace open` in the order a real user would
|
||||
|
||||
### 6a. Root coordination open
|
||||
|
||||
```bash
|
||||
openspec workspace open
|
||||
```
|
||||
|
||||
What to look for:
|
||||
|
||||
- your preferred agent should launch
|
||||
- the session should open in workspace-root mode
|
||||
- `Attached repos:` should list the registered repos with valid local paths
|
||||
- the agent should have the registered repos, repo inventory, and active workspace changes available for coordination
|
||||
|
||||
If you want to inspect the prepared surface without launching the agent:
|
||||
|
||||
```bash
|
||||
openspec workspace open --prepare-only
|
||||
```
|
||||
|
||||
### 6b. Change-scoped open for the default agent
|
||||
|
||||
```bash
|
||||
openspec workspace open --change workspace-dogfood
|
||||
```
|
||||
|
||||
What to look for:
|
||||
|
||||
- your preferred agent should launch again, now change-scoped
|
||||
- only the targeted aliases should appear
|
||||
- owner and handoff notes should appear
|
||||
- non-targeted repos should not appear
|
||||
|
||||
If you want to inspect the prepared surface without launching the agent:
|
||||
|
||||
```bash
|
||||
openspec workspace open --change workspace-dogfood --prepare-only
|
||||
```
|
||||
|
||||
### 6c. Change-scoped open for Codex
|
||||
|
||||
```bash
|
||||
openspec workspace open --change workspace-dogfood --agent codex
|
||||
```
|
||||
|
||||
What to look for:
|
||||
|
||||
- Codex should launch with the workspace root plus only the targeted repos attached
|
||||
- the session should stay scoped to the targeted repos
|
||||
|
||||
If you want to inspect the generated prompt surface without launching Codex:
|
||||
|
||||
```bash
|
||||
openspec workspace open --change workspace-dogfood --agent codex --prepare-only
|
||||
```
|
||||
|
||||
### 6d. Change-scoped open for GitHub Copilot in VS Code
|
||||
|
||||
```bash
|
||||
openspec workspace open --change workspace-dogfood --agent github-copilot
|
||||
```
|
||||
|
||||
Inspect the generated artifacts:
|
||||
|
||||
```bash
|
||||
sed -n '1,200p' .github/prompts/opsx-workspace-open.prompt.md
|
||||
sed -n '1,200p' .openspec/workspace-open/github-copilot/workspace-dogfood.code-workspace
|
||||
```
|
||||
|
||||
What to notice:
|
||||
|
||||
- the prompt file lives under `.github/prompts/`
|
||||
- the VS Code workspace file lives under `.openspec/workspace-open/github-copilot/`
|
||||
- the `.code-workspace` file includes:
|
||||
- the workspace root
|
||||
- only the targeted repos
|
||||
|
||||
If you have VS Code installed, open the generated workspace:
|
||||
|
||||
```bash
|
||||
code .openspec/workspace-open/github-copilot/workspace-dogfood.code-workspace
|
||||
```
|
||||
|
||||
This is the real Copilot path: open the generated VS Code workspace and use Copilot there.
|
||||
|
||||
## 7. Use `status` as your control plane
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
openspec status --change workspace-dogfood
|
||||
openspec status --change workspace-dogfood --json
|
||||
```
|
||||
|
||||
What to look for:
|
||||
|
||||
- overall change state
|
||||
- target-by-target progress
|
||||
- owner and handoff notes
|
||||
- the next recommended step
|
||||
|
||||
This is the main command to re-enter an in-flight cross-repo change later.
|
||||
|
||||
## 8. Optional: try target-set changes before apply
|
||||
|
||||
This section is only interesting if you registered at least one repo that is **not** already in the change target list.
|
||||
|
||||
For example, if you registered `docs` but did not target it yet:
|
||||
|
||||
```bash
|
||||
openspec workspace targets workspace-dogfood --add docs
|
||||
find changes/workspace-dogfood/targets -maxdepth 2 -type f | sort
|
||||
openspec status --change workspace-dogfood
|
||||
```
|
||||
|
||||
What to notice:
|
||||
|
||||
- the `docs` target draft gets scaffolded
|
||||
- `status` now includes `docs`
|
||||
|
||||
Now remove it again before any apply:
|
||||
|
||||
```bash
|
||||
openspec workspace targets workspace-dogfood --remove docs
|
||||
find changes/workspace-dogfood/targets -maxdepth 2 -type f | sort
|
||||
openspec status --change workspace-dogfood
|
||||
```
|
||||
|
||||
What to notice:
|
||||
|
||||
- removing an unmaterialized target is allowed
|
||||
- the remaining targets stay intact
|
||||
|
||||
## 9. Materialize one real repo
|
||||
|
||||
Now hand execution off into the `openspec` repo:
|
||||
|
||||
```bash
|
||||
openspec apply --change workspace-dogfood --repo openspec
|
||||
openspec status --change workspace-dogfood
|
||||
find /path/to/your/openspec/repo/openspec/changes/workspace-dogfood -maxdepth 3 -type f | sort
|
||||
sed -n '1,200p' /path/to/your/openspec/repo/openspec/changes/workspace-dogfood/tasks.md
|
||||
```
|
||||
|
||||
What to notice:
|
||||
|
||||
- the workspace change still exists
|
||||
- the `openspec` repo now has a repo-local change
|
||||
- the source of truth for execution of that slice has moved into the repo
|
||||
|
||||
This is the core handoff:
|
||||
|
||||
- plan centrally
|
||||
- execute locally
|
||||
|
||||
## 10. Optional: trigger a guardrail after apply
|
||||
|
||||
Once a repo has crossed into repo-local execution, try to remove it from the target set:
|
||||
|
||||
```bash
|
||||
openspec workspace targets workspace-dogfood --remove openspec
|
||||
```
|
||||
|
||||
This should fail.
|
||||
|
||||
What to learn:
|
||||
|
||||
- workspace target mutation is allowed only while the alias is still workspace-owned
|
||||
- after apply, the workspace refuses to silently rewrite the target set around a repo-local slice
|
||||
|
||||
## 11. Continue from inside the real repo
|
||||
|
||||
Now switch into the `openspec` repo and look at the repo-local change directly:
|
||||
|
||||
```bash
|
||||
cd /path/to/your/openspec/repo
|
||||
find openspec/changes/workspace-dogfood -maxdepth 3 -type f | sort
|
||||
sed -n '1,200p' openspec/changes/workspace-dogfood/tasks.md
|
||||
```
|
||||
|
||||
This is where you would now do real implementation work.
|
||||
|
||||
When you want the workspace view again:
|
||||
|
||||
```bash
|
||||
cd "$HOME/.local/share/openspec/workspaces/openspec-dogfood"
|
||||
openspec status --change workspace-dogfood
|
||||
```
|
||||
|
||||
## 12. Optional: test `workspace doctor` on a real broken path
|
||||
|
||||
If you want to see the repair flow, temporarily break one alias in `.openspec/local.yaml`.
|
||||
|
||||
The simplest safe way is:
|
||||
|
||||
1. open `.openspec/local.yaml`
|
||||
2. replace one repo path with a missing path like `/tmp/does-not-exist`
|
||||
3. run:
|
||||
|
||||
```bash
|
||||
openspec workspace doctor
|
||||
openspec status --change workspace-dogfood
|
||||
```
|
||||
|
||||
Then repair the path in `.openspec/local.yaml` and run:
|
||||
|
||||
```bash
|
||||
openspec workspace doctor
|
||||
```
|
||||
|
||||
What to learn:
|
||||
|
||||
- broken local paths are a **doctor** problem
|
||||
- the fix belongs in `local.yaml`, not in the shared workspace metadata
|
||||
|
||||
## 13. Optional: complete and archive the full flow
|
||||
|
||||
If you want to exercise the whole lifecycle, finish the tasks and archive the repo-local change.
|
||||
|
||||
In the `openspec` repo:
|
||||
|
||||
```bash
|
||||
cd /path/to/your/openspec/repo
|
||||
perl -0pi -e 's/- \[ \]/- [x]/g' openspec/changes/workspace-dogfood/tasks.md
|
||||
openspec archive workspace-dogfood --yes --skip-specs --no-validate
|
||||
```
|
||||
|
||||
Back in the workspace:
|
||||
|
||||
```bash
|
||||
cd "$HOME/.local/share/openspec/workspaces/openspec-dogfood"
|
||||
perl -0pi -e 's/- \[ \]/- [x]/g' changes/workspace-dogfood/tasks/coordination.md
|
||||
openspec status --change workspace-dogfood
|
||||
openspec archive workspace-dogfood --workspace
|
||||
openspec status --change workspace-dogfood
|
||||
```
|
||||
|
||||
What to notice:
|
||||
|
||||
- repo-local archive and workspace archive are distinct
|
||||
- the workspace archive is the explicit “this cross-repo change is done” step
|
||||
|
||||
## 14. The re-entry flow you will actually use later
|
||||
|
||||
Once you have a real workspace in use, this is the normal re-entry sequence:
|
||||
|
||||
```bash
|
||||
cd "$HOME/.local/share/openspec/workspaces/openspec-dogfood"
|
||||
openspec status --change workspace-dogfood
|
||||
openspec workspace open --change workspace-dogfood
|
||||
openspec workspace open --change workspace-dogfood --agent codex
|
||||
openspec workspace open --change workspace-dogfood --agent github-copilot
|
||||
```
|
||||
|
||||
Use:
|
||||
|
||||
- `status` to understand current state and next action
|
||||
- `workspace open` to relaunch the root or change-scoped session
|
||||
- `workspace doctor` if aliases or paths look stale
|
||||
- `apply` only when you are ready to hand execution off into a repo
|
||||
|
||||
## If you want to remove the workspace later
|
||||
|
||||
The workspace is just a managed directory under:
|
||||
|
||||
```bash
|
||||
$HOME/.local/share/openspec/workspaces/
|
||||
```
|
||||
|
||||
So if you want to discard this dogfood workspace after testing:
|
||||
|
||||
```bash
|
||||
rm -rf "$HOME/.local/share/openspec/workspaces/openspec-dogfood"
|
||||
```
|
||||
|
||||
That does **not** delete your registered repos. It only deletes the coordination root.
|
||||
|
||||
## Optional convenience shortcuts
|
||||
|
||||
If you end up using the same repos repeatedly, you can set shell variables to avoid retyping long paths:
|
||||
|
||||
```bash
|
||||
export OPENSPEC_REPO="/path/to/your/openspec/repo"
|
||||
export WORKSPACE_ROOT="$HOME/.local/share/openspec/workspaces/openspec-dogfood"
|
||||
```
|
||||
|
||||
Those shortcuts are optional. They are not required for the walkthrough above.
|
||||
@@ -0,0 +1,130 @@
|
||||
# Workspace Mode
|
||||
|
||||
Workspace mode is the cross-repo coordination path for OpenSpec. It gives you one planning home for a change that spans multiple repositories, while keeping canonical specs and execution owned by the real repos.
|
||||
|
||||
## When To Use Workspace Mode
|
||||
|
||||
Use workspace mode when repo-local OpenSpec is no longer an honest representation of the work.
|
||||
|
||||
Typical signals:
|
||||
|
||||
- one change spans two or more repos
|
||||
- the canonical contract owner is different from one or more implementation repos
|
||||
- repos or teams need to move at different cadences
|
||||
- you need one place to pause, resume, or hand off a cross-repo change
|
||||
|
||||
Stay repo-local when:
|
||||
|
||||
- the work fits in one repo
|
||||
- the same repo owns planning, implementation, and archive
|
||||
- you do not need a separate coordination surface
|
||||
|
||||
Rule of thumb:
|
||||
|
||||
> Plan centrally, execute locally, preserve repo ownership.
|
||||
|
||||
Need a runnable walkthrough instead of a reference page? See [Workspace Demo](workspace-demo.md).
|
||||
|
||||
## Recommended First Run
|
||||
|
||||
Most people should start with the guided setup wizard:
|
||||
|
||||
```bash
|
||||
openspec workspace setup
|
||||
```
|
||||
|
||||
That flow:
|
||||
|
||||
1. creates the managed workspace root
|
||||
2. prompts for one or more repo paths and aliases
|
||||
3. stores optional owner and handoff notes
|
||||
4. runs `openspec workspace doctor`
|
||||
5. stores a preferred workspace-open agent in `.openspec/local.yaml`
|
||||
6. offers to open the workspace immediately using that preferred agent
|
||||
|
||||
Use the lower-level commands directly when you already know the exact workspace shape you want or when you are scripting against the workspace model.
|
||||
|
||||
## Supported CLI Flow
|
||||
|
||||
The current supported v0 flow is:
|
||||
|
||||
```bash
|
||||
openspec workspace setup
|
||||
openspec workspace list
|
||||
openspec new change <id> --targets <alias-a,alias-b>
|
||||
openspec workspace targets <id> --add <alias-c> --remove <alias-d>
|
||||
openspec workspace open [--change <id>] [--name <workspace>] [--agent claude|codex|github-copilot] [--prepare-only]
|
||||
openspec apply --change <id> --repo <alias>
|
||||
openspec status --change <id>
|
||||
```
|
||||
|
||||
The equivalent manual setup path is:
|
||||
|
||||
```bash
|
||||
openspec workspace create <name>
|
||||
openspec workspace add-repo <alias> <path> [--owner "<team or person>"] [--handoff "<next step>"]
|
||||
```
|
||||
|
||||
What each step does:
|
||||
|
||||
1. `workspace setup` is the onboarding path. It creates the workspace, registers repos, validates the registry, stores a preferred workspace-open agent, and can optionally launch the workspace immediately.
|
||||
2. `workspace list` shows the locally managed workspaces OpenSpec knows about.
|
||||
3. `workspace create` and `workspace add-repo` remain the manual setup path. `workspace create` creates a managed coordination root with `.openspec/` metadata and top-level `changes/`. `workspace add-repo` registers stable repo aliases. Repo paths stay local in `.openspec/local.yaml`. Optional owner and handoff notes are committed in `.openspec/workspace.yaml`.
|
||||
4. `new change --targets` creates one workspace change with shared planning artifacts plus per-target draft slices.
|
||||
5. `workspace targets <id>` adjusts the target set without manual file edits. It scaffolds added draft slices, removes unmaterialized draft slices, and refuses add or remove mutations once the same change ID already has repo-local execution or archive state for that alias.
|
||||
6. `workspace open` launches a workspace-root coordination session. If you are already inside a workspace root, it uses that workspace. If you are outside a workspace and only one managed workspace exists, it uses that automatically. If multiple managed workspaces exist, it prompts interactively or you can pass `--name <workspace>`. When you omit `--agent`, OpenSpec uses the preferred agent stored during setup, or prompts once and persists it for older workspaces with no stored preference.
|
||||
7. Workspace-root mode opens the workspace working set: the coordination root plus registered repos with valid local paths. It also gives the agent the registered repo inventory, owner or handoff notes, and active workspace changes so it can explore before proposal creation.
|
||||
8. `workspace open --change <id>` adds focused change context for an existing workspace change. Use `--agent codex` when you want Codex launched with the workspace working set attached, or `--agent github-copilot` when you want VS Code opened on a generated `.code-workspace` file.
|
||||
9. `workspace open --prepare-only` or `workspace open --json` prepares the surfaces without launching an external tool. Use that when you want to inspect or script the generated state.
|
||||
10. `apply --change <id> --repo <alias>` materializes one repo-local execution surface. After that point, repo-local execution remains local to that repo.
|
||||
11. `status --change <id>` from the workspace root rolls up coordination state, repo progress, blockers, owner or handoff notes, and the next action.
|
||||
|
||||
## Re-Enter An Existing Workspace
|
||||
|
||||
When you return to an in-flight cross-repo change:
|
||||
|
||||
1. Run `openspec status --change <id>` to see the overall state, affected repos, owner or handoff notes, and the next step.
|
||||
2. Run `openspec workspace open` when you want the root coordination session. You can run this from anywhere if OpenSpec can uniquely resolve the workspace. Add `--name <workspace>` when more than one managed workspace exists.
|
||||
3. Run `openspec workspace open --change <id>` when you want the current planning context reopened with just the targeted repos in view.
|
||||
4. Run `openspec workspace targets <id> --add <alias>` or `--remove <alias>` if the repo scope changed and that alias has not already crossed into repo-local execution for the same change ID.
|
||||
5. Run `openspec workspace doctor` if `status` reports a stale or missing repo alias.
|
||||
|
||||
If you need to explore or plan across the workspace, `openspec workspace open` without `--change` launches the workspace-root session with registered repo roots attached. The supported workspace-open agents are `claude`, `codex`, and `github-copilot`. The default agent comes from the workspace-local preferred agent stored in `.openspec/local.yaml`.
|
||||
|
||||
If you create a targeted workspace change from a launched root session, stop after the change is created. OpenSpec records that scope upgrade and reopens the next session change-scoped. Today that automatic upgrade is implemented as a relaunch or continue flow for Claude and Codex, not a live directory attach inside the existing TUI.
|
||||
|
||||
For GitHub Copilot, `workspace open` targets VS Code rather than Copilot CLI:
|
||||
|
||||
- it writes the scoped prompt file to `.github/prompts/opsx-workspace-open.prompt.md`
|
||||
- it writes a managed `.code-workspace` file under `.openspec/workspace-open/github-copilot/`
|
||||
- in workspace-root mode that workspace file includes the coordination root plus registered repos with valid local paths
|
||||
- in change-scoped mode it includes the coordination root plus only the targeted repos
|
||||
|
||||
## Hand Off Work To Another Repo Owner
|
||||
|
||||
Owner and handoff metadata are lightweight coordination notes for the workspace registry:
|
||||
|
||||
- `--owner` is the repo owner, primary contact, or team that should own the repo-local slice.
|
||||
- `--handoff` is the short next-step note another engineer should follow when they pick up that repo.
|
||||
|
||||
You can add or update those notes later without changing local repo paths:
|
||||
|
||||
```bash
|
||||
openspec workspace update-repo <alias> --owner "<team or person>" --handoff "<next step>"
|
||||
```
|
||||
|
||||
You can also adjust the target set later without editing `.openspec.yaml` by hand:
|
||||
|
||||
```bash
|
||||
openspec workspace targets <id> --add <alias-a,alias-b>
|
||||
openspec workspace targets <id> --remove <alias-c>
|
||||
```
|
||||
|
||||
That command keeps authority handoff explicit. If the same change ID already exists or was already archived in a target repo, `workspace targets` fails instead of silently mutating the workspace target set around repo-local execution.
|
||||
|
||||
The committed workspace metadata stays machine-safe:
|
||||
|
||||
- `.openspec/workspace.yaml` stores aliases plus optional owner or handoff notes
|
||||
- `.openspec/local.yaml` stores machine-specific repo paths
|
||||
|
||||
That split keeps shared workspace state portable while still letting each machine resolve local repo roots.
|
||||
@@ -0,0 +1,206 @@
|
||||
# Decision Space Navigation — Research Session
|
||||
**Date:** 2026-04-07
|
||||
|
||||
## Context
|
||||
|
||||
Exploring whether OpenSpec's linear assembly-line workflow (requirements → design → tasks) can be replaced with a more iterative, non-linear system where users work on any component in any order with continuous feedback.
|
||||
|
||||
---
|
||||
|
||||
## 1. The Starting Point: Assembly Line vs Iterative
|
||||
|
||||
**Current model:** OpenSpec enforces ordering via an ArtifactGraph DAG. Artifacts have hard gates — tasks are blocked until both specs and design are "done."
|
||||
|
||||
**Desired model:** User can work on any part in any order. System provides feedback on what's incomplete/inconsistent, but never blocks.
|
||||
|
||||
### Patterns explored:
|
||||
- **Blackboard Architecture** (1970s, Hearsay-II) — multiple specialists read/write shared state, controller suggests what to work on
|
||||
- **Stigmergy** — agents coordinate by modifying the environment (workspace is the pheromone trail)
|
||||
- **Tuple Spaces / Linda** — decoupled communication through shared memory
|
||||
- **ECS (Entity Component System)** — game engine pattern where systems process entities matching their component signature
|
||||
- **Society of Mind** (Minsky) — intelligence from many simple agents each handling a narrow concern
|
||||
|
||||
### Key design:
|
||||
- **Workspace** — shared state, items with maturity levels (sketch/draft/solid/complete)
|
||||
- **Concerns** — pluggable perspectives defined as YAML prompt files (security, PM, QA, etc.)
|
||||
- **The Loop** — classify → capture → dispatch concerns → surface findings
|
||||
|
||||
---
|
||||
|
||||
## 2. The IDE Analogy — Tested and Found Wanting
|
||||
|
||||
### Hypothesis
|
||||
Background LLM agents act as "language servers" that continuously analyze a shared workspace, like how IDEs surface type errors and lint warnings.
|
||||
|
||||
### Agent debate results (4 agents ran in parallel):
|
||||
|
||||
**The analogy breaks down on the properties that matter most:**
|
||||
|
||||
| IDE Property | Transfers to Specs? | Why |
|
||||
|---|---|---|
|
||||
| Formal grammar | NO | Specs are natural language, no AST |
|
||||
| Objective correctness | PARTIALLY | Some checks are objective (dangling refs), high-value ones are subjective |
|
||||
| Low false positive rate | NO | LLMs hallucinate. >67% false positive rate = users stop looking (IBM SOC research) |
|
||||
| Deterministic trust | NO | Same input → different output. Users can't trust it like a type checker |
|
||||
| Speed (<100ms) | NO | LLM calls are 5-30s. Not ambient, just slow consultation |
|
||||
| Incrementality | PARTIALLY | Specs are small enough for brute-force re-analysis |
|
||||
| Actionability | PARTIALLY | "Add return type here" vs "this section may conflict with section 3" |
|
||||
| Progressive disclosure | YES | Pure UX pattern, transfers cleanly |
|
||||
| Composability | NO | Multiple LLM concerns will contradict each other |
|
||||
|
||||
**Market research confirmed:** No one has shipped a true "IDE for specs" that stuck for general product work. QVscribe works in aerospace/medical (bad requirements kill people). ChatPRD works because it's on-demand, not ambient.
|
||||
|
||||
### What survived the critique:
|
||||
The shift from **review-time to authoring-time** feedback is genuinely valuable. Finding contradictions while writing — not days later in review — is better. The question is delivery mechanism.
|
||||
|
||||
---
|
||||
|
||||
## 3. Ambient Suggestions — The Graveyard and Survivors
|
||||
|
||||
### What died:
|
||||
- **Clippy (1997-2003)** — interruption without intelligence, high dismissal cost, couldn't learn
|
||||
- **Cortana proactive suggestions** — 10% usage, generic, required dedicated pane
|
||||
- **Google Now cards** — ambient card deck abandoned within 4 years
|
||||
- **Apple Siri Suggestions** — 73% of users say "little to no value"
|
||||
|
||||
### What survived:
|
||||
- **Grammarly** — 40M+ users. Inline underlines, zero cost to ignore, passive/contextual
|
||||
- **Gmail Smart Compose** — 70% adoption. Ghost text, Tab to accept, zero dismissal cost
|
||||
- **GitHub Copilot** — 21-30% acceptance rate. Same inline ghost text pattern. BUT sentiment dropping (70% → 60%)
|
||||
- **Nest thermostat** — Gold standard: invisible when correct. You see outcomes, not suggestions
|
||||
|
||||
### The fundamental law:
|
||||
**The cost of ignoring a suggestion must be lower than the cost of evaluating it, or users disable the system.**
|
||||
|
||||
### The pattern:
|
||||
| Factor | Survives | Dies |
|
||||
|---|---|---|
|
||||
| Where | Inline, in workflow | Separate pane, pop-up |
|
||||
| Ignore cost | Zero | Must actively dismiss |
|
||||
| Accuracy | High precision | High recall, many false positives |
|
||||
| Learning | Adapts over time | Same for everyone |
|
||||
| Agency | User chooses | System interrupts |
|
||||
|
||||
---
|
||||
|
||||
## 4. The Reframe: Decision Space Navigation
|
||||
|
||||
### Key insight
|
||||
Specs aren't about **construction** (like code). They're about **deciding** — navigating a problem space with many open dimensions. Gaps aren't errors to fix; they're unmade decisions.
|
||||
|
||||
The right question isn't "how do we show inline errors" — it's "how do we help someone navigate a large decision space efficiently?"
|
||||
|
||||
### The good collaborator model
|
||||
A good PM doesn't present a list of 12 open questions. They follow your thread and pull you toward the adjacent unexplored area:
|
||||
|
||||
> "Solid. What happens when they deny the permission?"
|
||||
|
||||
Gaps are the agent's **internal state, not a UI element.** Surface ONE thing at a time, the most relevant to the user's current train of thought.
|
||||
|
||||
### Two types of gaps:
|
||||
- **Decision gaps** — only the user can resolve ("should we support multiple providers?"). Surface as questions.
|
||||
- **Research gaps** — system can explore autonomously ("what OAuth libraries does the project use?"). Run in background.
|
||||
|
||||
### The model: Research team, not IDE
|
||||
- **Lead agent** (foreground) — follows your thread, asks the next relevant question
|
||||
- **Research agents** (background) — explore research gaps, report findings
|
||||
- **Internal state** (never shown raw) — full map of all gaps, dependencies, priorities
|
||||
|
||||
---
|
||||
|
||||
## 5. UX: Spatial vs Temporal
|
||||
|
||||
### The fundamental tension
|
||||
Chat is temporal (sequential). Decision spaces are spatial (multi-dimensional). Can't represent a map in a line.
|
||||
|
||||
### Three models explored:
|
||||
|
||||
**Model 1: Workspace file as passive map**
|
||||
Agent maintains a markdown file open in user's editor. Chat is focused work, file is the map. Works today, zero infrastructure.
|
||||
|
||||
**Model 2: Named focus areas**
|
||||
`/focus auth` — switch between dimensions. Agent gives a briefing on entry ("here's where we are, what changed since last time"). Still a single chat thread.
|
||||
|
||||
**Model 3: Parallel conversations**
|
||||
Each dimension is its own persistent agent conversation. Map view shows the landscape. Cross-impacts propagate automatically. Requires new runtime model.
|
||||
|
||||
### Core structure all models share:
|
||||
```
|
||||
MAP (spatial, always available, shows whole landscape)
|
||||
├── DIMENSION (focused workspace, deep conversation)
|
||||
├── DIMENSION
|
||||
├── DIMENSION
|
||||
CROSS-CUTS (propagation layer, how decisions ripple)
|
||||
```
|
||||
|
||||
### What's genuinely new:
|
||||
**Decision propagation.** When you make a decision in one dimension, the system understands implications for other dimensions, updates their state, and briefs you when you arrive. No existing tool does this well.
|
||||
|
||||
---
|
||||
|
||||
## 6. Desktop App — Not Worth It
|
||||
|
||||
### Agent debate results (4 agents):
|
||||
|
||||
**Market evidence on spatial tools:**
|
||||
| Tool | Approach | Outcome |
|
||||
|---|---|---|
|
||||
| Muse (Ink & Switch) | Spatial-first | Dead ($120K ARR peak) |
|
||||
| Roam Research | Graph-first | Collapsed from $200M hype |
|
||||
| Scapple, TheBrain, Kinopio | Spatial/graph | Permanent niche |
|
||||
| Obsidian Canvas | Canvas as feature | "Half-baked," minimal sustained use |
|
||||
| Miro | Spatial whiteboard | $665M ARR but only for brainstorming |
|
||||
| Linear | Structured-first | Won |
|
||||
| Notion | Structured-first | Won |
|
||||
| Claude Code, Cursor | Text/chat-first | Won |
|
||||
|
||||
**Cognitive Fit Theory (Vessey, 1991):** Spatial helps with spatial tasks (seeing relationships). Hurts analytical tasks (prioritizing, sequencing). Planning requires both. Answer: **structured-first with spatial views as a lens.**
|
||||
|
||||
**The Muse lesson:** Spatial was great for ideation but users couldn't bridge to execution. Exactly the transition our product needs.
|
||||
|
||||
**Engineering cost:** 70% of effort goes to UI, 30% to AI. Inverted from where value lives.
|
||||
|
||||
### Recommendation:
|
||||
1. **Weeks 1-4:** Build the AI. Ship as Claude Code skill. Markdown workspace as map.
|
||||
2. **Months 2-3:** Add lightweight web viz (ReactFlow). Browser tab alongside terminal.
|
||||
3. **Months 4-6:** Invest in whatever surface drives retention.
|
||||
4. **Probably never:** Desktop app. Moat is in AI judgment, not renderer.
|
||||
|
||||
---
|
||||
|
||||
## 7. Where's the Moat? (The Uncomfortable Truth)
|
||||
|
||||
### What the "judgment layer" actually is:
|
||||
|
||||
| Component | What it really is |
|
||||
|---|---|
|
||||
| Detect cross-impacts | A prompt |
|
||||
| Rank gaps by importance | A prompt |
|
||||
| Decide when to speak | A prompt with rules |
|
||||
| Propagate decisions | A prompt |
|
||||
| Choose which concern to consult | A few lines of routing code |
|
||||
| Classify user input | A prompt |
|
||||
|
||||
**Day one, it's prompts and files. No moat.** Someone with Claude and a markdown file gets 80% of the value.
|
||||
|
||||
### Where real brain could emerge over time:
|
||||
|
||||
| Timeline | Component | Moat type |
|
||||
|---|---|---|
|
||||
| Day 1 | Prompts + files | None |
|
||||
| Month 3 | Formal decision graph with deterministic constraint propagation | Structural — code enforces what LLM guesses |
|
||||
| Month 6 | Learned silence model from usage patterns | Data — when to speak, trained on real sessions |
|
||||
| Month 12 | Temporal provenance + decision decay | Product — tracking how decisions evolve over weeks |
|
||||
|
||||
### The honest framing:
|
||||
The moat isn't in technology on day one. It's in **product design** — getting the conversation rhythm right. When to ask, how to bridge dimensions, how to surface cross-impacts. Design moats are real (Linear, Figma) but defended by taste and iteration speed, not patents.
|
||||
|
||||
---
|
||||
|
||||
## Open Questions
|
||||
|
||||
1. Is the "good collaborator" conversational model enough, or do users actually need to see the decision map?
|
||||
2. Does the formal decision graph (month 3 milestone) actually improve over LLM reasoning, or is it unnecessary engineering?
|
||||
3. How many dimensions does a typical feature planning session actually have? If it's 4-6, markdown is fine. If it's 15, we need something more.
|
||||
4. Can the "silence problem" (when to speak vs stay quiet) be solved with heuristics, or does it genuinely require learned models?
|
||||
5. Is this a product or a feature? Could this be a mode within an existing tool (Claude Code, Linear, Notion) rather than standalone?
|
||||
@@ -0,0 +1,27 @@
|
||||
# Phase 00 Manual Test
|
||||
|
||||
## Scenarios Run
|
||||
|
||||
- Copied the committed `happy-path` fixture into two fresh temp roots by cloning both `workspace/` and `repos/` outside Vitest.
|
||||
- Confirmed one copied workspace root contains `.openspec/` and `changes/`, and does not contain a repo-local `openspec/` directory.
|
||||
- Ran `node "$OPENSPEC_REPO/dist/cli/index.js" list --json` from the copied `repos/app` root, with `OPENSPEC_REPO` set to the current OpenSpec checkout, and parsed stdout as JSON.
|
||||
- Mutated `repos/app/README.md` in the first temp root and confirmed the same file in the second temp root remained unchanged.
|
||||
- Ran `rg -n -F "$OPENSPEC_REPO" test/fixtures/workspace-poc` to confirm the current checkout path is not committed into the workspace fixtures.
|
||||
|
||||
## Results
|
||||
|
||||
- All manual smoke scenarios passed.
|
||||
- The workspace copy preserved the expected Phase 00 layout: `.openspec/` and `changes/` exist at the workspace root, and no nested repo-local `openspec/` directory exists there.
|
||||
- The direct CLI invocation exited `0`, produced empty `stderr`, and returned parseable JSON from the attached repo fixture. The current payload shape is an object with a `changes` array containing the fixture-backed `app-ui-polish` change.
|
||||
- Mutating one fresh fixture copy did not affect the second copy, which confirms the Phase 00 isolation property outside the automated test harness.
|
||||
- The committed fixture seeds do not contain the current checkout path.
|
||||
|
||||
## Fixes Applied
|
||||
|
||||
- No product-code fixes were needed from this manual pass.
|
||||
- Corrected the first smoke attempt to use the attached repo as the real process working directory; `openspec list` does not expose a `--cwd` flag.
|
||||
|
||||
## Residual Risks
|
||||
|
||||
- No residual risks were found within the implemented Phase 00 scope.
|
||||
- This manual smoke still validates attached-repo execution rather than future workspace command entrypoints, because workspace commands land in later phases.
|
||||
@@ -0,0 +1,24 @@
|
||||
# Phase 00 Summary
|
||||
|
||||
## Changes Made
|
||||
|
||||
- Added `test/helpers/workspace-sandbox.ts` to clone workspace fixtures into unique temp roots, split managed workspace state from attached repos, and rewrite `.openspec/local.yaml` repo paths to canonical absolute paths at runtime.
|
||||
- Added `test/helpers/workspace-assertions.ts` with reusable checks for workspace layout, committed absolute-path leakage, target membership, and materialization invariants.
|
||||
- Added workspace fixture seeds under `test/fixtures/workspace-poc/` for `empty`, `happy-path`, and `dirty`.
|
||||
- Reserved workspace test suite locations with new coverage in `test/core/workspace/`, `test/commands/workspace/`, and `test/cli-e2e/workspace/`.
|
||||
- Added focused Phase 00 tests in `test/core/workspace/workspace-sandbox.test.ts` and `test/cli-e2e/workspace/workspace-sandbox-cli.test.ts`.
|
||||
|
||||
## Tests Performed
|
||||
|
||||
- `pnpm vitest run test/core/workspace/workspace-sandbox.test.ts test/cli-e2e/workspace/workspace-sandbox-cli.test.ts`
|
||||
|
||||
## Results
|
||||
|
||||
- All 6 Phase 00 tests passed under the current forked Vitest worker configuration.
|
||||
- The harness creates `.openspec/` plus `changes/` at the workspace root and does not create an inner repo-local `openspec/`.
|
||||
- Fixture clones mutate independently, committed fixture seeds stay free of absolute repo paths, and `runCLI()` can execute JSON commands inside sandbox repos without spinner noise in stderr.
|
||||
|
||||
## Blockers And Next-Step Notes
|
||||
|
||||
- No blockers in this phase.
|
||||
- The harness is ready for Phase 01 and later workspace command coverage to reuse the same `workspaceSandbox()` helper and fixture seeds.
|
||||
@@ -0,0 +1,25 @@
|
||||
# Phase 00 Verification
|
||||
|
||||
## Checks Performed
|
||||
|
||||
- Re-read the Phase 00 block in `ROADMAP.md` plus the current `SUMMARY.md`, `VERIFY.md`, and `MANUAL_TEST.md` artifacts in fresh context.
|
||||
- Inspected the Phase 00 implementation in `test/helpers/workspace-sandbox.ts`, `test/helpers/workspace-assertions.ts`, `test/core/workspace/workspace-sandbox.test.ts`, `test/cli-e2e/workspace/workspace-sandbox-cli.test.ts`, and the committed fixtures under `test/fixtures/workspace-poc/`.
|
||||
- Re-ran the focused Phase 00 suite with `pnpm vitest run test/core/workspace/workspace-sandbox.test.ts test/cli-e2e/workspace/workspace-sandbox-cli.test.ts`.
|
||||
- Reproduced the manual smoke by copying the committed `happy-path` fixture into a fresh temp root, confirming the workspace layout, running `node "$OPENSPEC_REPO/dist/cli/index.js" list --json` from `repos/app`, and parsing the JSON output.
|
||||
- Ran `rg -n -F "$(pwd)" test/fixtures/workspace-poc || true` to confirm the committed fixture seeds do not embed the current checkout path.
|
||||
- Ran `git diff --check -- test/helpers/workspace-sandbox.ts test/helpers/workspace-assertions.ts test/core/workspace/workspace-sandbox.test.ts test/cli-e2e/workspace/workspace-sandbox-cli.test.ts test/fixtures/workspace-poc notes/workspace-poc/phase-00-test-harness ROADMAP.md` after the note updates to confirm the phase files remain whitespace-clean.
|
||||
|
||||
## Issues Found
|
||||
|
||||
- Documentation quality issue: `MANUAL_TEST.md` recorded a workstation-specific absolute CLI path, which made the smoke instructions less portable than the rest of the phase artifacts.
|
||||
- No harness, fixture, or acceptance-test defects were found during the verification pass.
|
||||
|
||||
## Fixes Applied
|
||||
|
||||
- Updated `MANUAL_TEST.md` to describe the CLI smoke with `OPENSPEC_REPO` instead of a machine-specific absolute path.
|
||||
- Updated this verification note to reflect the fresh-context checks that were actually rerun for Phase 00.
|
||||
|
||||
## Residual Risks
|
||||
|
||||
- No residual risks were found within the implemented Phase 00 scope.
|
||||
- `test/commands/workspace/` remains intentionally reserved until later phases add workspace commands, so the current CLI compatibility proof is limited to attached repo roots.
|
||||
@@ -0,0 +1,33 @@
|
||||
# Phase 01 Manual Test
|
||||
|
||||
## Scenarios Run
|
||||
|
||||
- Rebuilt the CLI with `pnpm run build` so the manual pass used the current source tree.
|
||||
- Ran `node bin/openspec.js --no-color workspace --help` in a fresh temp XDG config/data root with telemetry disabled.
|
||||
- Ran `node bin/openspec.js --no-color workspace create alpha-team-binmanual` in that same fresh context.
|
||||
- Inspected the created workspace root on disk, including `.openspec/workspace.yaml`, `.openspec/local.yaml`, `changes/`, and `.gitignore`.
|
||||
- Re-ran `node bin/openspec.js --no-color workspace create alpha-team-binmanual` to confirm duplicate handling.
|
||||
- Ran `node bin/openspec.js --no-color workspace create "Alpha Team"` to confirm invalid-name handling.
|
||||
|
||||
## Results
|
||||
|
||||
- `workspace --help` exposed the `create <name>` entrypoint as expected.
|
||||
- Successful create produced a managed workspace root under the temporary XDG data directory with:
|
||||
- `.openspec/workspace.yaml`
|
||||
- `.openspec/local.yaml`
|
||||
- `changes/`
|
||||
- `.gitignore` containing `/.openspec/local.yaml`
|
||||
- The created workspace root did not contain `openspec/changes` or any inner `openspec/` repo-local layout.
|
||||
- `workspace.yaml` stored the workspace name and empty repo registry as expected for a new workspace.
|
||||
- `local.yaml` stored the local overlay version and an empty `repoPaths` map.
|
||||
- Re-running `workspace create` with the same name failed cleanly with an actionable duplicate-workspace error and did not mutate the existing workspace.
|
||||
- Creating a workspace with `Alpha Team` failed cleanly with the expected kebab-case validation error.
|
||||
|
||||
## Fixes Applied
|
||||
|
||||
- None.
|
||||
|
||||
## Residual Risks
|
||||
|
||||
- None found within the Phase 01 scope.
|
||||
- Broader automated command and CLI coverage for `workspace create` still belongs to Phase 02.
|
||||
@@ -0,0 +1,37 @@
|
||||
# Phase 01 Summary
|
||||
|
||||
## Changes Made
|
||||
|
||||
- Added `src/commands/workspace.ts` and registered a new `openspec workspace` command group with a `workspace create <name>` entrypoint.
|
||||
- Added `src/core/workspace/create.ts` to create managed workspace roots under the global OpenSpec data directory at `workspaces/<name>`.
|
||||
- Added `src/core/setup/bootstrap.ts` and reused it from both `workspace create` and the existing `InitCommand` so writable-target checks and directory bootstrapping stay on one shared setup path.
|
||||
- `workspace create` now creates a dedicated workspace layout with `.openspec/workspace.yaml`, `.openspec/local.yaml`, and top-level `changes/`, without creating a repo-local `openspec/` tree.
|
||||
- `workspace create` now writes `/.openspec/local.yaml` into the workspace root `.gitignore` so the local overlay is treated as local-only state.
|
||||
- Duplicate and invalid workspace names now fail with explicit, actionable errors.
|
||||
|
||||
## Tests Performed
|
||||
|
||||
- `pnpm run build`
|
||||
- `pnpm vitest run test/core/init.test.ts test/core/workspace/workspace-sandbox.test.ts test/cli-e2e/workspace/workspace-sandbox-cli.test.ts`
|
||||
- Fresh CLI smoke in temp XDG config/data roots:
|
||||
- `node dist/cli/index.js --no-color workspace create alpha-team-2`
|
||||
- repeated create for duplicate handling
|
||||
- invalid create with `Alpha Team`
|
||||
|
||||
## Results
|
||||
|
||||
- Build passed.
|
||||
- 48 focused Vitest checks passed, including existing init coverage and workspace harness compatibility coverage.
|
||||
- Fresh CLI smoke created a managed workspace at `XDG_DATA_HOME/openspec/workspaces/alpha-team-2` with:
|
||||
- `.openspec/workspace.yaml`
|
||||
- `.openspec/local.yaml`
|
||||
- `changes/`
|
||||
- `.gitignore` containing `/.openspec/local.yaml`
|
||||
- The created workspace root did not contain `openspec/changes`.
|
||||
- Re-running against the same name failed explicitly without mutating the workspace.
|
||||
- Invalid names failed with a workspace-specific kebab-case error.
|
||||
|
||||
## Blockers And Next-Step Notes
|
||||
|
||||
- No blockers in Phase 01.
|
||||
- Automated command/unit/e2e coverage for `workspace create` is still intentionally thin and should be expanded in Phase 02.
|
||||
@@ -0,0 +1,38 @@
|
||||
# Phase 01 Verification
|
||||
|
||||
## Checks Performed
|
||||
|
||||
- Read the Phase 01 block in `ROADMAP.md` plus the current `SUMMARY.md` and `MANUAL_TEST.md` artifacts.
|
||||
- Reviewed the implementation boundary for this phase in:
|
||||
- `src/cli/index.ts`
|
||||
- `src/commands/workspace.ts`
|
||||
- `src/core/workspace/create.ts`
|
||||
- `src/core/setup/bootstrap.ts`
|
||||
- `src/core/init.ts`
|
||||
- Rebuilt the CLI with `pnpm run build`.
|
||||
- Ran focused regression coverage:
|
||||
- `pnpm vitest run test/core/init.test.ts test/core/workspace/workspace-sandbox.test.ts test/cli-e2e/workspace/workspace-sandbox-cli.test.ts`
|
||||
- Ran fresh CLI verification in temporary XDG config/data roots with telemetry disabled:
|
||||
- `node dist/cli/index.js --no-color workspace --help`
|
||||
- `node dist/cli/index.js --no-color workspace create alpha-team-verify`
|
||||
- repeated create for duplicate handling
|
||||
- `node dist/cli/index.js --no-color workspace create "Alpha Team"` for invalid-name handling
|
||||
- Inspected the generated workspace root on disk and confirmed:
|
||||
- `.openspec/workspace.yaml` exists
|
||||
- `.openspec/local.yaml` exists
|
||||
- top-level `changes/` exists
|
||||
- `.gitignore` contains `/.openspec/local.yaml`
|
||||
- no nested `openspec/` or `openspec/changes` was created
|
||||
|
||||
## Issues Found
|
||||
|
||||
- None.
|
||||
|
||||
## Fixes Applied
|
||||
|
||||
- None.
|
||||
|
||||
## Residual Risks
|
||||
|
||||
- No blocking issues were found within the Phase 01 scope.
|
||||
- Dedicated automated command/e2e coverage for `workspace create` is still intentionally deferred to Phase 02, so create-specific confidence still comes from this fresh CLI smoke plus the shared regression suites.
|
||||
@@ -0,0 +1,34 @@
|
||||
# Phase 02 Manual Test
|
||||
|
||||
Manual pass date: 2026-04-17
|
||||
Phase cycle: 1
|
||||
Stage: `manual-test`
|
||||
|
||||
## Scenarios Run
|
||||
|
||||
- Rebuilt the CLI with `pnpm run build` so the manual pass used the current source tree.
|
||||
- In a fresh `mktemp` root with isolated `XDG_CONFIG_HOME` and `XDG_DATA_HOME`, and `OPEN_SPEC_TELEMETRY_DISABLED=1`, ran `node bin/openspec.js --no-color workspace --help`.
|
||||
- Ran `node bin/openspec.js --no-color workspace create alpha-manual`.
|
||||
- Inspected the created `alpha-manual` workspace root for `.openspec/workspace.yaml`, `.openspec/local.yaml`, `changes/`, `.gitignore`, and absence of any nested repo-local `openspec/` directory.
|
||||
- Ran `node bin/openspec.js --no-color workspace create beta-json --json` and parsed stdout as JSON.
|
||||
- Re-ran `node bin/openspec.js --no-color workspace create alpha-manual` and compared file hashes for `.gitignore`, `.openspec/workspace.yaml`, and `.openspec/local.yaml` before and after the duplicate attempt.
|
||||
|
||||
## Results
|
||||
|
||||
- `workspace --help` exposed `create [options] <name>` under the `workspace` command.
|
||||
- `workspace create alpha-manual` exited `0`, produced no stderr output, and created a managed workspace root under the isolated XDG data directory.
|
||||
- The created workspace contained `.openspec/workspace.yaml`, `.openspec/local.yaml`, `changes/`, and `.gitignore` with `/.openspec/local.yaml`.
|
||||
- `workspace.yaml` contained `version: 1`, `name: alpha-manual`, and `repos: {}`.
|
||||
- `local.yaml` contained `version: 1` and `repoPaths: {}`.
|
||||
- The workspace root did not contain any nested repo-local `openspec/` directory.
|
||||
- `workspace create beta-json --json` exited `0`, emitted parseable JSON on stdout only, and returned the expected absolute paths plus `gitignoreStatus: "created"`.
|
||||
- Re-running `workspace create alpha-manual` exited `1`, emitted the expected blank line on stdout plus an actionable error on stderr, and left the existing workspace files unchanged.
|
||||
|
||||
## Fixes Applied
|
||||
|
||||
- None. No product or test changes were required from this manual pass.
|
||||
- Refreshed this artifact so the manual-test record matches the fresh cycle-1 run.
|
||||
|
||||
## Residual Risks
|
||||
|
||||
- None found within the Phase 02 scope.
|
||||
@@ -0,0 +1,34 @@
|
||||
# Phase 02 Summary
|
||||
|
||||
## Changes Made
|
||||
|
||||
- Added focused core coverage in `test/core/workspace/workspace-create.test.ts` for managed workspace path resolution plus metadata and overlay initialization.
|
||||
- Added command-layer coverage in `test/commands/workspace/create.test.ts` for the `workspace create` action, including happy path, duplicate handling, invalid names, and machine-readable output.
|
||||
- Added CLI e2e coverage in `test/cli-e2e/workspace/workspace-create-cli.test.ts` for help output, JSON cleanliness, exit codes, on-disk layout, and duplicate-create safety.
|
||||
- Added a minimal `--json` success and error path to `src/commands/workspace.ts` so acceptance 02.6 is concrete and testable instead of hypothetical.
|
||||
- Updated `test/commands/workspace/README.md` now that the reserved command-layer directory contains real coverage.
|
||||
|
||||
## Tests Performed
|
||||
|
||||
- `pnpm run build`
|
||||
- `pnpm vitest run test/core/workspace/workspace-create.test.ts test/core/workspace/workspace-sandbox.test.ts test/commands/workspace/create.test.ts test/cli-e2e/workspace/workspace-create-cli.test.ts test/cli-e2e/workspace/workspace-sandbox-cli.test.ts`
|
||||
- Fresh CLI verification and manual smoke in isolated XDG config/data roots with telemetry disabled:
|
||||
- `node bin/openspec.js --no-color workspace --help`
|
||||
- `node bin/openspec.js --no-color workspace create alpha-manual`
|
||||
- `node bin/openspec.js --no-color workspace create beta-json --json`
|
||||
- repeated `workspace create alpha-manual` for duplicate handling
|
||||
- `git diff --check -- src/commands/workspace.ts test/core/workspace/workspace-create.test.ts test/commands/workspace/create.test.ts test/cli-e2e/workspace/workspace-create-cli.test.ts test/commands/workspace/README.md`
|
||||
|
||||
## Results
|
||||
|
||||
- Build passed.
|
||||
- The focused workspace suite passed with 15/15 tests.
|
||||
- `workspace --help` now documents `create [options] <name>`.
|
||||
- Successful create still produces a usable managed workspace root with `.openspec/workspace.yaml`, `.openspec/local.yaml`, top-level `changes/`, and no nested repo-local `openspec/`.
|
||||
- `workspace create --json` now emits clean parseable JSON with no stderr noise on success.
|
||||
- Duplicate create attempts still exit `1`, surface an actionable error, and leave the existing workspace files unchanged.
|
||||
|
||||
## Blockers And Next-Step Notes
|
||||
|
||||
- No blockers in Phase 02.
|
||||
- No new roadmap phases were required from this pass.
|
||||
@@ -0,0 +1,43 @@
|
||||
# Phase 02 Verification
|
||||
|
||||
## Checks Performed
|
||||
|
||||
- Read the Phase 02 block in `ROADMAP.md` plus the current `SUMMARY.md`, `VERIFY.md`, and `MANUAL_TEST.md` for this phase before running checks.
|
||||
- Reviewed the current Phase 02 implementation boundary in:
|
||||
- `src/commands/workspace.ts`
|
||||
- `src/core/workspace/create.ts`
|
||||
- `src/cli/index.ts`
|
||||
- `test/core/workspace/workspace-create.test.ts`
|
||||
- `test/commands/workspace/create.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-create-cli.test.ts`
|
||||
- `test/helpers/workspace-assertions.ts`
|
||||
- `test/helpers/run-cli.ts`
|
||||
- `test/commands/workspace/README.md`
|
||||
- Rebuilt the CLI with `pnpm run build`.
|
||||
- Ran the focused regression suite:
|
||||
- `pnpm vitest run test/core/workspace/workspace-create.test.ts test/core/workspace/workspace-sandbox.test.ts test/commands/workspace/create.test.ts test/cli-e2e/workspace/workspace-create-cli.test.ts test/cli-e2e/workspace/workspace-sandbox-cli.test.ts`
|
||||
- Re-ran fresh CLI verification in isolated XDG roots with telemetry disabled:
|
||||
- `node bin/openspec.js --no-color workspace --help`
|
||||
- `node bin/openspec.js --no-color workspace create alpha-manual`
|
||||
- inspected `.openspec/workspace.yaml`, `.openspec/local.yaml`, `.gitignore`, and the top-level `changes/` directory
|
||||
- confirmed there is no nested repo-local `openspec/` directory
|
||||
- `node bin/openspec.js --no-color workspace create beta-json --json`
|
||||
- repeated `workspace create alpha-manual` to verify duplicate handling, exit code `1`, and unchanged workspace files
|
||||
- Ran `git diff --check` on the Phase 02 source, test, and helper files.
|
||||
- Validated documentation quality against the live command surface by comparing the current help text and test assertions with the phase notes.
|
||||
|
||||
## Issues Found
|
||||
|
||||
- No product or test failures were found in the current Phase 02 scope.
|
||||
- The existing `VERIFY.md` reflected the earlier implementation pass rather than this independent verification pass, so the phase notes were stale.
|
||||
|
||||
## Fixes Applied
|
||||
|
||||
- Refreshed this verification note so it documents the current independent verification run, the checks actually performed, and the current status of the phase.
|
||||
- Refreshed `MANUAL_TEST.md` to match the current manual pass and to keep the phase documentation aligned with the live CLI behavior.
|
||||
|
||||
## Residual Risks
|
||||
|
||||
- No blocking issues remain within the Phase 02 scope.
|
||||
- Phase 02 still stays within its intended boundary: managed workspace creation, metadata initialization, and validation coverage only. Later workspace behaviors remain outside this phase.
|
||||
- `--json` discipline is currently proven for `workspace create`; future workspace commands should follow the same stdout/stderr contract when they add machine-readable output.
|
||||
@@ -0,0 +1,42 @@
|
||||
# Phase 03 Manual Test
|
||||
|
||||
Manual test stage re-run in fresh isolated XDG state on 2026-04-17 for ROADMAP Phase 03, cycle 1.
|
||||
|
||||
## Scenarios run
|
||||
|
||||
- Built the current CLI with `pnpm run build`.
|
||||
- Created a managed workspace with `openspec workspace create phase03-manual --json`.
|
||||
- Registered a repo with `openspec workspace add-repo app <symlink-path> --json`.
|
||||
- Confirmed the persisted split:
|
||||
- `.openspec/workspace.yaml` stored only the committed alias entry `app: {}`
|
||||
- `.openspec/local.yaml` stored only the canonical absolute repo path
|
||||
- no absolute repo path leaked into `.openspec/workspace.yaml`
|
||||
- Exercised `workspace add-repo` failure cases from the real CLI:
|
||||
- duplicate alias registration
|
||||
- missing repo path
|
||||
- repo path without repo-local `openspec/`
|
||||
- Ran `openspec workspace doctor --json` on a healthy workspace and confirmed a clean pass.
|
||||
- Corrupted fresh workspace metadata to simulate doctor-only recovery scenarios, then ran `openspec workspace doctor --json` and confirmed:
|
||||
- `missing-local-path` for a committed alias missing from `.openspec/local.yaml`
|
||||
- `non-canonical-path` for a symlinked local overlay path
|
||||
- `extra-local-alias` for a local-only alias not present in committed metadata
|
||||
- non-zero exit and no mutation of `.openspec/workspace.yaml` or `.openspec/local.yaml`
|
||||
- Removed a previously registered repo directory, reran `openspec workspace doctor --json`, and confirmed `missing-repo-path` with no overlay mutation.
|
||||
- Removed `openspec/` from a previously registered repo, reran `openspec workspace doctor --json`, and confirmed `missing-openspec-state`.
|
||||
|
||||
## Results
|
||||
|
||||
- All manual smoke scenarios passed against the current built CLI.
|
||||
- `workspace add-repo` still persists committed alias metadata separately from local absolute paths.
|
||||
- Canonicalization still resolves symlink inputs before persistence.
|
||||
- `workspace doctor` reports healthy state correctly, reports stale or broken registry state with the expected issue codes, exits non-zero on problems, and does not rewrite workspace files during diagnostics.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No product fixes were required from this manual-test pass.
|
||||
- Updated this manual-test note to reflect the fresh-context run and expanded doctor scenarios.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No residual Phase 03 functional issues were found during manual testing.
|
||||
- Dedicated automated regression coverage for these flows is still expected in Phase 04.
|
||||
@@ -0,0 +1,48 @@
|
||||
# Phase 03 Summary
|
||||
|
||||
## Changes made
|
||||
|
||||
- Added shared workspace metadata helpers in `src/core/workspace/metadata.ts` so committed workspace state and local overlay state are read and written consistently.
|
||||
- Added repo registry and doctor logic in `src/core/workspace/registry.ts`.
|
||||
- Extended `src/commands/workspace.ts` with:
|
||||
- `openspec workspace add-repo <alias> <path>`
|
||||
- `openspec workspace doctor`
|
||||
- Kept committed alias registration in `.openspec/workspace.yaml`.
|
||||
- Kept canonical absolute repo paths in `.openspec/local.yaml`.
|
||||
- Validated repo registration inputs for:
|
||||
- kebab-case alias shape
|
||||
- existing directory paths
|
||||
- repo-local OpenSpec state via `openspec/`
|
||||
- Implemented doctor diagnostics for:
|
||||
- missing local alias mappings
|
||||
- missing repo paths
|
||||
- non-canonical local overlay paths
|
||||
- extra local-only aliases
|
||||
- missing repo-local OpenSpec state
|
||||
|
||||
## Tests or research performed
|
||||
|
||||
- `pnpm run build`
|
||||
- `pnpm vitest run test/core/workspace/workspace-create.test.ts test/core/workspace/workspace-sandbox.test.ts test/commands/workspace/create.test.ts test/cli-e2e/workspace/workspace-create-cli.test.ts test/cli-e2e/workspace/workspace-sandbox-cli.test.ts`
|
||||
- Fresh CLI smoke in temporary XDG roots covering:
|
||||
- `workspace create`
|
||||
- `workspace add-repo` success with a symlinked repo path
|
||||
- duplicate alias failure
|
||||
- missing path failure
|
||||
- missing `openspec/` failure
|
||||
- `workspace doctor` success on a healthy workspace
|
||||
- `workspace doctor --json` failure reporting stale path and local-overlay drift without mutating files
|
||||
|
||||
## Results
|
||||
|
||||
- Build passed.
|
||||
- Existing workspace regression tests passed: 15/15.
|
||||
- `workspace add-repo` writes only the alias to `.openspec/workspace.yaml` and only the canonical absolute path to `.openspec/local.yaml`.
|
||||
- Canonicalization resolved a symlinked repo input to the real absolute path before persistence.
|
||||
- `workspace doctor` reports missing repos and overlay drift and exits non-zero without rewriting workspace files.
|
||||
- No absolute repo path leaked into committed workspace metadata during the fresh acceptance run.
|
||||
|
||||
## Blockers and next-step notes
|
||||
|
||||
- No blockers in Phase 03.
|
||||
- Phase 04 should add permanent automated coverage for the new registry and doctor behaviors across core, command, and CLI layers.
|
||||
@@ -0,0 +1,35 @@
|
||||
# Phase 03 Verification
|
||||
|
||||
## Checks performed
|
||||
|
||||
- Re-read the Phase 03 block in `ROADMAP.md` and the current phase artifacts in `notes/workspace-poc/phase-03-repo-registry/`.
|
||||
- Inspected the Phase 03 implementation boundaries in:
|
||||
- `src/core/workspace/metadata.ts`
|
||||
- `src/core/workspace/registry.ts`
|
||||
- `src/commands/workspace.ts`
|
||||
- `src/cli/index.ts`
|
||||
- `src/utils/file-system.ts`
|
||||
- Rebuilt from the current workspace with `pnpm run build`.
|
||||
- Re-ran the current workspace-focused automated coverage with `pnpm vitest run test/core/workspace test/commands/workspace test/cli-e2e/workspace`.
|
||||
- Verified the acceptance cases in a fresh temporary XDG workspace using the built CLI:
|
||||
- `workspace create phase03-verify`
|
||||
- `workspace add-repo app <symlink-path>`
|
||||
- confirmed `.openspec/workspace.yaml` stored only the committed alias entry
|
||||
- confirmed `.openspec/local.yaml` stored only the canonical absolute repo path
|
||||
- confirmed duplicate alias, missing path, and missing `openspec/` failures
|
||||
- confirmed `workspace doctor` passes on healthy state
|
||||
- corrupted `.openspec/local.yaml` and confirmed `workspace doctor --json` reports stale state with a non-zero exit and no YAML mutation
|
||||
- Reviewed `openspec workspace --help` to confirm the new subcommands are discoverable from the CLI surface.
|
||||
|
||||
## Issues found
|
||||
|
||||
- No implementation, boundary, or documentation defects were found during this verification pass.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- Updated this verification note to reflect the fresh-context verification run.
|
||||
- No code changes were required.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- Direct automated coverage for `workspace add-repo` and `workspace doctor` is still deferred to Phase 04, so this phase currently relies on manual verification plus adjacent workspace regression tests.
|
||||
@@ -0,0 +1,42 @@
|
||||
# Phase 04 Manual Test
|
||||
|
||||
Manual smoke re-run with the built CLI in fresh isolated XDG state on 2026-04-17 for ROADMAP Phase 04, cycle 1.
|
||||
|
||||
## Scenarios run
|
||||
|
||||
- Built the current CLI with `pnpm run build`.
|
||||
- Created a managed workspace with `openspec workspace create phase04-manual-cycle1 --json`.
|
||||
- Created three real repo fixtures with repo-local `openspec/changes` state: `app`, `api`, and `docs`.
|
||||
- Registered all three repos through the real CLI with:
|
||||
- `openspec workspace add-repo app <path> --json`
|
||||
- `openspec workspace add-repo api <path> --json`
|
||||
- `openspec workspace add-repo docs <path> --json`
|
||||
- Ran `openspec workspace doctor --json` and confirmed a clean pass with:
|
||||
- `registeredAliasCount: 3`
|
||||
- `localAliasCount: 3`
|
||||
- `issues: []`
|
||||
- `status: "ok"`
|
||||
- Edited `.openspec/local.yaml` to replace the `api` path with a relative non-canonical path and reran `openspec workspace doctor --json`.
|
||||
- Confirmed the drift run returned exit code `1` with a `non-canonical-path` issue for alias `api`.
|
||||
- Removed `docs/openspec/` from a registered repo and reran `openspec workspace doctor --json`.
|
||||
- Confirmed the doctor run returned exit code `1` with a `missing-openspec-state` issue for alias `docs`.
|
||||
- Edited `.openspec/local.yaml` to replace the `app` path with a missing repo root and reran `openspec workspace doctor --json`.
|
||||
- Confirmed the stale run returned exit code `1` with a `missing-repo-path` issue for alias `app`.
|
||||
- Repaired `.openspec/local.yaml` by restoring the canonical absolute repo path and restored `docs/openspec/`, then reran `openspec workspace doctor --json`.
|
||||
- Compared `.openspec/workspace.yaml` before and after the local overlay edits to confirm committed metadata stayed unchanged.
|
||||
|
||||
## Results
|
||||
|
||||
- All manual smoke scenarios passed.
|
||||
- Multiple repo additions remained readable and doctor-clean in one workspace.
|
||||
- Doctor detected alias/path drift, missing repo-local `openspec/`, and missing repo roots with the expected non-zero exit behavior.
|
||||
- Repairing the stale `local.yaml` entry restored doctor success.
|
||||
- `.openspec/workspace.yaml` remained unchanged across local path mutations, so committed metadata stayed stable while only the local overlay changed.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No additional product fixes were required during this manual smoke pass.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No user-visible Phase 04 issues were found in this manual smoke run.
|
||||
@@ -0,0 +1,46 @@
|
||||
# Phase 04 Summary
|
||||
|
||||
## Changes made
|
||||
|
||||
- Added core registry coverage in `test/core/workspace/registry.test.ts` for:
|
||||
- alias trimming and invalid alias rejection
|
||||
- canonical repo-path persistence
|
||||
- committed metadata stability when `local.yaml` changes
|
||||
- doctor diagnostics for missing local mappings, missing repo roots, missing `openspec/`, alias/path drift, and extra local aliases
|
||||
- Added command-surface coverage in `test/commands/workspace/registry.test.ts` for:
|
||||
- `workspace add-repo`
|
||||
- healthy `workspace doctor`
|
||||
- stale `workspace doctor`
|
||||
- Added CLI e2e coverage in `test/cli-e2e/workspace/workspace-registry-cli.test.ts` for:
|
||||
- multiple repo additions in one workspace
|
||||
- healthy doctor JSON output
|
||||
- stale-path detection and repair via `.openspec/local.yaml`
|
||||
- Fixed two issues exposed by the new coverage in `src/commands/workspace.ts`:
|
||||
- corrected pluralized doctor status text for `aliases` and `entries`
|
||||
- changed doctor issue exits to set `process.exitCode = 1` after printing results instead of calling `process.exit(1)` inside the action body
|
||||
|
||||
## Tests or research performed
|
||||
|
||||
- `pnpm vitest run test/core/workspace test/commands/workspace test/cli-e2e/workspace`
|
||||
- `pnpm run build`
|
||||
- `pnpm vitest run test/core/workspace/registry.test.ts test/commands/workspace/registry.test.ts test/cli-e2e/workspace/workspace-registry-cli.test.ts`
|
||||
- Fresh built-CLI smoke on 2026-04-17 covering:
|
||||
- `workspace create phase04-manual --json`
|
||||
- two successful `workspace add-repo ... --json` registrations
|
||||
- healthy `workspace doctor --json`
|
||||
- forced stale `local.yaml` repo path
|
||||
- successful doctor recovery after repairing the stale local path
|
||||
|
||||
## Results
|
||||
|
||||
- All targeted workspace tests passed: 23/23 in the full workspace slice and 8/8 in the Phase 04-focused verification slice.
|
||||
- Build passed.
|
||||
- Doctor now reports clean human-readable pluralization in healthy output.
|
||||
- Doctor still exits non-zero when issues are present, while keeping the command-surface control flow stable enough for interception and tests.
|
||||
- The registry stayed readable after multiple repo additions, committed metadata remained path-free and stable, and stale local overlay repair restored doctor success.
|
||||
|
||||
## Blockers and next-step notes
|
||||
|
||||
- No blockers remain for Phase 04.
|
||||
- No new roadmap phases were required from this test pass.
|
||||
- Phase 05 can build on the now-covered repo registry and doctor behavior.
|
||||
@@ -0,0 +1,38 @@
|
||||
# Phase 04 Verification
|
||||
|
||||
Verification re-run in a fresh shell context on 2026-04-17 for ROADMAP Phase 04, cycle 1.
|
||||
|
||||
## Checks performed
|
||||
|
||||
- Re-read the Phase 04 block in `ROADMAP.md`.
|
||||
- Reviewed the current phase artifacts for scope and documentation quality:
|
||||
- `notes/workspace-poc/phase-04-test-repo-registry/SUMMARY.md`
|
||||
- `notes/workspace-poc/phase-04-test-repo-registry/MANUAL_TEST.md`
|
||||
- Reviewed the implementation and test coverage for this phase:
|
||||
- `src/core/workspace/registry.ts`
|
||||
- `src/commands/workspace.ts`
|
||||
- `test/core/workspace/registry.test.ts`
|
||||
- `test/commands/workspace/registry.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-registry-cli.test.ts`
|
||||
- Verified that the implementation boundaries still match the phase intent:
|
||||
- committed repo aliases live in `.openspec/workspace.yaml`
|
||||
- local absolute repo paths live only in `.openspec/local.yaml`
|
||||
- doctor reports missing local mappings, missing repo roots, missing `openspec/`, non-canonical path drift, and extra local aliases
|
||||
- Rebuilt the CLI with `pnpm run build`.
|
||||
- Re-ran the Phase 04-focused automated slice with:
|
||||
- `pnpm vitest run test/core/workspace/registry.test.ts test/commands/workspace/registry.test.ts test/cli-e2e/workspace/workspace-registry-cli.test.ts`
|
||||
- Re-ran the broader workspace regression slice with:
|
||||
- `pnpm vitest run test/core/workspace test/commands/workspace test/cli-e2e/workspace`
|
||||
|
||||
## Issues found
|
||||
|
||||
- None.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- None required.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- None found for Phase 04 in this verification pass.
|
||||
- The phase artifacts remain consistent with the implemented scope, and the acceptance coverage is in place across core, command, and CLI layers.
|
||||
@@ -0,0 +1,64 @@
|
||||
# Phase 05 Manual Test
|
||||
|
||||
Manual smoke re-run in a fresh temp/XDG context on 2026-04-17 (Australia/Sydney) for ROADMAP Phase 05, cycle 1.
|
||||
|
||||
## Scenarios run
|
||||
|
||||
- Rebuilt the current CLI with `pnpm run build`.
|
||||
- Checked `node dist/cli/index.js new change --help` and confirmed the Phase 05 surface still documents:
|
||||
- `--description <text>` as seeding the initial change artifact
|
||||
- `--targets <aliases>` for workspace-targeted change creation
|
||||
- Created a brand-new isolated CLI environment with:
|
||||
- `OPENSPEC_TELEMETRY=0`
|
||||
- fresh `XDG_CONFIG_HOME`
|
||||
- fresh `XDG_DATA_HOME`
|
||||
- Created three real repo roots under the temp sandbox:
|
||||
- `app`
|
||||
- `api`
|
||||
- `docs`
|
||||
- Seeded each repo root with repo-local OpenSpec state via `openspec/changes/` so the real `workspace add-repo` path validation would accept them.
|
||||
- Ran `node dist/cli/index.js workspace create phase05-manual-cycle1 --json`.
|
||||
- Ran the real repo registration flow from inside that managed workspace:
|
||||
- `node dist/cli/index.js workspace add-repo app <path> --json`
|
||||
- `node dist/cli/index.js workspace add-repo api <path> --json`
|
||||
- `node dist/cli/index.js workspace add-repo docs <path> --json`
|
||||
- Ran the target-aware create flow:
|
||||
- `node dist/cli/index.js new change shared-auth --targets app,api --description "Cross-repo auth rollout"`
|
||||
- Inspected the created workspace change and confirmed:
|
||||
- `changes/shared-auth/.openspec.yaml` exists
|
||||
- metadata recorded `schema: spec-driven`
|
||||
- metadata recorded `targets: [app, api]`
|
||||
- `proposal.md`, `design.md`, and `tasks/coordination.md` exist
|
||||
- `targets/app/tasks.md` and `targets/api/tasks.md` exist
|
||||
- `targets/app/specs/` and `targets/api/specs/` exist
|
||||
- Verified the untargeted and targeted repos all remained free of repo-local materialization:
|
||||
- `<app>/openspec/changes/shared-auth` does not exist
|
||||
- `<api>/openspec/changes/shared-auth` does not exist
|
||||
- `<docs>/openspec/changes/shared-auth` does not exist
|
||||
- Exercised the negative CLI cases in the same fresh workspace:
|
||||
- `node dist/cli/index.js new change dup-targets --targets app,app`
|
||||
- `node dist/cli/index.js new change unknown-target --targets app,missing`
|
||||
- reran `node dist/cli/index.js new change shared-auth --targets app,api`
|
||||
- Re-ran `node dist/cli/index.js workspace doctor --json` after targeted creation.
|
||||
|
||||
## Results
|
||||
|
||||
- All manual smoke scenarios passed.
|
||||
- The real targeted-create flow produced the expected central workspace scaffold under `changes/shared-auth/`.
|
||||
- The workspace change metadata recorded the exact requested target set: `app`, `api`.
|
||||
- Duplicate target aliases failed with a non-zero exit and the expected actionable message: `Duplicate target alias 'app' in --targets. Remove duplicates and retry.`
|
||||
- Unknown target aliases failed with a non-zero exit and the expected actionable message naming the missing alias and registered aliases.
|
||||
- Reusing the same workspace change ID failed predictably with the existing duplicate-change error.
|
||||
- No repo-local change directories were created in any registered repo during `new change`.
|
||||
- `workspace doctor --json` still returned `status: "ok"` after targeted creation, so the registry remained healthy.
|
||||
- The generated metadata still stored `created: 2026-04-16` during this 2026-04-17 Australia/Sydney run because the shared date path remains UTC-based.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No product fixes were required during this manual-test pass.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No Phase 05 user-visible regressions were found in this manual smoke cycle.
|
||||
- The shared metadata `created` field still reflects UTC day boundaries rather than local date boundaries. That was observed again here, but it is existing shared behavior rather than a Phase 05-specific regression.
|
||||
- Permanent automated coverage for this flow is still expected in Phase 06.
|
||||
@@ -0,0 +1,52 @@
|
||||
# Phase 05 Summary
|
||||
|
||||
## Changes made
|
||||
|
||||
- Added workspace-aware change creation in [src/commands/workflow/new-change.ts](/Users/tabishbidiwale/fission/repos/openspec/src/commands/workflow/new-change.ts) so `openspec new change <id> --targets <a,b,c>` now detects managed workspaces, requires explicit targets there, and still preserves the existing repo-local path outside a workspace.
|
||||
- Added [src/core/workspace/change-create.ts](/Users/tabishbidiwale/fission/repos/openspec/src/core/workspace/change-create.ts) to:
|
||||
- parse and validate `--targets`
|
||||
- reject duplicate or unknown aliases before writing anything
|
||||
- create workspace changes under `changes/<id>/`
|
||||
- scaffold `proposal.md`, `design.md`, `tasks/coordination.md`, and per-target `targets/<alias>/tasks.md` plus `targets/<alias>/specs/`
|
||||
- Extended change metadata in [src/core/artifact-graph/types.ts](/Users/tabishbidiwale/fission/repos/openspec/src/core/artifact-graph/types.ts) and reused the shared metadata writer so workspace changes persist explicit `targets` in `.openspec.yaml`.
|
||||
- Added `findWorkspaceRoot()` in [src/core/workspace/registry.ts](/Users/tabishbidiwale/fission/repos/openspec/src/core/workspace/registry.ts) so the command can detect workspace topology without disturbing the existing registry and doctor flows.
|
||||
- Extracted schema resolution into [src/utils/change-utils.ts](/Users/tabishbidiwale/fission/repos/openspec/src/utils/change-utils.ts) so repo-local and workspace change creation both resolve schemas through the same path.
|
||||
- Updated [src/cli/index.ts](/Users/tabishbidiwale/fission/repos/openspec/src/cli/index.ts) to expose `--targets` on `openspec new change`.
|
||||
- Clarified the `openspec new change --help` text in [src/cli/index.ts](/Users/tabishbidiwale/fission/repos/openspec/src/cli/index.ts) so `--description` no longer incorrectly promises a `README.md` write for workspace-targeted changes.
|
||||
- Expanded [test/utils/change-metadata.test.ts](/Users/tabishbidiwale/fission/repos/openspec/test/utils/change-metadata.test.ts) so shared metadata coverage now includes persisted target aliases and duplicate-target rejection.
|
||||
|
||||
## Tests or research performed
|
||||
|
||||
- `pnpm run build`
|
||||
- `pnpm vitest run test/utils/change-metadata.test.ts test/utils/change-utils.test.ts test/core/workspace/registry.test.ts`
|
||||
- `node dist/cli/index.js new change --help`
|
||||
- Fresh isolated CLI smoke on 2026-04-17 (Australia/Sydney) with telemetry disabled:
|
||||
- `openspec workspace create phase05-manual`
|
||||
- `openspec workspace add-repo app <path>`
|
||||
- `openspec workspace add-repo api <path>`
|
||||
- `openspec workspace add-repo docs <path>`
|
||||
- `openspec new change shared-auth --targets app,api --description "Cross-repo auth rollout"`
|
||||
- verified `changes/shared-auth/.openspec.yaml`
|
||||
- verified `proposal.md`, `design.md`, `tasks/coordination.md`, and `targets/{app,api}/{tasks.md,specs/}`
|
||||
- verified no `openspec/changes/shared-auth` directory was created in any registered repo
|
||||
- verified duplicate-target, unknown-target, and duplicate-change-ID failures
|
||||
- Fresh isolated post-create health check:
|
||||
- `openspec workspace doctor --json` after targeted creation
|
||||
|
||||
## Results
|
||||
|
||||
- Build passed.
|
||||
- Focused regression coverage passed: 51/51 tests.
|
||||
- Targeted workspace changes now record the exact target list in `.openspec.yaml`.
|
||||
- The workspace change layout now includes the central planning scaffold plus per-target task/spec partitions under `changes/<id>/targets/`.
|
||||
- Unknown targets and duplicate targets fail before any workspace artifacts are written, with actionable error messages.
|
||||
- Repo-local repos remained untouched during creation; no target repo received a materialized `openspec/changes/<id>` directory.
|
||||
- Duplicate workspace change IDs still fail predictably at the workspace change path.
|
||||
- `workspace doctor --json` still reported `status: "ok"` after targeted change creation, so the new flow does not corrupt workspace registry state.
|
||||
- The CLI help output now describes `--description` generically enough to match both repo-local and workspace-targeted change creation.
|
||||
|
||||
## Blockers and next-step notes
|
||||
|
||||
- No blockers remain for Phase 05.
|
||||
- No new roadmap phases were required from this implementation pass.
|
||||
- Phase 06 should add dedicated permanent unit, command, and CLI coverage for the new workspace-targeted change path instead of relying on the focused shared regressions and CLI smoke used here.
|
||||
@@ -0,0 +1,43 @@
|
||||
# Phase 05 Verification
|
||||
|
||||
Independent verification re-run in a fresh context on 2026-04-17 (Australia/Sydney) for ROADMAP Phase 05, cycle 1.
|
||||
|
||||
## Checks performed
|
||||
|
||||
- Re-read the Phase 05 block in [ROADMAP.md](/Users/tabishbidiwale/fission/repos/openspec/ROADMAP.md) and the current phase artifacts in [SUMMARY.md](/Users/tabishbidiwale/fission/repos/openspec/notes/workspace-poc/phase-05-targeted-change-create/SUMMARY.md) and [MANUAL_TEST.md](/Users/tabishbidiwale/fission/repos/openspec/notes/workspace-poc/phase-05-targeted-change-create/MANUAL_TEST.md).
|
||||
- Reviewed the implementation boundary in:
|
||||
- [src/commands/workflow/new-change.ts](/Users/tabishbidiwale/fission/repos/openspec/src/commands/workflow/new-change.ts)
|
||||
- [src/core/workspace/change-create.ts](/Users/tabishbidiwale/fission/repos/openspec/src/core/workspace/change-create.ts)
|
||||
- [src/core/workspace/registry.ts](/Users/tabishbidiwale/fission/repos/openspec/src/core/workspace/registry.ts)
|
||||
- [src/utils/change-utils.ts](/Users/tabishbidiwale/fission/repos/openspec/src/utils/change-utils.ts)
|
||||
- [src/core/artifact-graph/types.ts](/Users/tabishbidiwale/fission/repos/openspec/src/core/artifact-graph/types.ts)
|
||||
- [src/cli/index.ts](/Users/tabishbidiwale/fission/repos/openspec/src/cli/index.ts)
|
||||
- [test/utils/change-metadata.test.ts](/Users/tabishbidiwale/fission/repos/openspec/test/utils/change-metadata.test.ts)
|
||||
- Confirmed `openspec new change --help` documents both `--targets` and the updated generic `--description` behavior.
|
||||
- Rebuilt the current tree with `pnpm run build`.
|
||||
- Re-ran focused regressions with `pnpm vitest run test/utils/change-metadata.test.ts test/utils/change-utils.test.ts test/core/workspace/registry.test.ts`.
|
||||
- Ran a fresh isolated CLI verification with the built CLI and telemetry disabled:
|
||||
- created a managed workspace
|
||||
- registered `app`, `api`, and `docs`
|
||||
- created `shared-auth` with `--targets app,api`
|
||||
- inspected `changes/shared-auth/.openspec.yaml`
|
||||
- confirmed `proposal.md`, `design.md`, `tasks/coordination.md`, and per-target `tasks.md` plus `specs/` directories
|
||||
- confirmed no repo-local `openspec/changes/shared-auth` directory was created in any registered repo
|
||||
- confirmed duplicate-target, unknown-target, and duplicate-change-ID failures returned non-zero exits with actionable messages
|
||||
- confirmed `openspec workspace doctor --json` returned `status: "ok"` after targeted creation
|
||||
- Observed that the generated metadata stored `created: 2026-04-16` during this 2026-04-17 Australia/Sydney verification run because the shared date path still uses UTC `toISOString()`.
|
||||
|
||||
## Issues found
|
||||
|
||||
- `openspec new change --help` still said `--description` adds text to `README.md`, which was inaccurate for workspace-targeted changes that seed `proposal.md` instead.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- Updated [src/cli/index.ts](/Users/tabishbidiwale/fission/repos/openspec/src/cli/index.ts) so `--description` is described as seeding the initial change artifact rather than specifically writing `README.md`.
|
||||
- Rebuilt the CLI and rechecked both `openspec new change --help` and the fresh targeted-create smoke flow after that text change.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No Phase 05 correctness blockers remain after verification.
|
||||
- Dedicated permanent automated coverage for workspace-targeted change creation is still intentionally deferred to Phase 06.
|
||||
- The shared metadata `created` date remains UTC-based. On 2026-04-17 in Australia/Sydney, the generated file stored `2026-04-16`. This is existing shared behavior rather than a Phase 05-specific regression.
|
||||
@@ -0,0 +1,47 @@
|
||||
# Phase 06 Manual Test
|
||||
|
||||
Manual pass date: 2026-04-17
|
||||
Phase cycle: 1
|
||||
Stage: `manual-test`
|
||||
|
||||
## Scenarios run
|
||||
|
||||
- Reused the current built CLI from `pnpm run build`.
|
||||
- Created a fresh isolated workspace by copying the `happy-path` workspace fixture and repo fixtures into a temporary directory.
|
||||
- Rewrote `.openspec/local.yaml` in the copied workspace so `app`, `api`, and `docs` pointed to canonical absolute repo paths inside the temporary fixture root.
|
||||
On this macOS host, that canonicalization resolved the temp repo roots under `/private/var/...`.
|
||||
- Created repo-local `openspec/changes/` directories in all three attached repos so `workspace doctor` exercised a healthy registered workspace.
|
||||
- Ran `OPEN_SPEC_TELEMETRY_DISABLED=1 node bin/openspec.js --no-color new change phase06-manual --targets app,api` from the workspace root.
|
||||
- Ran `OPEN_SPEC_TELEMETRY_DISABLED=1 node bin/openspec.js --no-color status --change phase06-manual --json`.
|
||||
- Ran `OPEN_SPEC_TELEMETRY_DISABLED=1 node bin/openspec.js --no-color workspace doctor --json`.
|
||||
- Ran `OPEN_SPEC_TELEMETRY_DISABLED=1 node bin/openspec.js --no-color new change phase06-bad --targets app,missing`.
|
||||
- Checked that no repo-local `openspec/changes/phase06-manual` or `openspec/changes/phase06-bad` directories existed in `app`, `api`, or `docs`.
|
||||
|
||||
## Results
|
||||
|
||||
- `new change phase06-manual --targets app,api` exited `0` and created `changes/phase06-manual/` in the workspace root.
|
||||
- The resulting workspace change kept the expected central planning topology:
|
||||
- `.openspec.yaml`
|
||||
- `proposal.md`
|
||||
- `design.md`
|
||||
- `tasks/coordination.md`
|
||||
- `targets/app/{tasks.md,specs/}`
|
||||
- `targets/api/{tasks.md,specs/}`
|
||||
- `status --change phase06-manual --json` exited `0` and returned parseable JSON for the workspace change.
|
||||
- The status JSON reported:
|
||||
- `proposal: done`
|
||||
- `design: done`
|
||||
- `specs: ready`
|
||||
- `tasks: blocked` by `specs`
|
||||
- `workspace doctor --json` exited `0` and returned `status: "ok"` with `issues: []`.
|
||||
- `new change phase06-bad --targets app,missing` exited `1` with `Unknown target alias: missing. Registered aliases: api, app, docs`.
|
||||
- No repo-local change directories were created in any attached repo for either the successful or rejected create attempt.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No product fixes were required during this manual-test pass.
|
||||
- The temporary workspace overlay was canonicalized before running `workspace doctor --json` so the copied fixture matched the CLI's expected path form on this macOS host.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- None found within the Phase 06 scope.
|
||||
@@ -0,0 +1,57 @@
|
||||
# Phase 06 Summary
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `implementation`
|
||||
|
||||
## Changes made
|
||||
|
||||
- Added workspace-aware change-container helpers in `src/core/workspace/metadata.ts` and reused them from:
|
||||
- `src/commands/workflow/shared.ts`
|
||||
- `src/core/artifact-graph/instruction-loader.ts`
|
||||
- Fixed the workflow path mismatch exposed by the new coverage so `status --change <name>` can read workspace-created changes from top-level `changes/` instead of only repo-local `openspec/changes/`.
|
||||
- Added an exact workspace-change topology assertion to `test/helpers/workspace-assertions.ts`.
|
||||
- Added focused core coverage in `test/core/workspace/change-create.test.ts` for:
|
||||
- `parseWorkspaceTargets()`
|
||||
- workspace change metadata
|
||||
- layout-only central planning scaffolds
|
||||
- unknown alias rejection
|
||||
- Added command-surface coverage in `test/commands/workflow/new-change.workspace.test.ts` for targeted change creation inside a registered workspace.
|
||||
- Added CLI e2e coverage in `test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts` for:
|
||||
- successful targeted creation
|
||||
- unknown alias rejection
|
||||
- untouched repo-local roots
|
||||
- healthy `status` and `workspace doctor` after creation
|
||||
|
||||
## Tests or research performed
|
||||
|
||||
- `pnpm run build`
|
||||
- `pnpm vitest --run test/core/workspace/change-create.test.ts test/commands/workflow/new-change.workspace.test.ts test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts`
|
||||
- `pnpm vitest --run test/core/artifact-graph/instruction-loader.test.ts test/commands/artifact-workflow.test.ts test/cli-e2e/workspace/workspace-registry-cli.test.ts test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts`
|
||||
- `git diff --check -- src/core/workspace/metadata.ts src/commands/workflow/shared.ts src/core/artifact-graph/instruction-loader.ts test/helpers/workspace-assertions.ts test/core/workspace/change-create.test.ts test/commands/workflow/new-change.workspace.test.ts test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts`
|
||||
- Fresh built-CLI smoke in an isolated copied workspace fixture with telemetry disabled:
|
||||
- `node bin/openspec.js --no-color new change phase06-manual --targets app,api`
|
||||
- `node bin/openspec.js --no-color status --change phase06-manual --json`
|
||||
- `node bin/openspec.js --no-color workspace doctor --json`
|
||||
- `node bin/openspec.js --no-color new change phase06-bad --targets app,missing`
|
||||
- explicit repo-root checks that no `openspec/changes/phase06-manual` or `openspec/changes/phase06-bad` directories were created under `app`, `api`, or `docs`
|
||||
|
||||
## Results
|
||||
|
||||
- Build passed.
|
||||
- The focused Phase 06 slice passed: 9/9 tests.
|
||||
- The broader regression slice that touches workflow loading and workspace registry behavior passed: 98/98 tests.
|
||||
- `new change --targets` now has direct coverage for rejecting aliases outside the workspace registry.
|
||||
- Workspace change creation is now proven to produce only:
|
||||
- central planning artifacts at the workspace change root
|
||||
- per-target partitions under `targets/<alias>/`
|
||||
- Successful targeted creation leaves repo-local `openspec/changes/` roots untouched before any materialization step.
|
||||
- `status --change` now succeeds for workspace-created changes and reports the expected incomplete planning state:
|
||||
- `proposal` and `design` are `done`
|
||||
- `specs` is `ready`
|
||||
- `tasks` is `blocked` by missing `specs`
|
||||
- `workspace doctor --json` still reports a healthy workspace after targeted change creation.
|
||||
|
||||
## Blockers and next-step notes
|
||||
|
||||
- No blockers remain for Phase 06.
|
||||
- No new bounded follow-up phases were required from this implementation pass.
|
||||
@@ -0,0 +1,48 @@
|
||||
# Phase 06 Verification
|
||||
|
||||
Verification re-run in a fresh shell context on 2026-04-17 for ROADMAP Phase 06, cycle 1.
|
||||
|
||||
## Checks performed
|
||||
|
||||
- Re-read the Phase 06 block in `ROADMAP.md`.
|
||||
- Reviewed the current phase artifacts for scope and note quality:
|
||||
- `notes/workspace-poc/phase-06-test-targeted-change-create/SUMMARY.md`
|
||||
- `notes/workspace-poc/phase-06-test-targeted-change-create/MANUAL_TEST.md`
|
||||
- Reviewed the implementation and tests touched by this phase:
|
||||
- `src/commands/workflow/new-change.ts`
|
||||
- `src/core/workspace/change-create.ts`
|
||||
- `src/core/workspace/metadata.ts`
|
||||
- `src/commands/workflow/shared.ts`
|
||||
- `src/core/artifact-graph/instruction-loader.ts`
|
||||
- `test/helpers/workspace-assertions.ts`
|
||||
- `test/core/workspace/change-create.test.ts`
|
||||
- `test/commands/workflow/new-change.workspace.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts`
|
||||
- Rebuilt the CLI with `pnpm run build`.
|
||||
- Re-ran the focused Phase 06 automated slice:
|
||||
- `pnpm vitest --run test/core/workspace/change-create.test.ts test/commands/workflow/new-change.workspace.test.ts test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts`
|
||||
- Re-ran the closest regression slice for shared workflow path resolution and workspace health:
|
||||
- `pnpm vitest --run test/core/artifact-graph/instruction-loader.test.ts test/commands/artifact-workflow.test.ts test/cli-e2e/workspace/workspace-registry-cli.test.ts test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts`
|
||||
- Ran `git diff --check` on the Phase 06 source, helper, and test files.
|
||||
- Re-executed the manual smoke against a freshly copied `happy-path` workspace fixture with telemetry disabled:
|
||||
- `node bin/openspec.js --no-color new change phase06-manual --targets app,api`
|
||||
- `node bin/openspec.js --no-color status --change phase06-manual --json`
|
||||
- `node bin/openspec.js --no-color workspace doctor --json`
|
||||
- `node bin/openspec.js --no-color new change phase06-bad --targets app,missing`
|
||||
- explicit repo-root checks that no `openspec/changes/phase06-manual` or `openspec/changes/phase06-bad` directories were created under `app`, `api`, or `docs`
|
||||
|
||||
## Issues found
|
||||
|
||||
- No remaining product or test failures were found in the current Phase 06 scope.
|
||||
- During the first manual smoke setup, the temporary workspace overlay used raw `/var/...` paths; on this macOS host `workspace doctor --json` correctly flagged them as `non-canonical-path` drift because the canonical repo roots resolve under `/private/var/...`.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No additional fixes were required during this verification pass.
|
||||
- Corrected the manual verification setup to rewrite `.openspec/local.yaml` with canonicalized repo paths before the final `workspace doctor --json` check.
|
||||
- Refreshed this verification artifact so it reflects the current post-fix validation run instead of an empty placeholder.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No blocking risks remain within the Phase 06 scope.
|
||||
- This phase stays bounded to targeted workspace change creation and its pre-materialization stability checks; later workspace-open and materialization behavior remains outside this phase.
|
||||
@@ -0,0 +1,189 @@
|
||||
# Phase 07 Decision
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `implementation`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
## Recommended contract
|
||||
|
||||
The minimum honest v0 contract for `workspace open` is:
|
||||
|
||||
- `openspec workspace open` is a planning-only session-prep command.
|
||||
- `openspec workspace open --change <id>` is a change-scoped attached-roots session-prep command.
|
||||
- v0 produces a usable instruction surface for one supported agent path instead of promising generic external process launch.
|
||||
- v0 officially supports only `--agent claude`. Omitting `--agent` defaults to `claude`.
|
||||
- `workspace open --change <id>` resolves only that change's targeted repos and hard-fails if any target repo is unresolved.
|
||||
- `workspace open` never materializes repo-local changes and never replaces `openspec apply --change <id> --repo <alias>`.
|
||||
|
||||
This is the smallest contract that is still real:
|
||||
|
||||
- planning-only mode is useful even when no repos are ready
|
||||
- attached mode is honest only when every targeted repo is actually readable
|
||||
- the CLI stays responsible for materialization, not the agent
|
||||
- the POC avoids claiming multi-agent parity that the current code and tool landscape do not prove
|
||||
|
||||
## Why this contract
|
||||
|
||||
Evidence reviewed for this phase:
|
||||
|
||||
- `src/commands/workspace.ts` currently implements only `create`, `add-repo`, and `doctor`; there is no `open` entrypoint yet.
|
||||
- `src/core/workspace/registry.ts` already defines the concrete repo-resolution failure states the new command can build on.
|
||||
- `src/core/workspace/change-create.ts` already makes target aliases explicit in workspace change metadata.
|
||||
- `src/core/command-generation/adapters/claude.ts`, `codex.ts`, and `github-copilot.ts` show that command formatting exists, but not a stable cross-tool attach-at-launch contract.
|
||||
- `docs/supported-tools.md` already documents that Copilot custom prompts are IDE-only and that Codex commands are global prompts, which is weaker than a clean repo-scoped attach story.
|
||||
- `WORKSPACE_POC_PRD.md` and `WORKSPACE_POC_DECISION_RECORD.md` both point toward planning-only vs attached-roots mode and a single primary demo path.
|
||||
|
||||
The practical conclusion is:
|
||||
|
||||
- planning-only mode should exist independently of repo resolution
|
||||
- change-scoped attached mode should be all-targets-or-fail
|
||||
- the first shipped path should optimize for one tool, not theoretical parity
|
||||
|
||||
## Exact user-visible behavior
|
||||
|
||||
### `openspec workspace open`
|
||||
|
||||
`workspace open` with no `--change` enters planning-only mode.
|
||||
|
||||
Behavior:
|
||||
|
||||
- Must be run inside a managed workspace created with `openspec workspace create`.
|
||||
- Defaults to `--agent claude` when `--agent` is omitted.
|
||||
- Does not resolve repo aliases and does not attach any repo roots.
|
||||
- Exits successfully with a planning-only instruction surface rooted at the workspace.
|
||||
- The surface must state:
|
||||
- mode: `planning-only`
|
||||
- workspace root path
|
||||
- agent target
|
||||
- attached repos: `none`
|
||||
- next step: use the workspace for central planning, then run `workspace open --change <id>` when target repos need to be in view
|
||||
- Does not create or update repo-local change artifacts.
|
||||
- Does not mutate workspace metadata.
|
||||
|
||||
### `openspec workspace open --change <id>`
|
||||
|
||||
`workspace open --change <id>` enters change-scoped attached-roots mode.
|
||||
|
||||
Behavior:
|
||||
|
||||
- Must be run inside a managed workspace created with `openspec workspace create`.
|
||||
- Defaults to `--agent claude` when `--agent` is omitted.
|
||||
- Validates that `changes/<id>/` exists in the workspace.
|
||||
- Reads the workspace change metadata and requires a non-empty `targets` list.
|
||||
- Resolves only the aliases named in that change's `targets`.
|
||||
- Treats a target as resolved only when:
|
||||
- the alias is registered in workspace metadata
|
||||
- the alias has a local overlay path
|
||||
- the resolved path exists and is a directory
|
||||
- the resolved path contains repo-local OpenSpec state at `openspec/`
|
||||
- On success, exits with a change-scoped instruction surface that states:
|
||||
- mode: `change-scoped`
|
||||
- workspace root path
|
||||
- change ID and change path
|
||||
- agent target
|
||||
- attached repos: only the targeted aliases with their resolved absolute paths
|
||||
- a reminder that `openspec apply --change <id> --repo <alias>` is still the supported materialization step
|
||||
- Does not attach every registered repo.
|
||||
- Does not create or update repo-local change artifacts.
|
||||
|
||||
### Failure behavior for targeted repos
|
||||
|
||||
`workspace open --change <id>` fails the entire command if one or more targeted repos are unresolved.
|
||||
|
||||
Behavior:
|
||||
|
||||
- Exit code is non-zero.
|
||||
- No partial success surface is emitted.
|
||||
- The error names every failing alias and why it failed.
|
||||
- The error points the user to `openspec workspace doctor` or the exact alias that needs repair.
|
||||
|
||||
Fatal failure reasons:
|
||||
|
||||
- change does not exist
|
||||
- change metadata has no `targets`
|
||||
- target alias is missing from the workspace registry
|
||||
- target alias is missing from `.openspec/local.yaml`
|
||||
- target repo path is missing
|
||||
- target repo path is not a directory
|
||||
- target repo path exists but lacks `openspec/`
|
||||
|
||||
Non-fatal nuance:
|
||||
|
||||
- A non-canonical but still valid stored path may be normalized for use and surfaced as drift, but it is not by itself an unresolved-target failure.
|
||||
|
||||
## Supported agent targets in v0
|
||||
|
||||
Decision:
|
||||
|
||||
- `claude` is the only officially supported `workspace open` agent target in v0.
|
||||
- Omitting `--agent` is equivalent to `--agent claude`.
|
||||
- Non-primary agents are explicitly out of scope for Phase 08 v0 behavior.
|
||||
|
||||
Rationale:
|
||||
|
||||
- Phase 08 only needs one primary agent path to produce a real demoable outcome.
|
||||
- The current codebase has command-format adapters for many tools, but that is not the same as proving stable multi-root session-open behavior.
|
||||
- Claude is already the clearest documented primary path in the workspace POC docs.
|
||||
- Supporting more tools now would expand the test matrix faster than the current workspace implementation surface justifies.
|
||||
|
||||
Follow-up note:
|
||||
|
||||
- Codex is the first revisit candidate after Phase 08 and Phase 09 if the primary path lands cleanly.
|
||||
- Copilot remains out of scope for v0 because the repo's current support is prompt-file oriented and not a credible one-shot multi-root CLI attach story.
|
||||
|
||||
## Rejected alternatives
|
||||
|
||||
### Rejected: attach every registered repo
|
||||
|
||||
Why rejected:
|
||||
|
||||
- it violates the roadmap principle that attachment should be change-scoped, not workspace-wide
|
||||
- it scales poorly as workspaces grow
|
||||
- it makes agent context noisy and hides the actual execution set
|
||||
|
||||
### Rejected: partial open when some targeted repos are unresolved
|
||||
|
||||
Why rejected:
|
||||
|
||||
- attached mode is only honest if the agent can see the full targeted working set
|
||||
- partial success creates a false sense that cross-repo planning is complete
|
||||
- planning-only mode already covers the "not all repos are ready yet" use case
|
||||
|
||||
### Rejected: promise multi-agent parity in v0
|
||||
|
||||
Why rejected:
|
||||
|
||||
- the repo currently proves command generation, not equal attach semantics across tools
|
||||
- it would force Phase 08 to solve tool-specific behavior instead of landing one real path
|
||||
- the roadmap only needs one primary agent path for the POC
|
||||
|
||||
### Rejected: auto-launch and manage external agent processes in v0
|
||||
|
||||
Why rejected:
|
||||
|
||||
- it adds tool-specific process and environment complexity that is not required to prove the contract
|
||||
- a deterministic instruction surface is enough for the next phase acceptance target
|
||||
|
||||
## Testable success and failure cases for Phase 08
|
||||
|
||||
### Success cases
|
||||
|
||||
- `openspec workspace open` inside a healthy workspace exits `0` and reports `planning-only` with `attached repos: none`.
|
||||
- `openspec workspace open --change shared-auth` for a change targeting `app,api` exits `0` and lists only `app` and `api`, not other registered aliases like `docs`.
|
||||
- `openspec workspace open --change shared-auth` reports the workspace root, the change path, and the exact resolved absolute repo paths for the targeted aliases.
|
||||
- `openspec workspace open --change shared-auth` leaves repo-local `openspec/changes/shared-auth` absent in all targeted repos.
|
||||
- `openspec workspace open --change shared-auth --agent claude` produces the same usable instruction surface as the default no-flag path.
|
||||
|
||||
### Failure cases
|
||||
|
||||
- `openspec workspace open` outside a managed workspace exits non-zero with an actionable workspace-root error.
|
||||
- `openspec workspace open --change missing-change` exits non-zero and names the missing change.
|
||||
- `openspec workspace open --change planning-only-draft` exits non-zero if the change exists but has no `targets` metadata.
|
||||
- `openspec workspace open --change shared-auth` exits non-zero when any targeted alias is missing from `.openspec/local.yaml`.
|
||||
- `openspec workspace open --change shared-auth` exits non-zero when any targeted path is stale, missing, or no longer contains `openspec/`.
|
||||
- `openspec workspace open --change shared-auth --agent codex` exits non-zero with an unsupported-agent error in v0.
|
||||
|
||||
## Blockers and next-step notes
|
||||
|
||||
- No new roadmap phase is required from this decision.
|
||||
- Phase 08 should implement only the recommended contract above and should not broaden agent scope during the build unless a new bounded phase is added first.
|
||||
@@ -0,0 +1,40 @@
|
||||
# Phase 07 Manual Test
|
||||
|
||||
Manual test stage re-run in a fresh isolated XDG context on 2026-04-17 (Australia/Sydney) for ROADMAP Phase 07, cycle 1.
|
||||
|
||||
This phase is research-only, so the manual pass combined a real CLI smoke for the current workspace/change workflow boundary with a tabletop review of the proposed `workspace open` contract. `workspace open` is not implemented yet, so the command itself was validated only up to its current user-visible absence (`error: unknown command 'open'`).
|
||||
|
||||
## Scenarios run
|
||||
|
||||
- Created isolated `XDG_DATA_HOME` and `XDG_CONFIG_HOME` roots under `/tmp` with `OPENSPEC_TELEMETRY=0` so the smoke could exercise the built CLI without writing to the real home directory.
|
||||
- Ran `node bin/openspec.js --no-color workspace create phase07-manual --json`.
|
||||
- Created three disposable repo roots with repo-local `openspec/` directories and registered them sequentially:
|
||||
- `workspace add-repo app ../../../../repos/app --json`
|
||||
- `workspace add-repo api ../../../../repos/api --json`
|
||||
- `workspace add-repo docs ../../../../repos/docs --json`
|
||||
- Ran `workspace doctor --json` to confirm the healthy registry state.
|
||||
- Ran `node bin/openspec.js --no-color new change shared-auth --targets app,api` inside the managed workspace.
|
||||
- Inspected `changes/shared-auth/.openspec.yaml` and the generated planning layout under `changes/shared-auth/targets/{app,api}`.
|
||||
- Ran `node bin/openspec.js --no-color workspace open` and `node bin/openspec.js --no-color workspace open --change shared-auth` to confirm the current CLI surface still rejects `open` as unimplemented.
|
||||
- Removed `repos/api/openspec`, reran `workspace doctor --json`, restored the directory, and reran `workspace doctor --json` to confirm the existing unresolved-repo diagnostics that Phase 07 relies on.
|
||||
|
||||
## Results
|
||||
|
||||
- `workspace create`, sequential `workspace add-repo`, `workspace doctor`, and `new change --targets` all worked in the fresh isolated context.
|
||||
- The created change wrote explicit target metadata to `changes/shared-auth/.openspec.yaml`:
|
||||
- `schema: spec-driven`
|
||||
- `targets: app, api`
|
||||
- The generated planning layout was change-scoped: `changes/shared-auth/targets/app/` and `changes/shared-auth/targets/api/` were created, and no `changes/shared-auth/targets/docs/` directory was created.
|
||||
- `workspace doctor` reported `status: ok` before the failure injection and then reported a precise `missing-openspec-state` issue for alias `api` after the repo-local `openspec/` directory was removed.
|
||||
- The current CLI still exposes no `workspace open` subcommand. Both `workspace open` and `workspace open --change shared-auth` failed with `error: unknown command 'open'`.
|
||||
- Given that runtime boundary, the remaining validation for Phase 07 stayed at the artifact/tabletop level: [DECISION.md](/Users/tabishbidiwale/fission/repos/openspec/notes/workspace-poc/phase-07-open-contract-research/DECISION.md) still matches the current implementation surface and does not overclaim behavior that exists today.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- Rewrote this manual-test artifact from the prior authoring-time tabletop note into a fresh-context record with real CLI evidence.
|
||||
- No product code or roadmap changes were required for Phase 07. The recommended contract in [DECISION.md](/Users/tabishbidiwale/fission/repos/openspec/notes/workspace-poc/phase-07-open-contract-research/DECISION.md) remained valid after the smoke and failure-injection pass.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- `workspace open` still has no runtime implementation, so this manual pass can only prove the surrounding workflow boundary and the honesty of the proposed contract, not the eventual UX.
|
||||
- Phase 08 still needs to implement the command exactly as documented, and Phase 09 still needs fixture-backed automated coverage for the success and failure cases listed in [DECISION.md](/Users/tabishbidiwale/fission/repos/openspec/notes/workspace-poc/phase-07-open-contract-research/DECISION.md).
|
||||
@@ -0,0 +1,49 @@
|
||||
# Phase 07 Summary
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `implementation`
|
||||
|
||||
## Changes made
|
||||
|
||||
- Added [DECISION.md](/Users/tabishbidiwale/fission/repos/openspec/notes/workspace-poc/phase-07-open-contract-research/DECISION.md) with a concrete v0 contract for `workspace open`.
|
||||
- Chose the minimum supported behavior for:
|
||||
- planning-only mode with `openspec workspace open`
|
||||
- change-scoped attached mode with `openspec workspace open --change <id>`
|
||||
- hard-fail behavior when one or more targeted repos are unresolved
|
||||
- official v0 agent support limited to `claude`, with non-primary agents explicitly out of scope
|
||||
- Added [VERIFY.md](/Users/tabishbidiwale/fission/repos/openspec/notes/workspace-poc/phase-07-open-contract-research/VERIFY.md) and [MANUAL_TEST.md](/Users/tabishbidiwale/fission/repos/openspec/notes/workspace-poc/phase-07-open-contract-research/MANUAL_TEST.md) to record the research checks and tabletop/manual review for this phase.
|
||||
|
||||
## Tests or research performed
|
||||
|
||||
- Re-read the Phase 07 block in [ROADMAP.md](/Users/tabishbidiwale/fission/repos/openspec/ROADMAP.md) and confirmed the phase started with no on-disk artifacts.
|
||||
- Reviewed the current workspace implementation surface in:
|
||||
- [src/commands/workspace.ts](/Users/tabishbidiwale/fission/repos/openspec/src/commands/workspace.ts)
|
||||
- [src/core/workspace/registry.ts](/Users/tabishbidiwale/fission/repos/openspec/src/core/workspace/registry.ts)
|
||||
- [src/core/workspace/metadata.ts](/Users/tabishbidiwale/fission/repos/openspec/src/core/workspace/metadata.ts)
|
||||
- [src/core/workspace/change-create.ts](/Users/tabishbidiwale/fission/repos/openspec/src/core/workspace/change-create.ts)
|
||||
- Reviewed the existing tool-command surface in:
|
||||
- [src/core/command-generation/adapters/claude.ts](/Users/tabishbidiwale/fission/repos/openspec/src/core/command-generation/adapters/claude.ts)
|
||||
- [src/core/command-generation/adapters/codex.ts](/Users/tabishbidiwale/fission/repos/openspec/src/core/command-generation/adapters/codex.ts)
|
||||
- [src/core/command-generation/adapters/github-copilot.ts](/Users/tabishbidiwale/fission/repos/openspec/src/core/command-generation/adapters/github-copilot.ts)
|
||||
- [docs/supported-tools.md](/Users/tabishbidiwale/fission/repos/openspec/docs/supported-tools.md)
|
||||
- Reviewed the higher-level workspace direction in:
|
||||
- [WORKSPACE_POC_PRD.md](/Users/tabishbidiwale/fission/repos/openspec/WORKSPACE_POC_PRD.md)
|
||||
- [WORKSPACE_POC_DECISION_RECORD.md](/Users/tabishbidiwale/fission/repos/openspec/WORKSPACE_POC_DECISION_RECORD.md)
|
||||
- Ran focused research verification after drafting:
|
||||
- content checks against `DECISION.md` for recommended contract, rejected alternatives, exact command behavior, and next-phase success/failure cases
|
||||
- `git diff --check` on the touched Phase 07 files and `ROADMAP.md`
|
||||
|
||||
## Results
|
||||
|
||||
- The note now defines one recommended v0 contract instead of leaving `workspace open` underspecified.
|
||||
- The contract distinguishes planning-only mode from attached-roots mode and keeps repo attachment change-scoped.
|
||||
- The contract defines exact failure semantics: attached mode is all-targets-or-fail, with actionable diagnostics per failing alias.
|
||||
- The note explicitly chooses `claude` as the only official v0 agent target and keeps non-primary agents out of scope.
|
||||
- The note records multiple rejected alternatives so Phase 08 does not accidentally broaden scope.
|
||||
- The note lists concrete success and failure cases that are directly usable for Phase 08 implementation and Phase 09 test planning.
|
||||
|
||||
## Blockers and next-step notes
|
||||
|
||||
- No blockers remain for Phase 07.
|
||||
- No new bounded follow-up phase was required from this research pass.
|
||||
- Phase 08 should implement only the contract in `DECISION.md` and avoid adding multi-agent or partial-open behavior without a new explicit roadmap phase.
|
||||
@@ -0,0 +1,54 @@
|
||||
# Phase 07 Verification
|
||||
|
||||
Independent verification completed in a fresh context on 2026-04-17 (Australia/Sydney) for ROADMAP Phase 07, cycle 1.
|
||||
|
||||
This phase is research-only. `workspace open` is not implemented yet, so verification here checks the Phase 07 contract against the current codebase, roadmap, and workspace POC docs rather than executing a new CLI command.
|
||||
|
||||
## Checks performed
|
||||
|
||||
- Re-read the Phase 07 block in [ROADMAP.md](/Users/tabishbidiwale/fission/repos/openspec/ROADMAP.md) and verified the completion checklist and acceptance targets for this phase.
|
||||
- Re-read [DECISION.md](/Users/tabishbidiwale/fission/repos/openspec/notes/workspace-poc/phase-07-open-contract-research/DECISION.md) and validated the documentation quality for the research output:
|
||||
- one recommended contract is named
|
||||
- rejected alternatives are listed
|
||||
- exact user-visible behavior is defined for both `openspec workspace open` and `openspec workspace open --change <id>`
|
||||
- concrete success and failure cases are listed for the next build and test phases
|
||||
- Reviewed the current workspace implementation boundary in:
|
||||
- [src/commands/workspace.ts](/Users/tabishbidiwale/fission/repos/openspec/src/commands/workspace.ts)
|
||||
- [src/core/workspace/registry.ts](/Users/tabishbidiwale/fission/repos/openspec/src/core/workspace/registry.ts)
|
||||
- [src/core/workspace/metadata.ts](/Users/tabishbidiwale/fission/repos/openspec/src/core/workspace/metadata.ts)
|
||||
- [src/core/workspace/change-create.ts](/Users/tabishbidiwale/fission/repos/openspec/src/core/workspace/change-create.ts)
|
||||
- [src/utils/change-metadata.ts](/Users/tabishbidiwale/fission/repos/openspec/src/utils/change-metadata.ts)
|
||||
- Confirmed the decision note stays inside the real implementation boundary:
|
||||
- there is no `workspace open` subcommand yet
|
||||
- workspace changes already record explicit `targets`
|
||||
- repo resolution and failure states already exist through workspace registry and doctor behavior
|
||||
- the note keeps `workspace open` read-only and does not blur into `openspec apply --change <id> --repo <alias>`
|
||||
- Reviewed the current agent/tool surface in:
|
||||
- [src/core/command-generation/adapters/claude.ts](/Users/tabishbidiwale/fission/repos/openspec/src/core/command-generation/adapters/claude.ts)
|
||||
- [src/core/command-generation/adapters/codex.ts](/Users/tabishbidiwale/fission/repos/openspec/src/core/command-generation/adapters/codex.ts)
|
||||
- [src/core/command-generation/adapters/github-copilot.ts](/Users/tabishbidiwale/fission/repos/openspec/src/core/command-generation/adapters/github-copilot.ts)
|
||||
- [docs/supported-tools.md](/Users/tabishbidiwale/fission/repos/openspec/docs/supported-tools.md)
|
||||
- Confirmed the agent-scope choice in the decision note matches the broader workspace POC direction in:
|
||||
- [WORKSPACE_POC_PRD.md](/Users/tabishbidiwale/fission/repos/openspec/WORKSPACE_POC_PRD.md)
|
||||
- [WORKSPACE_POC_DECISION_RECORD.md](/Users/tabishbidiwale/fission/repos/openspec/WORKSPACE_POC_DECISION_RECORD.md)
|
||||
- Ran `git diff --check -- ROADMAP.md notes/workspace-poc/phase-07-open-contract-research/DECISION.md notes/workspace-poc/phase-07-open-contract-research/SUMMARY.md notes/workspace-poc/phase-07-open-contract-research/VERIFY.md notes/workspace-poc/phase-07-open-contract-research/MANUAL_TEST.md`.
|
||||
- Ran `rg -n "[[:blank:]]$" ROADMAP.md notes/workspace-poc/phase-07-open-contract-research/DECISION.md notes/workspace-poc/phase-07-open-contract-research/SUMMARY.md notes/workspace-poc/phase-07-open-contract-research/VERIFY.md notes/workspace-poc/phase-07-open-contract-research/MANUAL_TEST.md` and confirmed there is no trailing whitespace in the Phase 07 files.
|
||||
|
||||
## Issues found
|
||||
|
||||
- The existing `VERIFY.md` was not a clean independent verification artifact. It included stale implementation-stage claims such as "confirmed the phase started with no on-disk artifacts" and authoring-time statements about changes made "during authoring," which do not belong in a fresh verification pass.
|
||||
- No contract gaps were found in [DECISION.md](/Users/tabishbidiwale/fission/repos/openspec/notes/workspace-poc/phase-07-open-contract-research/DECISION.md). The acceptance tests for this research phase are satisfied.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- Rewrote [VERIFY.md](/Users/tabishbidiwale/fission/repos/openspec/notes/workspace-poc/phase-07-open-contract-research/VERIFY.md) to reflect only this fresh-context verification pass.
|
||||
- Removed stale claims about the prior artifact state and removed authoring-stage commentary that did not belong in independent verification.
|
||||
- Recorded a direct file-content whitespace check in addition to `git diff --check`, because the Phase 07 files are currently untracked in this worktree.
|
||||
- No changes were required to [DECISION.md](/Users/tabishbidiwale/fission/repos/openspec/notes/workspace-poc/phase-07-open-contract-research/DECISION.md), [MANUAL_TEST.md](/Users/tabishbidiwale/fission/repos/openspec/notes/workspace-poc/phase-07-open-contract-research/MANUAL_TEST.md), or the Phase 07 checklist in [ROADMAP.md](/Users/tabishbidiwale/fission/repos/openspec/ROADMAP.md).
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No residual research-note gaps were found for Phase 07 itself.
|
||||
- Runtime proof still belongs to later phases:
|
||||
- Phase 08 must implement the contract without broadening scope.
|
||||
- Phase 09 must validate the resulting behavior with fixture-backed tests.
|
||||
@@ -0,0 +1,50 @@
|
||||
# Phase 08 Manual Test
|
||||
|
||||
Manual smoke re-run in a fresh temp context on 2026-04-17 (Australia/Sydney) for ROADMAP Phase 08, cycle 1.
|
||||
|
||||
## Scenarios run
|
||||
|
||||
- Rebuilt the current CLI with `pnpm run build`.
|
||||
- Checked `node dist/cli/index.js workspace open --help`.
|
||||
- Created a brand-new temp sandbox by copying the real fixture state into sibling `workspace/` and `repos/` directories under one temp root, because `.openspec/local.yaml` resolves repo overlays through `../repos/*`:
|
||||
- `test/fixtures/workspace-poc/dirty/workspace`
|
||||
- `test/fixtures/workspace-poc/dirty/repos`
|
||||
- Ran the planning-only flow from inside the copied workspace:
|
||||
- `node dist/cli/index.js workspace open --json`
|
||||
- Created a healthy change-scoped case:
|
||||
- `node dist/cli/index.js new change shared-refresh --targets app,api`
|
||||
- `node dist/cli/index.js workspace open --change shared-refresh --json`
|
||||
- Verified the success case output reported:
|
||||
- `mode: "change-scoped"`
|
||||
- `change.id: "shared-refresh"`
|
||||
- attached repos for `app` and `api` only
|
||||
- no `docs` attachment
|
||||
- instruction surface path `.claude/commands/opsx/workspace-open.md`
|
||||
- Verified `workspace open` did not materialize repo-local execution state:
|
||||
- `repos/app/openspec/changes/shared-refresh` remained absent
|
||||
- `repos/api/openspec/changes/shared-refresh` remained absent
|
||||
- `repos/docs/openspec/changes/shared-refresh` remained absent
|
||||
- Created a stale-target failure case:
|
||||
- `node dist/cli/index.js new change shared-broken --targets app,docs`
|
||||
- `node dist/cli/index.js workspace open --change shared-broken`
|
||||
- Exercised the unsupported-agent path:
|
||||
- `node dist/cli/index.js workspace open --agent codex`
|
||||
|
||||
## Results
|
||||
|
||||
- All manual smoke scenarios passed.
|
||||
- Planning-only open succeeded even though the copied fixture still had a stale `docs` path in `.openspec/local.yaml`, confirming that the no-change path does not attach repo roots.
|
||||
- Change-scoped open for `shared-refresh` attached only `app` and `api`, not all registered repos.
|
||||
- Change-scoped open for `shared-broken` failed with a non-zero exit and the expected actionable message naming `docs` plus the `workspace doctor` repair path.
|
||||
- The unsupported-agent path failed cleanly with `Unsupported agent 'codex' for workspace open in v0. Supported agent: claude.`
|
||||
- `workspace open` left repo-local `openspec/changes/shared-refresh` directories absent in all copied repos after the smoke run.
|
||||
- The help surface still exposes the Phase 08 contract cleanly: `--change <id>`, `--agent <tool>` with `claude` as the v0 default, and `--json`.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No product fixes were required during this manual-test pass.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No Phase 08 user-visible regressions or residual risks were identified in this manual smoke cycle.
|
||||
- Phase 09 can still widen the permanent validation matrix, but the shipped Phase 08 user path behaved as intended end to end.
|
||||
@@ -0,0 +1,56 @@
|
||||
# Phase 08 Summary
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `implementation`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
## Changes made
|
||||
|
||||
- Added [src/core/workspace/open.ts](/Users/tabishbidiwale/fission/repos/openspec/src/core/workspace/open.ts) so `openspec workspace open` now supports:
|
||||
- planning-only mode when no `--change` is supplied
|
||||
- change-scoped mode for `--change <id>`
|
||||
- defaulting `--agent` to `claude`
|
||||
- generating a usable Claude instruction surface through the existing command adapter/generator path instead of inventing a separate formatter
|
||||
- validating that workspace changes exist and have non-empty `targets`
|
||||
- resolving only the targeted repos for the selected change
|
||||
- hard-failing with aggregated actionable diagnostics when one or more targeted repos are unresolved
|
||||
- Extended [src/core/workspace/registry.ts](/Users/tabishbidiwale/fission/repos/openspec/src/core/workspace/registry.ts) with target-specific repo resolution helpers so `workspace open` can reuse the existing registry model while resolving only the change’s requested aliases.
|
||||
- Extended [src/commands/workspace.ts](/Users/tabishbidiwale/fission/repos/openspec/src/commands/workspace.ts) with `openspec workspace open`, including both human-readable and `--json` output.
|
||||
- Added focused Phase 08 coverage in:
|
||||
- [test/core/workspace/open.test.ts](/Users/tabishbidiwale/fission/repos/openspec/test/core/workspace/open.test.ts)
|
||||
- [test/commands/workspace/open.test.ts](/Users/tabishbidiwale/fission/repos/openspec/test/commands/workspace/open.test.ts)
|
||||
- [test/cli-e2e/workspace/workspace-open-cli.test.ts](/Users/tabishbidiwale/fission/repos/openspec/test/cli-e2e/workspace/workspace-open-cli.test.ts)
|
||||
|
||||
## Tests or research performed
|
||||
|
||||
- `pnpm run build`
|
||||
- `pnpm vitest run test/core/workspace/open.test.ts test/commands/workspace/open.test.ts test/cli-e2e/workspace/workspace-open-cli.test.ts`
|
||||
- `pnpm vitest run test/core/workspace/*.test.ts test/commands/workspace/*.test.ts test/cli-e2e/workspace/*.test.ts`
|
||||
- `node dist/cli/index.js workspace open --help`
|
||||
- Fresh copied-fixture CLI smoke on 2026-04-17 (Australia/Sydney):
|
||||
- copied `test/fixtures/workspace-poc/dirty/{workspace,repos}` into a fresh temp root
|
||||
- `node dist/cli/index.js workspace open --json`
|
||||
- `node dist/cli/index.js new change shared-refresh --targets app,api`
|
||||
- `node dist/cli/index.js workspace open --change shared-refresh --json`
|
||||
- verified only `app` and `api` were attached
|
||||
- verified `repos/{app,api,docs}/openspec/changes/shared-refresh` remained absent after `workspace open`
|
||||
- `node dist/cli/index.js new change shared-broken --targets app,docs`
|
||||
- `node dist/cli/index.js workspace open --change shared-broken`
|
||||
- `node dist/cli/index.js workspace open --agent codex`
|
||||
|
||||
## Results
|
||||
|
||||
- Build passed.
|
||||
- Focused Phase 08 tests passed: 7/7.
|
||||
- Broader workspace regression coverage passed: 37/37.
|
||||
- `workspace open` without `--change` now succeeds in planning-only mode and reports `attachedRepos: []` / `Attached repos: none`.
|
||||
- `workspace open --change <id>` now attaches only the change’s targeted repos and does not pull in unrelated registered aliases.
|
||||
- Change-scoped open now fails clearly when a targeted repo path is stale or missing, and the error names the broken alias plus the `workspace doctor` repair path.
|
||||
- The primary v0 agent path now produces a usable Claude instruction surface at `.claude/commands/opsx/workspace-open.md`.
|
||||
- `workspace open` does not materialize repo-local changes during the session-prep flow.
|
||||
|
||||
## Blockers and next-step notes
|
||||
|
||||
- No blockers remain for Phase 08.
|
||||
- No new roadmap phases were required from this implementation pass.
|
||||
- Phase 09 can expand the validation matrix further, but the Phase 08 contract is now implemented, exercised, and manually smoke-tested.
|
||||
@@ -0,0 +1,41 @@
|
||||
# Phase 08 Verification
|
||||
|
||||
Independent verification re-run in a fresh context on 2026-04-17 (Australia/Sydney) for ROADMAP Phase 08, cycle 1.
|
||||
|
||||
## Checks performed
|
||||
|
||||
- Re-read the Phase 08 block in [ROADMAP.md](/Users/tabishbidiwale/fission/repos/openspec/ROADMAP.md) and the current phase artifacts in [SUMMARY.md](/Users/tabishbidiwale/fission/repos/openspec/notes/workspace-poc/phase-08-workspace-open/SUMMARY.md) and [MANUAL_TEST.md](/Users/tabishbidiwale/fission/repos/openspec/notes/workspace-poc/phase-08-workspace-open/MANUAL_TEST.md).
|
||||
- Reviewed the implementation boundary in:
|
||||
- [src/core/workspace/open.ts](/Users/tabishbidiwale/fission/repos/openspec/src/core/workspace/open.ts)
|
||||
- [src/core/workspace/registry.ts](/Users/tabishbidiwale/fission/repos/openspec/src/core/workspace/registry.ts)
|
||||
- [src/commands/workspace.ts](/Users/tabishbidiwale/fission/repos/openspec/src/commands/workspace.ts)
|
||||
- [test/core/workspace/open.test.ts](/Users/tabishbidiwale/fission/repos/openspec/test/core/workspace/open.test.ts)
|
||||
- [test/commands/workspace/open.test.ts](/Users/tabishbidiwale/fission/repos/openspec/test/commands/workspace/open.test.ts)
|
||||
- [test/cli-e2e/workspace/workspace-open-cli.test.ts](/Users/tabishbidiwale/fission/repos/openspec/test/cli-e2e/workspace/workspace-open-cli.test.ts)
|
||||
- Confirmed `node dist/cli/index.js workspace open --help` documents:
|
||||
- `--change <id>`
|
||||
- `--agent <tool>` with `claude` as the default
|
||||
- `--json`
|
||||
- Rebuilt the current tree with `pnpm run build`.
|
||||
- Re-ran the focused Phase 08 suites with `pnpm vitest run test/core/workspace/open.test.ts test/commands/workspace/open.test.ts test/cli-e2e/workspace/workspace-open-cli.test.ts`.
|
||||
- Re-ran the broader workspace regression slice with `pnpm vitest run test/core/workspace/*.test.ts test/commands/workspace/*.test.ts test/cli-e2e/workspace/*.test.ts`.
|
||||
- Rechecked the copied-fixture CLI smoke outcomes in a fresh temp root while preserving the expected sibling `workspace/` and `repos/` fixture layout from `.openspec/local.yaml`:
|
||||
- planning-only open attached no repos even with a stale non-targeted `docs` overlay entry
|
||||
- change-scoped open for a change targeting `app,api` attached only those repos
|
||||
- change-scoped open for a change targeting `app,docs` failed non-zero with an aggregated alias-specific diagnostic
|
||||
- unsupported-agent open failed cleanly with the documented v0 `claude`-only error
|
||||
|
||||
## Issues found
|
||||
|
||||
- No Phase 08 product correctness issues were found during the independent verification pass.
|
||||
- The manual test notes were slightly underspecified about fixture layout. Copying the dirty workspace fixture into an arbitrary directory name breaks the smoke harness because the checked-in local overlay uses relative `../repos/*` paths.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No product code changes were required during verification.
|
||||
- Clarified [MANUAL_TEST.md](/Users/tabishbidiwale/fission/repos/openspec/notes/workspace-poc/phase-08-workspace-open/MANUAL_TEST.md) so the copied-fixture smoke explicitly preserves sibling `workspace/` and `repos/` directories.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- `workspace open` intentionally supports only `claude` in v0. That is the chosen Phase 08 contract, not an accidental gap.
|
||||
- Phase 09 can still widen and harden the validation matrix, especially around unsupported-agent coverage and extra edge cases, but no Phase 08 blocker remains.
|
||||
@@ -0,0 +1,49 @@
|
||||
# Phase 09 Manual Test
|
||||
|
||||
Manual smoke re-run in a fresh temp context on 2026-04-17 (Australia/Sydney) for ROADMAP Phase 09, cycle 1.
|
||||
|
||||
## Scenarios run
|
||||
|
||||
- Rebuilt the current CLI with `pnpm run build`.
|
||||
- Created a brand-new temp sandbox by copying the real dirty fixture into sibling `workspace/` and `repos/` directories under one temp root:
|
||||
- `test/fixtures/workspace-poc/dirty/workspace`
|
||||
- `test/fixtures/workspace-poc/dirty/repos`
|
||||
- Canonicalized the temp root with `pwd -P` before making path assertions so the smoke matched the CLI's real canonical path output on macOS.
|
||||
- Confirmed the copied dirty fixture preserved the stale `docs` alias pointing at a missing `repos/docs-missing` path before exercising the failure case.
|
||||
- Ran the planning-only flow:
|
||||
- `node dist/cli/index.js workspace open --json`
|
||||
- Created a healthy change-scoped case:
|
||||
- `node dist/cli/index.js new change shared-refresh --targets app,api`
|
||||
- `node dist/cli/index.js workspace open --change shared-refresh --agent claude`
|
||||
- Verified the success case output reported:
|
||||
- `Prepared change-scoped workspace open surface for claude.`
|
||||
- instruction surface path `.claude/commands/opsx/workspace-open.md`
|
||||
- attached repos for `app` and `api` only
|
||||
- no `docs` attachment
|
||||
- the `openspec apply --change shared-refresh --repo <alias>` reminder
|
||||
- Verified the session-prep contract stayed intact:
|
||||
- `workspace/.claude/commands/opsx/workspace-open.md` was still absent on disk after the command
|
||||
- `repos/app/openspec/changes/shared-refresh` was absent
|
||||
- `repos/api/openspec/changes/shared-refresh` was absent
|
||||
- Created a stale-target failure case:
|
||||
- `node dist/cli/index.js new change shared-broken --targets app,docs`
|
||||
- `node dist/cli/index.js workspace open --change shared-broken`
|
||||
- Exercised the unsupported-agent path:
|
||||
- `node dist/cli/index.js workspace open --agent codex`
|
||||
|
||||
## Results
|
||||
|
||||
- All manual smoke scenarios passed.
|
||||
- Planning-only open succeeded without exposing attached repo roots, even with the copied fixture still carrying the stale `docs -> repos/docs-missing` alias.
|
||||
- Change-scoped open for `shared-refresh` attached only `app` and `api`, not all registered repos.
|
||||
- The Claude demo path remained instruction-surface only; it did not write a `.claude` command file and did not materialize repo-local execution state.
|
||||
- Change-scoped open for `shared-broken` failed with a non-zero exit and the expected actionable message naming `docs`, the missing `repos/docs-missing` path, and the `workspace doctor` repair path.
|
||||
- The unsupported-agent path failed cleanly with `Unsupported agent 'codex' for workspace open in v0. Supported agent: claude.`
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No product fixes were required during this manual-test pass.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No new user-visible residual risks were identified within the Phase 09 validation scope.
|
||||
@@ -0,0 +1,49 @@
|
||||
# Phase 09 Summary
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `implementation`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
## Changes made
|
||||
|
||||
- Added stronger Phase 09 validation coverage for `workspace open` in:
|
||||
- [test/core/workspace/open.test.ts](/Users/tabishbidiwale/fission/repos/openspec/test/core/workspace/open.test.ts)
|
||||
- [test/commands/workspace/open.test.ts](/Users/tabishbidiwale/fission/repos/openspec/test/commands/workspace/open.test.ts)
|
||||
- [test/cli-e2e/workspace/workspace-open-cli.test.ts](/Users/tabishbidiwale/fission/repos/openspec/test/cli-e2e/workspace/workspace-open-cli.test.ts)
|
||||
- Strengthened the planning-only assertions so Phase 09 now proves the surface does not leak attached repo roots, including stale overlay paths from the dirty fixture.
|
||||
- Added command and CLI coverage that proves change-scoped open lists only targeted aliases and excludes unrelated registered repos.
|
||||
- Added unsupported-agent coverage for the documented v0 contract (`claude` only), using `codex` as the explicit negative case even though that tool has a command adapter elsewhere in the repo.
|
||||
- Added non-JSON CLI e2e coverage for the primary Claude demo path and asserted that `workspace open` stays session-prep only:
|
||||
- no `.claude/commands/opsx/workspace-open.md` file is written to disk
|
||||
- no repo-local `openspec/changes/<id>` materialization is created in attached repos
|
||||
- Updated the Phase 09 checklist in [ROADMAP.md](/Users/tabishbidiwale/fission/repos/openspec/ROADMAP.md).
|
||||
|
||||
## Tests or research performed
|
||||
|
||||
- `pnpm run build`
|
||||
- `pnpm vitest run test/core/workspace/open.test.ts test/commands/workspace/open.test.ts test/cli-e2e/workspace/workspace-open-cli.test.ts`
|
||||
- `pnpm vitest run test/core/workspace/*.test.ts test/commands/workspace/*.test.ts test/cli-e2e/workspace/*.test.ts`
|
||||
- Fresh copied-fixture CLI smoke on 2026-04-17 (Australia/Sydney):
|
||||
- copied `test/fixtures/workspace-poc/dirty/{workspace,repos}` into a fresh temp root while preserving sibling `workspace/` and `repos/`
|
||||
- canonicalized the temp root with `pwd -P` so the smoke assertions matched the CLI's real path normalization on macOS
|
||||
- ran `node dist/cli/index.js workspace open --json`
|
||||
- ran `node dist/cli/index.js new change shared-refresh --targets app,api`
|
||||
- ran `node dist/cli/index.js workspace open --change shared-refresh --agent claude`
|
||||
- ran `node dist/cli/index.js new change shared-broken --targets app,docs`
|
||||
- ran `node dist/cli/index.js workspace open --change shared-broken`
|
||||
- ran `node dist/cli/index.js workspace open --agent codex`
|
||||
|
||||
## Results
|
||||
|
||||
- Build passed.
|
||||
- Focused Phase 09 workspace-open validation passed: 12/12 tests.
|
||||
- Broader workspace regression coverage passed: 42/42 tests.
|
||||
- Planning-only open now has permanent coverage proving it exposes no attached repo roots in either JSON output or the generated instruction surface.
|
||||
- Change-scoped open now has permanent coverage proving it attaches only the targeted aliases and excludes unrelated registered repos.
|
||||
- Failure coverage now proves unresolved target diagnostics include both the failing alias and the `workspace doctor` repair path.
|
||||
- The primary Claude demo path is covered end to end in CLI e2e without relying on real multi-root writes or repo-local materialization.
|
||||
|
||||
## Blockers and next-step notes
|
||||
|
||||
- No blockers remain for Phase 09.
|
||||
- No new roadmap phases were required from this validation pass.
|
||||
@@ -0,0 +1,47 @@
|
||||
# Phase 09 Verification
|
||||
|
||||
Independent verification re-run in a fresh context on 2026-04-17 (Australia/Sydney) for ROADMAP Phase 09, cycle 1.
|
||||
|
||||
## Checks performed
|
||||
|
||||
- Re-read the Phase 09 block in [ROADMAP.md](/Users/tabishbidiwale/fission/repos/openspec/ROADMAP.md) and the current implementation summary in [notes/workspace-poc/phase-09-test-workspace-open/SUMMARY.md](/Users/tabishbidiwale/fission/repos/openspec/notes/workspace-poc/phase-09-test-workspace-open/SUMMARY.md).
|
||||
- Reviewed the implementation boundary in:
|
||||
- [src/core/workspace/open.ts](/Users/tabishbidiwale/fission/repos/openspec/src/core/workspace/open.ts)
|
||||
- [src/commands/workspace.ts](/Users/tabishbidiwale/fission/repos/openspec/src/commands/workspace.ts)
|
||||
- [test/core/workspace/open.test.ts](/Users/tabishbidiwale/fission/repos/openspec/test/core/workspace/open.test.ts)
|
||||
- [test/commands/workspace/open.test.ts](/Users/tabishbidiwale/fission/repos/openspec/test/commands/workspace/open.test.ts)
|
||||
- [test/cli-e2e/workspace/workspace-open-cli.test.ts](/Users/tabishbidiwale/fission/repos/openspec/test/cli-e2e/workspace/workspace-open-cli.test.ts)
|
||||
- Rebuilt the current tree with `pnpm run build`.
|
||||
- Re-ran the focused Phase 09 suites with `pnpm vitest run test/core/workspace/open.test.ts test/commands/workspace/open.test.ts test/cli-e2e/workspace/workspace-open-cli.test.ts`.
|
||||
- Result: 3 files passed, 12/12 tests passed.
|
||||
- Re-ran the broader workspace regression slice with `pnpm vitest run test/core/workspace/*.test.ts test/commands/workspace/*.test.ts test/cli-e2e/workspace/*.test.ts`.
|
||||
- Result: 13 files passed, 42/42 tests passed.
|
||||
- Re-ran a fresh copied-fixture CLI smoke against sibling `workspace/` and `repos/` directories under a new temp root, canonicalized with `pwd -P`, then exercised:
|
||||
- `node dist/cli/index.js workspace open --json`
|
||||
- `node dist/cli/index.js new change shared-refresh --targets app,api`
|
||||
- `node dist/cli/index.js workspace open --change shared-refresh --agent claude`
|
||||
- `node dist/cli/index.js new change shared-broken --targets app,docs`
|
||||
- `node dist/cli/index.js workspace open --change shared-broken`
|
||||
- `node dist/cli/index.js workspace open --agent codex`
|
||||
- Validated the documented contract and notes quality for this phase:
|
||||
- planning-only open exposes no attached repo roots
|
||||
- change-scoped open lists only targeted aliases
|
||||
- stale-target diagnostics name the failing alias and `workspace doctor`
|
||||
- the Claude demo path stays session-prep only and does not write a real multi-root command file or repo-local materialization
|
||||
- [notes/workspace-poc/phase-09-test-workspace-open/MANUAL_TEST.md](/Users/tabishbidiwale/fission/repos/openspec/notes/workspace-poc/phase-09-test-workspace-open/MANUAL_TEST.md) still matches the real CLI behavior exercised in this pass
|
||||
|
||||
## Issues found
|
||||
|
||||
- No product correctness issues were found.
|
||||
- No acceptance-test coverage gaps were found for the Phase 09 scope.
|
||||
- No documentation-quality issues were found in the current summary or manual-test notes.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No product or test changes were required during this verification pass.
|
||||
- Updated this verification artifact to reflect the fresh-context checks and outcomes above.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No residual risks were identified within the Phase 09 verification scope.
|
||||
- The `claude`-only agent constraint remains an intentional v0 boundary and is explicitly covered by negative tests.
|
||||
@@ -0,0 +1,185 @@
|
||||
# Phase 10 Decision
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `implementation`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
## Recommended v0 contract
|
||||
|
||||
The v0 materialization contract for `openspec apply --change <id> --repo <alias>` is:
|
||||
|
||||
- create-only at the selected target repo
|
||||
- zero overwrite behavior
|
||||
- no refresh or re-materialize path in v0
|
||||
- reuse the workspace change ID as the repo-local change ID
|
||||
- keep the repo-local bundle self-contained enough to execute without going back to the workspace
|
||||
- keep workspace planning artifacts intact after apply
|
||||
|
||||
In concrete terms, a successful v0 apply writes exactly one repo-local change at:
|
||||
|
||||
`<resolved-repo>/openspec/changes/<change-id>/`
|
||||
|
||||
The repo-local bundle should contain:
|
||||
|
||||
- `.openspec.yaml` with the workspace change schema and a repo-local `created` date
|
||||
- `proposal.md` copied from the workspace change root
|
||||
- `design.md` copied from the workspace change root
|
||||
- `tasks.md` copied from `targets/<alias>/tasks.md`
|
||||
- `specs/` copied from `targets/<alias>/specs/`
|
||||
- `.openspec.materialization.yaml` as the minimum trace sidecar
|
||||
|
||||
The trace sidecar should be the smallest machine-readable link needed for later roll-up without redesigning core change metadata:
|
||||
|
||||
```yaml
|
||||
source: workspace
|
||||
workspaceName: <workspace metadata name>
|
||||
targetAlias: <alias>
|
||||
materializedAt: <ISO-8601 timestamp>
|
||||
```
|
||||
|
||||
This file intentionally does not store absolute paths.
|
||||
|
||||
What stays in the workspace only:
|
||||
|
||||
- `tasks/coordination.md`
|
||||
- any other workspace-only planning notes outside the selected target slice
|
||||
- the original `targets/` tree
|
||||
|
||||
## Why this contract
|
||||
|
||||
Evidence reviewed for this phase:
|
||||
|
||||
- `src/core/workspace/open.ts` explicitly keeps `workspace open` read-only and tells the user that repo-local materialization happens later with `openspec apply --change <id> --repo <alias>`.
|
||||
- `src/core/workspace/change-create.ts` already stores the shared planning truth centrally: schema, created date, and explicit target aliases in the workspace change.
|
||||
- `src/utils/change-metadata.ts` and `src/core/artifact-graph/types.ts` currently model normal change metadata as `schema`, `created`, and optional `targets`; adding traceability through a sidecar is less invasive than expanding `.openspec.yaml` first.
|
||||
- `schemas/spec-driven/schema.yaml` expects repo-local execution artifacts in their normal locations, especially root-level `tasks.md` and `specs/`.
|
||||
- The current CLI surface has schema-aware apply instructions, but no repo-aware `apply --repo` materialization implementation yet, so Phase 11 should land a narrow write contract instead of a refresh engine.
|
||||
|
||||
The practical conclusion is:
|
||||
|
||||
- create-only is the smallest honest contract for the POC
|
||||
- repo-local execution should not depend on the workspace remaining mounted in context
|
||||
- traceability should be explicit, but minimal
|
||||
|
||||
## Exact v0 behavior
|
||||
|
||||
### Preconditions
|
||||
|
||||
`openspec apply --change <id> --repo <alias>` should hard-fail unless all of the following are true:
|
||||
|
||||
- the command is run from a managed workspace root
|
||||
- `changes/<id>/` exists in that workspace
|
||||
- the workspace change metadata contains `targets`
|
||||
- `<alias>` is one of those targets
|
||||
- `<alias>` resolves through workspace metadata and local overlay to a live repo containing `openspec/`
|
||||
- the workspace change has the source files needed for a repo-local execution bundle:
|
||||
- `proposal.md`
|
||||
- `design.md`
|
||||
- `targets/<alias>/tasks.md`
|
||||
- `targets/<alias>/specs/` (may be empty, but the directory must exist)
|
||||
- the destination repo does not already contain `openspec/changes/<id>/`
|
||||
|
||||
### Successful materialization
|
||||
|
||||
A materialization counts as successful only when:
|
||||
|
||||
- the command exits `0`
|
||||
- only the selected target repo is modified
|
||||
- the destination repo now contains one complete repo-local change at `openspec/changes/<id>/`
|
||||
- that repo-local change includes the exact files listed in the recommended contract above
|
||||
- the workspace change remains intact and unchanged after the write
|
||||
|
||||
At the selected-repo scope, success is all-or-nothing:
|
||||
|
||||
- validate every source and destination condition before writing
|
||||
- stage the repo-local bundle in a fresh temp directory
|
||||
- move it into place only after the bundle is complete
|
||||
- if staging fails, clean up the temp directory and leave the final destination absent
|
||||
|
||||
### Repeat `apply` behavior
|
||||
|
||||
The repeat-call behavior in v0 is:
|
||||
|
||||
- first successful apply for a target repo creates that repo-local change and transfers execution authority for that target
|
||||
- repeating apply for the same `<change-id>` and the same `<alias>` fails clearly because v0 is create-only
|
||||
- repeating apply for a different targeted alias is allowed if that other target repo does not already have `openspec/changes/<id>/`
|
||||
- editing workspace planning artifacts after one repo has already been materialized does not refresh that repo on a repeat apply; divergence is expected until a future refresh contract exists
|
||||
|
||||
The user-facing rule is simple:
|
||||
|
||||
- if the repo-local change already exists, OpenSpec protects it and refuses to overwrite it
|
||||
|
||||
### Conflict handling
|
||||
|
||||
These cases should fail non-zero with no partial success:
|
||||
|
||||
- unknown repo alias
|
||||
- alias registered in the workspace but not targeted by the selected workspace change
|
||||
- stale or missing target repo path
|
||||
- target repo missing `openspec/`
|
||||
- missing workspace source files for the selected target slice
|
||||
- pre-existing destination change directory or destination file collision
|
||||
|
||||
The error should say whether the failure is:
|
||||
|
||||
- a target-selection problem
|
||||
- a repo-resolution problem
|
||||
- a source-artifact problem
|
||||
- or a create-only collision
|
||||
|
||||
## Explicit non-goals
|
||||
|
||||
The v0 contract explicitly does not include:
|
||||
|
||||
- refresh or re-materialize behavior
|
||||
- selective overwrite of existing repo-local files
|
||||
- sync-back from repo-local execution into workspace drafts
|
||||
- automatic workspace status updates during apply
|
||||
- automatic promotion of shared drafts into a canonical owner repo
|
||||
- copying workspace coordination tasks into repo-local execution bundles
|
||||
- expanding `.openspec.yaml` with richer workspace-link metadata in this phase
|
||||
|
||||
## Rejected alternatives
|
||||
|
||||
### Rejected: support refresh in v0
|
||||
|
||||
Why rejected:
|
||||
|
||||
- refresh immediately forces overwrite rules, merge semantics, and conflict resolution policy
|
||||
- the roadmap already leans toward create-only unless this phase proved otherwise
|
||||
- the POC does not need refresh to prove the planning-to-execution handoff
|
||||
|
||||
### Rejected: overwrite an existing repo-local change on repeat apply
|
||||
|
||||
Why rejected:
|
||||
|
||||
- it risks destroying real repo-local execution state
|
||||
- it hides authority transfer instead of making it explicit
|
||||
- it makes repeat behavior harder to explain and harder to test honestly
|
||||
|
||||
### Rejected: copy coordination tasks into the repo-local change
|
||||
|
||||
Why rejected:
|
||||
|
||||
- coordination remains a workspace concern
|
||||
- copying it into one repo would blur local execution with cross-repo planning
|
||||
- the target repo should receive only the shared context plus its own execution slice
|
||||
|
||||
### Rejected: store trace metadata by expanding `.openspec.yaml` first
|
||||
|
||||
Why rejected:
|
||||
|
||||
- current change metadata support is intentionally small
|
||||
- a sidecar is enough for Phase 11 and Phase 13 follow-on work
|
||||
- it avoids coupling the workspace POC to a broader metadata-schema change
|
||||
|
||||
## Phase 11 implications
|
||||
|
||||
Phase 11 should implement only this contract:
|
||||
|
||||
- one selected repo per apply call
|
||||
- create-only destination semantics
|
||||
- normal repo-local change layout
|
||||
- explicit minimal sidecar trace metadata
|
||||
|
||||
No new roadmap phase is required from this decision.
|
||||
@@ -0,0 +1,45 @@
|
||||
# Phase 10 Manual Test
|
||||
|
||||
Manual smoke re-run in a fresh local context on 2026-04-17 (Australia/Sydney) for ROADMAP Phase 10, cycle 1.
|
||||
|
||||
## Scenarios run
|
||||
|
||||
- Built the current CLI with `pnpm run build`.
|
||||
- Created a fresh temp root and copied:
|
||||
- `test/fixtures/workspace-poc/happy-path/workspace` to `<tmp>/workspace`
|
||||
- `test/fixtures/workspace-poc/happy-path/repos` to `<tmp>/repos`
|
||||
- Ran the real CLI from the copied workspace with telemetry disabled:
|
||||
|
||||
```bash
|
||||
cd <tmp>/workspace
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js new change shared-refresh --targets app,api
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js workspace open --change shared-refresh --agent claude
|
||||
test ! -e <tmp>/repos/app/openspec/changes/shared-refresh
|
||||
test ! -e <tmp>/repos/api/openspec/changes/shared-refresh
|
||||
test ! -e <tmp>/repos/docs/openspec/changes/shared-refresh
|
||||
```
|
||||
|
||||
- Inspected the `workspace open` output to confirm:
|
||||
- only targeted repos were attached
|
||||
- the instruction surface still said `Do not materialize repo-local changes from this session.`
|
||||
- the instruction surface still said `openspec apply --change shared-refresh --repo <alias>`
|
||||
- Checked that the reported `.claude/commands/opsx/workspace-open.md` path was not actually written during the command.
|
||||
|
||||
## Results
|
||||
|
||||
- `pnpm run build` passed.
|
||||
- `new change shared-refresh --targets app,api` succeeded and created the workspace change.
|
||||
- `workspace open --change shared-refresh --agent claude` succeeded and attached exactly `app` and `api`.
|
||||
- No repo-local change was materialized in `app`, `api`, or `docs`.
|
||||
- The instruction surface remained advisory only; the reported `.claude/commands/opsx/workspace-open.md` path was not written to disk.
|
||||
- The current product boundary still matches `DECISION.md`: planning and session prep happen in the workspace, while repo-local execution remains an explicit later step.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No product or test code fixes were required from this manual pass.
|
||||
- Rewrote this manual-test note to reflect the fresh smoke run and the required stage structure.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- None found within the scope of Phase 10.
|
||||
- Phase 11 still needs to implement the create-only materialization contract defined in `DECISION.md`; that is a forward implementation dependency, not a Phase 10 manual-test gap.
|
||||
@@ -0,0 +1,66 @@
|
||||
# Phase 10 Summary
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `implementation`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
## Changes made
|
||||
|
||||
- Added the Phase 10 research decision in `notes/workspace-poc/phase-10-materialization-contract-research/DECISION.md`.
|
||||
- Added Phase 10 verification and manual-test artifacts:
|
||||
- `notes/workspace-poc/phase-10-materialization-contract-research/VERIFY.md`
|
||||
- `notes/workspace-poc/phase-10-materialization-contract-research/MANUAL_TEST.md`
|
||||
- Chose one concrete v0 materialization contract for `openspec apply --change <id> --repo <alias>`:
|
||||
- create-only
|
||||
- no overwrite
|
||||
- no refresh path
|
||||
- explicit repeat-apply failure for the same target repo
|
||||
- minimal sidecar trace metadata in `.openspec.materialization.yaml`
|
||||
- Defined the repo-local bundle shape as:
|
||||
- shared context copied from workspace root: `proposal.md`, `design.md`
|
||||
- target slice copied from `targets/<alias>/`: `tasks.md`, `specs/`
|
||||
- no workspace coordination artifacts copied into the repo-local change
|
||||
- Updated the Phase 10 checklist in `ROADMAP.md`.
|
||||
|
||||
## Tests or research performed
|
||||
|
||||
- Re-read the Phase 10 and Phase 11 blocks in `ROADMAP.md`.
|
||||
- Reviewed the current workspace and apply-adjacent implementation surface in:
|
||||
- `src/core/workspace/open.ts`
|
||||
- `src/core/workspace/change-create.ts`
|
||||
- `src/utils/change-metadata.ts`
|
||||
- `src/core/artifact-graph/types.ts`
|
||||
- `schemas/spec-driven/schema.yaml`
|
||||
- `src/cli/index.ts`
|
||||
- Re-read prior workspace POC notes and design anchors in:
|
||||
- `notes/workspace-poc/phase-07-open-contract-research/DECISION.md`
|
||||
- `notes/workspace-poc/phase-09-test-workspace-open/{SUMMARY.md,VERIFY.md}`
|
||||
- `WORKSPACE_POC_PRD.md`
|
||||
- `WORKSPACE_POC_DECISION_RECORD.md`
|
||||
- Ran focused workspace regression coverage:
|
||||
- `pnpm vitest run test/core/workspace/change-create.test.ts test/core/workspace/open.test.ts test/commands/workspace/open.test.ts test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts test/cli-e2e/workspace/workspace-open-cli.test.ts`
|
||||
- Ran a fresh copied-fixture CLI smoke against `test/fixtures/workspace-poc/happy-path` using the built CLI:
|
||||
- `node dist/cli/index.js new change shared-refresh --targets app,api`
|
||||
- `node dist/cli/index.js workspace open --change shared-refresh --agent claude`
|
||||
- verified `repos/{app,api,docs}/openspec/changes/shared-refresh` remained absent
|
||||
- Corrected one invalid manual harness attempt during this run:
|
||||
- an initial smoke used `pnpm exec` from the copied temp workspace, which is not a package
|
||||
- reran successfully with `node dist/cli/index.js` from the repository build output
|
||||
|
||||
## Results
|
||||
|
||||
- Focused workspace tests passed: 5 files, 19/19 tests passed.
|
||||
- The current implementation boundary still holds:
|
||||
- workspace changes centralize planning and target metadata
|
||||
- `workspace open` remains read-only
|
||||
- the user-facing handoff to `apply --change --repo` is already explicit in the open surface
|
||||
- The chosen v0 contract is consistent with both the roadmap guardrails and the current implementation surface:
|
||||
- create-only avoids inventing refresh semantics before they are tested
|
||||
- copying shared context plus one target slice produces a usable repo-local execution bundle
|
||||
- a sidecar trace file is enough for later roll-up without broadening core change metadata now
|
||||
|
||||
## Blockers and next-step notes
|
||||
|
||||
- No blockers remain for Phase 10.
|
||||
- No new roadmap phases were required from this research pass.
|
||||
- Phase 11 should implement exactly the create-only contract captured in `DECISION.md` and should not add refresh or overwrite behavior unless the roadmap is expanded first.
|
||||
@@ -0,0 +1,57 @@
|
||||
# Phase 10 Verification
|
||||
|
||||
Independent verification re-run in a fresh local context on 2026-04-17 (Australia/Sydney) for ROADMAP Phase 10, cycle 1.
|
||||
|
||||
## Checks performed
|
||||
|
||||
- Re-read the Phase 10 roadmap block in `ROADMAP.md`.
|
||||
- Re-read the phase artifacts under `notes/workspace-poc/phase-10-materialization-contract-research/`, with primary focus on:
|
||||
- `SUMMARY.md`
|
||||
- `DECISION.md`
|
||||
- Re-checked the implementation boundary that Phase 10 depends on:
|
||||
- `src/core/workspace/open.ts`
|
||||
- `src/core/workspace/change-create.ts`
|
||||
- `src/utils/change-metadata.ts`
|
||||
- `src/core/artifact-graph/types.ts`
|
||||
- `schemas/spec-driven/schema.yaml`
|
||||
- `src/commands/workspace.ts`
|
||||
- Confirmed the decision still matches the current product surface:
|
||||
- workspace changes record explicit `targets`
|
||||
- `workspace open` remains session-prep only
|
||||
- `workspace open` still points repo-local execution to `openspec apply --change <id> --repo <alias>`
|
||||
- change metadata remains narrow enough that a sidecar trace file is the least invasive Phase 11 follow-on
|
||||
- Rebuilt the CLI used by the documented smoke path:
|
||||
- `pnpm run build`
|
||||
- Result: passed
|
||||
- Re-ran the focused workspace regression slice:
|
||||
- `pnpm vitest run test/core/workspace/change-create.test.ts test/core/workspace/open.test.ts test/commands/workspace/open.test.ts test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts test/cli-e2e/workspace/workspace-open-cli.test.ts`
|
||||
- Result: 5 files passed, 19/19 tests passed
|
||||
- Re-ran a fresh copied-fixture smoke using `test/fixtures/workspace-poc/happy-path`:
|
||||
- created `shared-refresh` with `new change --targets app,api`
|
||||
- opened it with `workspace open --change shared-refresh --agent claude`
|
||||
- confirmed only `app` and `api` were attached
|
||||
- confirmed the instruction surface still says `Do not materialize repo-local changes from this session.`
|
||||
- confirmed the instruction surface still says `openspec apply --change shared-refresh --repo <alias>`
|
||||
- confirmed no repo-local `openspec/changes/shared-refresh` directory was created in `app`, `api`, or `docs`
|
||||
- confirmed the reported `.claude/commands/opsx/workspace-open.md` instruction-surface path is not actually written during this flow
|
||||
- Re-validated the Phase 10 acceptance criteria against `DECISION.md`:
|
||||
- 10.4 one v0 contract is chosen and explicit non-goals are named
|
||||
- 10.5 successful materialization is defined concretely
|
||||
- 10.6 repeat `apply` behavior is defined explicitly
|
||||
|
||||
## Issues found
|
||||
|
||||
- No product correctness issues were found in the reviewed boundary.
|
||||
- No acceptance-test gaps were found in `DECISION.md`.
|
||||
- No documentation corrections were required in `SUMMARY.md`, `DECISION.md`, or `MANUAL_TEST.md`.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- Rewrote this verification note to reflect the fresh verification pass and the exact checks rerun here.
|
||||
- No product or test code changes were required.
|
||||
- No ROADMAP checkbox corrections were needed because the Phase 10 checklist was already accurate.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No residual risk remains within the scope of this research phase itself.
|
||||
- Phase 11 still needs to implement the create-only, all-or-nothing materialization behavior described here; that is a forward implementation dependency, not a Phase 10 verification gap.
|
||||
@@ -0,0 +1,56 @@
|
||||
# Phase 11 Manual Test
|
||||
|
||||
Manual smoke re-run in a fresh local context on 2026-04-17 (Australia/Sydney) for ROADMAP Phase 11, cycle 1.
|
||||
|
||||
## Scenarios run
|
||||
|
||||
- Rebuilt the CLI with `pnpm run build`.
|
||||
- Re-ran the focused Phase 11 regression slice to confirm the current tree before the manual smoke:
|
||||
- `pnpm vitest run test/core/workspace/apply.test.ts test/core/workspace/change-create.test.ts test/core/workspace/open.test.ts test/commands/workspace/open.test.ts test/cli-e2e/workspace/workspace-apply-cli.test.ts test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts test/cli-e2e/workspace/workspace-open-cli.test.ts`
|
||||
- Created a fresh temp root and copied:
|
||||
- `test/fixtures/workspace-poc/happy-path/workspace` to `<tmp>/workspace`
|
||||
- `test/fixtures/workspace-poc/happy-path/repos` to `<tmp>/repos`
|
||||
- Ran the real CLI from the copied workspace with telemetry disabled:
|
||||
|
||||
```bash
|
||||
cd <tmp>/workspace
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js new change shared-refresh --targets app,api
|
||||
# seed proposal.md, design.md, and targets/{app,api}/{tasks.md,specs/**}
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js apply --change shared-refresh --repo app
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js apply --change shared-refresh --repo app
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js apply --change shared-refresh --repo docs
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js apply --change shared-refresh --repo missing
|
||||
```
|
||||
|
||||
- Inspected the copied temp workspace and repos after the run to confirm:
|
||||
- `repos/app/openspec/changes/shared-refresh/` was created
|
||||
- `repos/api/openspec/changes/shared-refresh/` remained absent
|
||||
- `repos/docs/openspec/changes/shared-refresh/` remained absent
|
||||
- `repos/app/openspec/changes/shared-refresh/` contained `.openspec.yaml`, `proposal.md`, `design.md`, `tasks.md`, `specs/`, and `.openspec.materialization.yaml`
|
||||
- `workspace/changes/shared-refresh/targets/app/tasks.md` remained present after apply
|
||||
- Inspected the CLI output to confirm:
|
||||
- the success path printed the repo-local destination and explicit authority handoff
|
||||
- the repeat run failed with a create-only collision
|
||||
- `docs` failed as an untargeted alias
|
||||
- `missing` failed as an unknown alias
|
||||
|
||||
## Results
|
||||
|
||||
- `pnpm run build` passed.
|
||||
- The focused Phase 11 regression slice passed: 7 files, 23/23 tests passed.
|
||||
- `apply --change shared-refresh --repo app` succeeded and created the repo-local change only in `app`.
|
||||
- The success output explicitly showed the handoff from workspace planning to repo-local execution.
|
||||
- The same-alias repeat run failed with the expected create-only collision message.
|
||||
- The untargeted `docs` run failed with the expected targeted-alias error.
|
||||
- The unknown `missing` run failed with the expected unregistered-alias error.
|
||||
- The workspace draft files remained in place after the successful materialization.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No product fixes were required from this manual smoke pass.
|
||||
- Updated this manual-test note to reflect the exact commands, inspections, and results from the fresh-context run.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No residual risks were found within the Phase 11 scope during this pass.
|
||||
- Broader materialization matrix coverage remains Phase 12 follow-on work rather than a Phase 11 defect.
|
||||
@@ -0,0 +1,68 @@
|
||||
# Phase 11 Summary
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `implementation`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
## Changes made
|
||||
|
||||
- Added a real top-level `openspec apply` command that materializes one targeted workspace change into one selected repo with `--change <id> --repo <alias>`.
|
||||
- Added shared workspace-change resolution in `src/core/workspace/change.ts` so `workspace open` and `apply` use the same change lookup and target metadata rules.
|
||||
- Added the Phase 11 materialization engine in `src/core/workspace/apply.ts`:
|
||||
- resolves the workspace root and selected repo alias
|
||||
- validates unknown vs untargeted aliases distinctly
|
||||
- validates required workspace source artifacts for the selected target slice
|
||||
- stages a repo-local bundle under `openspec/changes/` and atomically renames it into place
|
||||
- reuses the workspace change ID in the target repo
|
||||
- writes `.openspec.materialization.yaml` with the minimum trace metadata from Phase 10
|
||||
- keeps workspace planning artifacts untouched
|
||||
- Made the authority handoff explicit in the CLI success output: workspace target slice before `apply`, repo-local execution surface after `apply`.
|
||||
- Added focused Phase 11 coverage in:
|
||||
- `test/core/workspace/apply.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-apply-cli.test.ts`
|
||||
- Updated the Phase 11 checklist in `ROADMAP.md`.
|
||||
|
||||
## Tests or research performed
|
||||
|
||||
- Re-read the Phase 11 block in `ROADMAP.md`.
|
||||
- Re-read the Phase 10 contract in `notes/workspace-poc/phase-10-materialization-contract-research/DECISION.md`.
|
||||
- Reviewed the current workspace implementation boundary in:
|
||||
- `src/core/workspace/open.ts`
|
||||
- `src/core/workspace/registry.ts`
|
||||
- `src/core/workspace/change-create.ts`
|
||||
- `src/utils/change-metadata.ts`
|
||||
- Built the CLI:
|
||||
- `pnpm run build`
|
||||
- Ran the focused Phase 11 regression slice:
|
||||
- `pnpm vitest run test/core/workspace/apply.test.ts test/core/workspace/change-create.test.ts test/core/workspace/open.test.ts test/commands/workspace/open.test.ts test/cli-e2e/workspace/workspace-apply-cli.test.ts test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts test/cli-e2e/workspace/workspace-open-cli.test.ts`
|
||||
- Ran a fresh copied-fixture CLI smoke using `test/fixtures/workspace-poc/happy-path`:
|
||||
- created `shared-refresh` with `new change --targets app,api`
|
||||
- seeded the target slice files
|
||||
- ran `apply --change shared-refresh --repo app`
|
||||
- re-ran `apply` for the same alias to confirm create-only collision behavior
|
||||
- ran `apply` for `docs` and `missing` to confirm untargeted and unknown alias failures
|
||||
|
||||
## Results
|
||||
|
||||
- `pnpm run build` passed.
|
||||
- The focused workspace regression slice passed: 7 files, 23/23 tests passed.
|
||||
- The new `apply` flow now satisfies the Phase 11 contract:
|
||||
- repo-local materialization uses the same change ID as the workspace change
|
||||
- only the selected target repo is modified
|
||||
- unknown and untargeted aliases fail with distinct target-selection errors
|
||||
- repeating `apply` for the same target repo fails with a create-only collision
|
||||
- applying the same change to a different targeted alias still works
|
||||
- workspace drafts remain intact after successful materialization
|
||||
- The repo-local bundle shape matches the Phase 10 decision:
|
||||
- `.openspec.yaml`
|
||||
- `proposal.md`
|
||||
- `design.md`
|
||||
- `tasks.md`
|
||||
- `specs/`
|
||||
- `.openspec.materialization.yaml`
|
||||
|
||||
## Blockers and next-step notes
|
||||
|
||||
- No blockers remain for Phase 11.
|
||||
- No new roadmap phases were required from this implementation pass.
|
||||
- Phase 12 can now focus on expanding the materialization test matrix rather than defining or changing the contract.
|
||||
@@ -0,0 +1,55 @@
|
||||
# Phase 11 Verification
|
||||
|
||||
Independent verification re-run in a fresh local context on 2026-04-17 (Australia/Sydney) for ROADMAP Phase 11, cycle 1.
|
||||
|
||||
## Checks performed
|
||||
|
||||
- Re-read the Phase 11 roadmap block in `ROADMAP.md`.
|
||||
- Re-read the current phase artifacts:
|
||||
- `notes/workspace-poc/phase-11-apply-materialization/SUMMARY.md`
|
||||
- `notes/workspace-poc/phase-11-apply-materialization/MANUAL_TEST.md`
|
||||
- Re-read the Phase 10 materialization contract in `notes/workspace-poc/phase-10-materialization-contract-research/DECISION.md`.
|
||||
- Re-checked the implementation surface added for this phase:
|
||||
- `src/core/workspace/change.ts`
|
||||
- `src/core/workspace/apply.ts`
|
||||
- `src/commands/workflow/apply.ts`
|
||||
- `src/cli/index.ts`
|
||||
- `src/core/workspace/open.ts`
|
||||
- `src/core/workspace/registry.ts`
|
||||
- Rebuilt the CLI used by the verification and manual smoke path:
|
||||
- `pnpm run build`
|
||||
- Result: passed
|
||||
- Re-ran the focused workspace regression slice:
|
||||
- `pnpm vitest run test/core/workspace/apply.test.ts test/core/workspace/change-create.test.ts test/core/workspace/open.test.ts test/commands/workspace/open.test.ts test/cli-e2e/workspace/workspace-apply-cli.test.ts test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts test/cli-e2e/workspace/workspace-open-cli.test.ts`
|
||||
- Result: 7 files passed, 23/23 tests passed
|
||||
- Ran a fresh copied-fixture CLI smoke outside the test harness:
|
||||
- copied `test/fixtures/workspace-poc/happy-path/workspace` and `test/fixtures/workspace-poc/happy-path/repos` into a temp root
|
||||
- ran `node dist/cli/index.js new change shared-refresh --targets app,api`
|
||||
- seeded `proposal.md`, `design.md`, and the per-target `tasks.md` and `specs/` files
|
||||
- ran `node dist/cli/index.js apply --change shared-refresh --repo app`
|
||||
- re-ran the same command for `app` to confirm create-only collision behavior
|
||||
- ran `apply` for `docs` and `missing` to confirm untargeted and unknown alias failures
|
||||
- Verified the acceptance criteria through the focused suites and the fresh CLI smoke:
|
||||
- repo-local materialization reuses the workspace change ID
|
||||
- only the selected target repo gets the materialized change
|
||||
- unknown and untargeted aliases fail distinctly
|
||||
- same-alias repeat `apply` fails with a create-only collision while another targeted alias can still materialize
|
||||
- workspace drafts remain unchanged after successful materialization
|
||||
- the repo-local bundle contains `.openspec.yaml`, `proposal.md`, `design.md`, `tasks.md`, `specs/`, and `.openspec.materialization.yaml`
|
||||
- the success output makes the workspace-to-repo authority handoff explicit
|
||||
|
||||
## Issues found
|
||||
|
||||
- No product correctness issues were found in the implemented materialization flow.
|
||||
- No acceptance-test gaps remained after the focused verification run.
|
||||
- Documentation-quality issue: the previous verification note mixed implementation work into the "Fixes applied" section instead of keeping that section scoped to verification-stage changes.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No product code changes were required during this verification pass.
|
||||
- Updated this verification note so it records the checks run in this pass and keeps the issues and fixes sections scoped to verification work.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No known residual risk remains inside the Phase 11 scope.
|
||||
- Phase 12 still needs to broaden coverage around the materialization matrix, but that is follow-on validation work rather than a correctness gap in the implemented Phase 11 contract.
|
||||
@@ -0,0 +1,53 @@
|
||||
# Phase 12 Manual Test
|
||||
|
||||
Manual smoke re-run in a fresh local context on 2026-04-17 (Australia/Sydney) for ROADMAP Phase 12, cycle 1, stage `manual-test`.
|
||||
|
||||
## Scenarios run
|
||||
|
||||
- Rebuilt the CLI with `pnpm run build`.
|
||||
- Re-ran the focused Phase 12 regression slice before the manual smoke:
|
||||
- `pnpm vitest run test/core/workspace/apply.test.ts test/commands/workflow/apply.test.ts test/cli-e2e/workspace/workspace-apply-cli.test.ts test/cli-e2e/workspace/workspace-create-cli.test.ts test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts`
|
||||
- Scenario 1: happy-path selective materialization into one repo out of many using copied fixture repos and isolated XDG roots.
|
||||
- Ran `workspace create phase-12-manual --json`.
|
||||
- Registered `app`, `api`, and `docs` with `workspace add-repo ... --json`.
|
||||
- Ran `new change shared-refresh --targets app,api,docs`.
|
||||
- Ran `apply --change shared-refresh --repo app --json`.
|
||||
- Re-ran `apply --change shared-refresh --repo app` to confirm repeat-apply collision behavior.
|
||||
- Inspected the temp repo trees and the JSON payload after apply.
|
||||
- Scenario 2: dirty-workspace stale alias failure using the committed dirty fixture plus a rewritten temp `local.yaml` overlay with `docs` still pointing at a missing path.
|
||||
- Copied `test/fixtures/workspace-poc/dirty/workspace` and `test/fixtures/workspace-poc/dirty/repos` into a temp root.
|
||||
- Rewrote `.openspec/local.yaml` to absolute temp paths for `app` and `api`, while leaving `docs` pointed at `<tmp>/repos/docs-missing`.
|
||||
- Ran `new change docs-repair --targets docs`.
|
||||
- Ran `apply --change docs-repair --repo docs`.
|
||||
- Inspected the temp repo trees to confirm no new repo-local change was created in the healthy repos.
|
||||
|
||||
## Results
|
||||
|
||||
- `pnpm run build` passed.
|
||||
- The focused Phase 12 regression slice passed: 5 files, 17/17 tests passed.
|
||||
- Scenario 1 passed end to end:
|
||||
- workspace creation and repo registration succeeded
|
||||
- `new change shared-refresh --targets app,api,docs` succeeded
|
||||
- `apply --change shared-refresh --repo app --json` succeeded
|
||||
- the JSON payload reported `change.id = shared-refresh`
|
||||
- `target.changePath` ended in `/shared-refresh`, so the repo-local change ID exactly matched the workspace change ID
|
||||
- only `app` received `openspec/changes/shared-refresh/`
|
||||
- `api` and `docs` kept only their pre-existing fixture changes and did not receive `shared-refresh`
|
||||
- the materialized app change contained `.openspec.yaml`, `proposal.md`, `design.md`, `tasks.md`, `specs/`, and `.openspec.materialization.yaml`
|
||||
- the repeat `app` apply exited with code `1` and surfaced the explicit create-only collision
|
||||
- Scenario 2 passed for the failure path:
|
||||
- `new change docs-repair --targets docs` succeeded inside the copied dirty workspace
|
||||
- `apply --change docs-repair --repo docs` exited with code `1`
|
||||
- the error reported `Target alias 'docs' points to a missing repo path: <tmp>/repos/docs-missing`
|
||||
- the error also told the user to run `openspec workspace doctor` and repair the failing alias before retrying
|
||||
- no `docs-repair` repo-local materialization appeared in `app` or `api`, so the stale-path failure did not produce silent partial success
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No product fixes were required from this manual smoke pass.
|
||||
- Updated this manual-test note to capture the exact fresh-context scenarios, outputs, and repo-tree inspections from the current run.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No residual risks were found within the Phase 12 scope during this pass.
|
||||
- Status roll-up and completion semantics remain future work for Phase 13 onward.
|
||||
@@ -0,0 +1,62 @@
|
||||
# Phase 12 Summary
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `implementation`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
## Changes made
|
||||
|
||||
- Expanded `test/core/workspace/apply.test.ts` to cover:
|
||||
- missing target-slice source artifacts during materialization plan construction
|
||||
- stale dirty-workspace alias resolution failures
|
||||
- pre-existing target change collisions without overwrite
|
||||
- Added `test/commands/workflow/apply.test.ts` to cover the direct command surface for:
|
||||
- apply success output
|
||||
- apply failure on stale repo resolution
|
||||
- repeat-apply create-only behavior
|
||||
- Expanded `test/cli-e2e/workspace/workspace-apply-cli.test.ts` to cover:
|
||||
- dirty-workspace stale-alias failure through the built CLI
|
||||
- a fresh `workspace create -> add-repo -> new change -> apply` flow using copied `happy-path` fixture repos
|
||||
- selective materialization into only one repo out of many
|
||||
- Updated the Phase 12 checklist in `ROADMAP.md`.
|
||||
|
||||
## Tests or research performed
|
||||
|
||||
- Re-read the Phase 12 roadmap block in `ROADMAP.md`.
|
||||
- Reviewed the current materialization implementation and existing tests in:
|
||||
- `src/core/workspace/apply.ts`
|
||||
- `src/commands/workflow/apply.ts`
|
||||
- `test/core/workspace/apply.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-apply-cli.test.ts`
|
||||
- `test/helpers/workspace-sandbox.ts`
|
||||
- Built the CLI:
|
||||
- `pnpm run build`
|
||||
- Ran the focused Phase 12 verification slice:
|
||||
- `pnpm vitest run test/core/workspace/apply.test.ts test/commands/workflow/apply.test.ts test/cli-e2e/workspace/workspace-apply-cli.test.ts test/cli-e2e/workspace/workspace-create-cli.test.ts test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts`
|
||||
- Ran a fresh manual CLI smoke in an isolated temp root with telemetry disabled:
|
||||
- `workspace create phase-12-manual --json`
|
||||
- `workspace add-repo app <tmp>/repos/app --json`
|
||||
- `workspace add-repo api <tmp>/repos/api --json`
|
||||
- `new change shared-refresh --targets app,api`
|
||||
- `apply --change shared-refresh --repo app --json`
|
||||
- repeated `apply --change shared-refresh --repo app` to confirm collision behavior
|
||||
|
||||
## Results
|
||||
|
||||
- `pnpm run build` passed.
|
||||
- The focused Phase 12 verification slice passed: 5 files, 17/17 tests passed.
|
||||
- The expanded coverage now proves the Phase 12 acceptance surface:
|
||||
- the repo-local change directory name matches the workspace change ID
|
||||
- apply writes only to the selected alias
|
||||
- stale-path and collision failures are explicit and do not produce silent partial success
|
||||
- the `happy-path` fixture repos support the fresh create/add-repo/new-change/apply flow through the built CLI
|
||||
- The manual smoke matched the automated results:
|
||||
- `shared-refresh` materialized only into `app`
|
||||
- `api` remained untouched
|
||||
- the repeat `app` apply failed with the expected create-only collision
|
||||
|
||||
## Blockers and next-step notes
|
||||
|
||||
- No blockers remain for Phase 12.
|
||||
- No new roadmap phases were required from this pass.
|
||||
- Phase 13 can build status semantics on top of a materially better-tested handoff surface.
|
||||
@@ -0,0 +1,57 @@
|
||||
# Phase 12 Verification
|
||||
|
||||
Independent verification re-run in a fresh local context on 2026-04-17 (Australia/Sydney) for ROADMAP Phase 12, cycle 1, stage `verification`.
|
||||
|
||||
## Checks performed
|
||||
|
||||
- Re-read the Phase 12 roadmap block in `ROADMAP.md`.
|
||||
- Re-read the current phase artifacts to verify scope coverage and documentation quality:
|
||||
- `notes/workspace-poc/phase-12-test-apply-materialization/SUMMARY.md`
|
||||
- `notes/workspace-poc/phase-12-test-apply-materialization/MANUAL_TEST.md`
|
||||
- Re-checked the Phase 12 implementation boundaries in:
|
||||
- `src/core/workspace/apply.ts`
|
||||
- `src/commands/workflow/apply.ts`
|
||||
- `src/core/workspace/change-create.ts`
|
||||
- `src/core/workspace/registry.ts`
|
||||
- `test/helpers/workspace-assertions.ts`
|
||||
- Re-checked the automated Phase 12 coverage in:
|
||||
- `test/core/workspace/apply.test.ts`
|
||||
- `test/commands/workflow/apply.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-apply-cli.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-create-cli.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts`
|
||||
- Rebuilt the CLI used by the e2e and direct CLI paths:
|
||||
- `pnpm run build`
|
||||
- Result: passed
|
||||
- Re-ran the focused Phase 12 regression slice:
|
||||
- `pnpm vitest run test/core/workspace/apply.test.ts test/commands/workflow/apply.test.ts test/cli-e2e/workspace/workspace-apply-cli.test.ts test/cli-e2e/workspace/workspace-create-cli.test.ts test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts`
|
||||
- Result: 5 files passed, 17/17 tests passed
|
||||
- Ran an isolated real-CLI smoke in a temp XDG root using copied `happy-path` fixture repos:
|
||||
- `workspace create phase-12-verify --json`
|
||||
- `workspace add-repo app <tmp>/repos/app --json`
|
||||
- `workspace add-repo api <tmp>/repos/api --json`
|
||||
- `new change shared-refresh --targets app,api`
|
||||
- `apply --change shared-refresh --repo app --json`
|
||||
- repeated `apply --change shared-refresh --repo app`
|
||||
- Confirmed:
|
||||
- `apply` returned `change.id = shared-refresh`
|
||||
- the repo-local change directory basename was `shared-refresh`
|
||||
- only `app` received `openspec/changes/shared-refresh/`
|
||||
- `api` remained untouched
|
||||
- repeat apply exited with code `1` and surfaced the explicit create-only collision
|
||||
|
||||
## Issues found
|
||||
|
||||
- No product correctness issues were found during this verification pass.
|
||||
- No acceptance-test gaps were found in the current Phase 12 implementation or coverage.
|
||||
- No documentation-quality issues were found in the phase summary or manual-test notes; both matched the current implementation and rerun results.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No product code changes were required during this verification pass.
|
||||
- Updated this verification note to capture the exact rerun scope, implementation-boundary review, and direct CLI smoke evidence.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No known residual risks remain inside the Phase 12 scope.
|
||||
- Phase 13 remains the next boundary: status and completion semantics still need their own contract and implementation work.
|
||||
@@ -0,0 +1,275 @@
|
||||
# Phase 13 Decision
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `implementation`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
## Recommended v0 status model
|
||||
|
||||
Phase 14 should implement workspace-aware roll-up instead of reusing raw artifact-graph status for workspace changes.
|
||||
|
||||
The minimum honest v0 model is:
|
||||
|
||||
- overall workspace-change state: `planned`, `in-progress`, `blocked`, `soft-done`, `hard-done`
|
||||
- per-target state: `planned`, `materialized`, `in-progress`, `blocked`, `complete`
|
||||
- coordination state: `planned`, `in-progress`, `blocked`, `complete`
|
||||
|
||||
This split is necessary because the current generic `status --change` command assumes repo-local topology:
|
||||
|
||||
- root-level `tasks.md`
|
||||
- root-level `specs/`
|
||||
- artifact completion by file existence
|
||||
|
||||
A workspace change does not have that layout. The direct manual probe for this phase showed that running `status --change shared-refresh --json` from a workspace root reports `proposal` and `design` as done, `specs` as ready, and `tasks` as blocked because it is looking for repo-local root artifacts that do not exist in workspace topology. That output is valid for the existing command, but it is not an honest workspace roll-up.
|
||||
|
||||
The current implementation surface already gives the right raw signals for a custom roll-up:
|
||||
|
||||
- `src/core/workspace/change-create.ts` creates workspace coordination tasks at `tasks/coordination.md` and per-target draft tasks at `targets/<alias>/tasks.md`
|
||||
- `src/core/workspace/apply.ts` reuses the workspace change ID in the target repo and writes `.openspec.materialization.yaml`
|
||||
- `src/utils/task-progress.ts` and `src/core/list.ts` already define tracked progress in terms of checkbox counts inside `tasks.md`
|
||||
|
||||
The practical conclusion is:
|
||||
|
||||
- use task-progress counts for progress and completion
|
||||
- use repo-local materialization plus trace metadata for execution provenance
|
||||
- do not infer archive from repo-local task completion
|
||||
|
||||
## One precise derivation rule per state
|
||||
|
||||
### `planned`
|
||||
|
||||
Rule:
|
||||
|
||||
- A target is `planned` when it is declared in the workspace change metadata, the target repo alias resolves cleanly, and no valid repo-local materialization exists at `<resolved-repo>/openspec/changes/<change-id>/`.
|
||||
- The overall workspace change is `planned` only when coordination is `planned` and every target is `planned`.
|
||||
|
||||
Why:
|
||||
|
||||
- an unmaterialized target is still using the workspace draft as its current authority
|
||||
- absence of repo-local execution state is not by itself a failure
|
||||
|
||||
### `materialized`
|
||||
|
||||
Rule:
|
||||
|
||||
- A target is `materialized` when a valid repo-local materialization exists and its repo-local task progress is either `0/<n>` or `0/0`.
|
||||
|
||||
Why:
|
||||
|
||||
- the current repo-local `list --json` surface collapses `0/<n>` into `in-progress`
|
||||
- the workspace roll-up needs one extra state to distinguish "execution surface exists" from "tracked work has started"
|
||||
|
||||
### `in-progress`
|
||||
|
||||
Rule:
|
||||
|
||||
- A coordination slice or target is `in-progress` when its tracked task progress is `0 < completed < total`.
|
||||
- The overall workspace change is `in-progress` when it is not `blocked`, `soft-done`, or `hard-done`, and at least one target is `materialized`, `in-progress`, or `complete`, or coordination is `in-progress` or `complete`.
|
||||
|
||||
Why:
|
||||
|
||||
- task progress is the only current product signal that distinguishes "some execution happened" from "nothing started"
|
||||
|
||||
### `blocked`
|
||||
|
||||
Rule:
|
||||
|
||||
- A coordination slice or target is `blocked` when status cannot classify it honestly because a required workspace or repo-local inspection surface is missing or inconsistent.
|
||||
- The overall workspace change is `blocked` when coordination is `blocked` or any target is `blocked`.
|
||||
|
||||
For v0, target-blocked conditions are:
|
||||
|
||||
- the target alias is declared on the workspace change but is missing from workspace repo metadata
|
||||
- the target alias is missing from `.openspec/local.yaml`
|
||||
- the resolved repo path is missing, not a directory, or no longer contains `openspec/`
|
||||
- a same-ID repo-local change exists, but `.openspec.materialization.yaml` is missing, malformed, or does not match this workspace and target alias
|
||||
- a traced repo-local change exists, but `tasks.md` cannot be read for progress derivation
|
||||
|
||||
For v0, coordination-blocked conditions are:
|
||||
|
||||
- `tasks/coordination.md` is missing or unreadable
|
||||
|
||||
Why:
|
||||
|
||||
- `blocked` should mean "the status command cannot tell the truth from the current state"
|
||||
- v0 should not invent softer warning labels when the underlying surface is actually broken
|
||||
|
||||
### `complete`
|
||||
|
||||
Rule:
|
||||
|
||||
- A coordination slice or target is `complete` when its tracked task progress is `n/n` with `n > 0`.
|
||||
|
||||
Why:
|
||||
|
||||
- `complete` is task-complete, not archive-complete
|
||||
- this keeps completion aligned with the current repo-local `list` semantics
|
||||
|
||||
### `soft-done`
|
||||
|
||||
Rule:
|
||||
|
||||
- The overall workspace change is `soft-done` when coordination is `complete` and every target is `complete`.
|
||||
|
||||
Why:
|
||||
|
||||
- this matches the PRD and decision-record definition of "all known coordination work and tracked target work are complete"
|
||||
- it still leaves explicit top-level archive for the final lifecycle step
|
||||
|
||||
### `hard-done`
|
||||
|
||||
Rule:
|
||||
|
||||
- The overall workspace change is `hard-done` only when an explicit workspace-level archive/completion marker exists for that workspace change.
|
||||
|
||||
Why:
|
||||
|
||||
- repo-local archive remains repo-local
|
||||
- repo-local task completion or repo-local archive alone must never imply top-level finality
|
||||
|
||||
## Workspace-only versus repo-local inspection
|
||||
|
||||
The minimum source split for v0 is:
|
||||
|
||||
### Uses workspace state alone
|
||||
|
||||
- workspace metadata and target membership
|
||||
- coordination task progress from `changes/<id>/tasks/coordination.md`
|
||||
- pre-materialization draft task progress from `changes/<id>/targets/<alias>/tasks.md`
|
||||
- overall `hard-done` once Phase 16 adds explicit workspace archive state
|
||||
|
||||
### Requires repo-local inspection
|
||||
|
||||
- whether a target has been materialized at all
|
||||
- whether the materialized change belongs to this workspace target rather than just sharing the same change ID
|
||||
- repo-local execution progress and completion from `<repo>/openspec/changes/<id>/tasks.md`
|
||||
- blocked states caused by stale repo paths, missing `openspec/`, or malformed materialization traces
|
||||
|
||||
### Mixed roll-up states
|
||||
|
||||
- overall `planned` depends on workspace coordination plus every target still being `planned`
|
||||
- overall `in-progress` depends on both workspace coordination and any materialized target state
|
||||
- overall `blocked` depends on any blocked coordination or target slice
|
||||
- overall `soft-done` depends on coordination plus every target reaching `complete`
|
||||
|
||||
## Reverse-link decision
|
||||
|
||||
Decision:
|
||||
|
||||
- reverse links are required in v0, but the minimum required reverse link is the existing `.openspec.materialization.yaml` sidecar
|
||||
|
||||
What is required:
|
||||
|
||||
- keep reusing the workspace change ID as the repo-local change ID
|
||||
- keep writing `.openspec.materialization.yaml`
|
||||
- Phase 14 status should validate:
|
||||
- `source: workspace`
|
||||
- `workspaceName` matches the current workspace
|
||||
- `targetAlias` matches the target being inspected
|
||||
|
||||
What is not required:
|
||||
|
||||
- no new backlink fields in `.openspec.yaml`
|
||||
- no absolute workspace paths
|
||||
- no extra workspace change ID field beyond the repo-local directory name, because Phase 11 already made the directory name match the workspace change ID
|
||||
|
||||
Why this is the minimum honest choice:
|
||||
|
||||
- without the sidecar, a same-ID repo-local change could be mistaken for a materialized workspace target even if it did not originate from this workspace flow
|
||||
- with the sidecar, Phase 14 can distinguish "materialized from this workspace" from "same change name exists locally for some other reason"
|
||||
|
||||
## Minimum JSON shape to lock down in Phase 14
|
||||
|
||||
Phase 14 should keep the JSON contract small and stable:
|
||||
|
||||
```json
|
||||
{
|
||||
"change": {
|
||||
"id": "shared-refresh",
|
||||
"state": "planned"
|
||||
},
|
||||
"coordination": {
|
||||
"state": "planned",
|
||||
"tasks": {
|
||||
"completed": 0,
|
||||
"total": 2
|
||||
}
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"alias": "api",
|
||||
"state": "planned",
|
||||
"source": "workspace",
|
||||
"tasks": {
|
||||
"completed": 0,
|
||||
"total": 2
|
||||
},
|
||||
"problems": []
|
||||
},
|
||||
{
|
||||
"alias": "app",
|
||||
"state": "materialized",
|
||||
"source": "repo",
|
||||
"tasks": {
|
||||
"completed": 0,
|
||||
"total": 2
|
||||
},
|
||||
"problems": []
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Contract notes:
|
||||
|
||||
- `change.id` is the workspace change ID
|
||||
- `change.state` is only `planned`, `in-progress`, `blocked`, `soft-done`, or `hard-done`
|
||||
- `coordination.state` is only `planned`, `in-progress`, `blocked`, or `complete`
|
||||
- target `state` is only `planned`, `materialized`, `in-progress`, `blocked`, or `complete`
|
||||
- `targets` are sorted by alias for deterministic tests
|
||||
- `source` is `workspace` before materialization and `repo` after materialization
|
||||
- `tasks` always reflects the authority for the current `source`
|
||||
- `problems` is empty unless the slice is `blocked`
|
||||
- the JSON should not include spinner text, ANSI codes, or absolute repo paths
|
||||
|
||||
## Rejected alternatives
|
||||
|
||||
### Rejected: reuse raw artifact-graph `status --change` for workspace roll-up
|
||||
|
||||
Why rejected:
|
||||
|
||||
- the current command is correct for repo-local change topology, not workspace topology
|
||||
- it looks for root `specs/` and root `tasks.md`, which the workspace change intentionally does not have
|
||||
- it would misreport workspace state instead of clarifying it
|
||||
|
||||
### Rejected: treat `0/<n>` repo-local task progress as `in-progress` in workspace roll-up
|
||||
|
||||
Why rejected:
|
||||
|
||||
- that loses the important distinction between "materialized, but untouched" and "work has actually started"
|
||||
- the roadmap explicitly wants both `materialized` and `in progress`
|
||||
|
||||
### Rejected: trust any same-ID repo-local change without a workspace trace sidecar
|
||||
|
||||
Why rejected:
|
||||
|
||||
- same-name repo-local changes are not strong enough provenance
|
||||
- status would risk claiming a workspace target was materialized when it was not
|
||||
|
||||
### Rejected: infer `hard-done` from repo-local archive or repo-local task completion
|
||||
|
||||
Why rejected:
|
||||
|
||||
- the PRD and roadmap keep workspace archive as an explicit top-level action
|
||||
- different repos can finish or archive at different times without closing the whole workspace change
|
||||
|
||||
## Phase 14 implications
|
||||
|
||||
Phase 14 should implement only this contract:
|
||||
|
||||
- custom workspace-aware roll-up logic
|
||||
- checkbox-based task progress for coordination and target completion
|
||||
- materialization provenance validated through `.openspec.materialization.yaml`
|
||||
- target states distinct from overall workspace states
|
||||
|
||||
No new roadmap phase is required from this decision.
|
||||
@@ -0,0 +1,75 @@
|
||||
# Phase 13 Manual Test
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `manual-test`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
Manual smoke run in a fresh local context for ROADMAP Phase 13 only.
|
||||
|
||||
## Scenarios run
|
||||
|
||||
- Built the current CLI with `pnpm run build`.
|
||||
- Created a fresh temp root and copied:
|
||||
- `test/fixtures/workspace-poc/happy-path/workspace` to `<tmp>/workspace`
|
||||
- `test/fixtures/workspace-poc/happy-path/repos` to `<tmp>/repos`
|
||||
- Ran the real CLI from the copied workspace and repo roots with telemetry disabled:
|
||||
|
||||
```bash
|
||||
cd <tmp>/workspace
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js new change shared-refresh --targets app,api
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js status --change shared-refresh --json
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js apply --change shared-refresh --repo app --json
|
||||
|
||||
cd <tmp>/repos/app
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js list --json
|
||||
|
||||
# edit tasks to simulate partial execution
|
||||
printf '%s\n' '## App Tasks' '- [x] Finish API wiring' '- [ ] Land UI follow-up' > openspec/changes/shared-refresh/tasks.md
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js list --json
|
||||
|
||||
# edit tasks to simulate completion
|
||||
printf '%s\n' '## App Tasks' '- [x] Finish API wiring' '- [x] Land UI follow-up' > openspec/changes/shared-refresh/tasks.md
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js list --json
|
||||
|
||||
cat openspec/changes/shared-refresh/.openspec.materialization.yaml
|
||||
```
|
||||
|
||||
- Inspected the raw workspace-root `status --change` JSON before apply.
|
||||
- Inspected repo-local `list --json` immediately after apply, after a partial task update, and after a full task update.
|
||||
- Inspected the materialization sidecar contents.
|
||||
|
||||
## Results
|
||||
|
||||
- `pnpm run build` passed.
|
||||
- `new change shared-refresh --targets app,api` succeeded and created the workspace change.
|
||||
- The raw workspace-root `status --change shared-refresh --json` output still reported:
|
||||
- `proposal: done`
|
||||
- `design: done`
|
||||
- `specs: ready`
|
||||
- `tasks: blocked`
|
||||
- That confirmed the current generic status command is still interpreting workspace changes as if they had repo-local root `specs/` and `tasks.md`.
|
||||
- `apply --change shared-refresh --repo app --json` succeeded and wrote one repo-local change under `repos/app/openspec/changes/shared-refresh`.
|
||||
- Repo-local `list --json` reported `shared-refresh` as:
|
||||
- `in-progress` at `0/2` immediately after apply
|
||||
- `in-progress` at `1/2` after one checked task
|
||||
- `complete` at `2/2` after both tasks were checked
|
||||
- The fixture also still contained the unrelated baseline entry `app-ui-polish` with `status: no-tasks`; it did not affect the `shared-refresh` probe.
|
||||
- The materialization sidecar contained:
|
||||
- `source: workspace`
|
||||
- `workspaceName: happy-path`
|
||||
- `targetAlias: app`
|
||||
- `materializedAt: 2026-04-17T00:44:12.632Z`
|
||||
- The current product surface therefore supports the Phase 13 decision:
|
||||
- task checkboxes are the real progress signal
|
||||
- raw artifact-graph status is not workspace-aware
|
||||
- the sidecar is the minimum reverse link needed for honest roll-up
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No product or test code fixes were required from this manual pass.
|
||||
- Updated this manual-test note to reflect the fresh smoke run and explicit `manual-test` stage metadata.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- None found within the scope of Phase 13.
|
||||
- Phase 14 still needs to implement the actual workspace roll-up behavior defined in `DECISION.md`; that is a forward implementation dependency, not a manual-test gap.
|
||||
@@ -0,0 +1,68 @@
|
||||
# Phase 13 Summary
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `implementation`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
## Changes made
|
||||
|
||||
- Added the Phase 13 research decision in `notes/workspace-poc/phase-13-status-research/DECISION.md`.
|
||||
- Added Phase 13 verification and manual-test artifacts:
|
||||
- `notes/workspace-poc/phase-13-status-research/VERIFY.md`
|
||||
- `notes/workspace-poc/phase-13-status-research/MANUAL_TEST.md`
|
||||
- Chose one concrete v0 status roll-up model for the workspace POC:
|
||||
- overall workspace states: `planned`, `in-progress`, `blocked`, `soft-done`, `hard-done`
|
||||
- per-target states: `planned`, `materialized`, `in-progress`, `blocked`, `complete`
|
||||
- coordination states: `planned`, `in-progress`, `blocked`, `complete`
|
||||
- Decided that Phase 14 must derive progress from task checkboxes plus materialization provenance instead of reusing raw artifact-graph status for workspace changes.
|
||||
- Decided that reverse links are required in v0, but the existing `.openspec.materialization.yaml` sidecar is the only required backlink.
|
||||
- Defined the minimum JSON status shape for Phase 14 tests to lock down.
|
||||
- Updated the Phase 13 checklist in `ROADMAP.md`.
|
||||
|
||||
## Tests or research performed
|
||||
|
||||
- Re-read the Phase 13, 14, 15, and 16 roadmap blocks in `ROADMAP.md`.
|
||||
- Reviewed the current implementation surfaces that define the available status signals:
|
||||
- `src/commands/workflow/status.ts`
|
||||
- `src/core/artifact-graph/instruction-loader.ts`
|
||||
- `src/core/view.ts`
|
||||
- `src/core/list.ts`
|
||||
- `src/utils/task-progress.ts`
|
||||
- `src/core/workspace/change-create.ts`
|
||||
- `src/core/workspace/apply.ts`
|
||||
- `src/utils/change-metadata.ts`
|
||||
- `src/core/workspace/metadata.ts`
|
||||
- Re-read the prior workspace POC anchors:
|
||||
- `WORKSPACE_POC_PRD.md`
|
||||
- `WORKSPACE_POC_DECISION_RECORD.md`
|
||||
- `notes/workspace-poc/phase-07-open-contract-research/DECISION.md`
|
||||
- `notes/workspace-poc/phase-10-materialization-contract-research/DECISION.md`
|
||||
- Ran focused automated validation:
|
||||
- `pnpm run build`
|
||||
- `pnpm vitest run test/core/workspace/apply.test.ts test/commands/artifact-workflow.test.ts test/core/artifact-graph/instruction-loader.test.ts`
|
||||
- Ran a fresh copied-fixture manual probe against `test/fixtures/workspace-poc/happy-path` with the built CLI:
|
||||
- created `shared-refresh` in the copied workspace
|
||||
- ran `status --change shared-refresh --json` from the workspace root before apply
|
||||
- ran `apply --change shared-refresh --repo app --json`
|
||||
- ran `list --json` in the copied `app` repo immediately after apply, after `1/2` tasks, and after `2/2` tasks
|
||||
- inspected `.openspec.materialization.yaml`
|
||||
|
||||
## Results
|
||||
|
||||
- The generic artifact-graph `status --change` command is not an honest workspace-status implementation because it inspects repo-local root artifact paths that workspace changes do not have.
|
||||
- The current codebase already exposes the minimum signals needed for Phase 14:
|
||||
- workspace coordination progress through `tasks/coordination.md`
|
||||
- target draft progress through `targets/<alias>/tasks.md`
|
||||
- repo-local execution progress through `openspec/changes/<id>/tasks.md`
|
||||
- materialization provenance through `.openspec.materialization.yaml`
|
||||
- The manual probe confirmed the key semantic gap Phase 14 must close:
|
||||
- immediately after `apply`, repo-local `list --json` reports `shared-refresh` as `in-progress` at `0/2`
|
||||
- Phase 14 therefore needs a distinct workspace-level `materialized` state for `0/<n>` or `0/0` repo-local task progress
|
||||
- The existing materialization sidecar is sufficient to act as the required v0 reverse link without expanding `.openspec.yaml`.
|
||||
- The note now defines one precise derivation rule per requested state, clearly separates workspace-only versus repo-local inspection, and resolves the reverse-link question.
|
||||
|
||||
## Blockers and next-step notes
|
||||
|
||||
- No blockers remain for Phase 13.
|
||||
- No new bounded follow-up phase was required from this research pass.
|
||||
- Phase 14 should implement only the custom roll-up and JSON shape described in `DECISION.md`.
|
||||
@@ -0,0 +1,55 @@
|
||||
# Phase 13 Verification
|
||||
|
||||
Independent verification re-run in a fresh local context on 2026-04-17 (Australia/Sydney) for ROADMAP Phase 13, cycle 1.
|
||||
|
||||
## Checks performed
|
||||
|
||||
- Re-read the Phase 13 roadmap block in `ROADMAP.md`.
|
||||
- Re-read the phase artifacts under `notes/workspace-poc/phase-13-status-research/`, with focus on `SUMMARY.md` and `DECISION.md`.
|
||||
- Re-checked the implementation boundary the research note depends on:
|
||||
- `src/commands/workflow/status.ts`
|
||||
- `src/core/artifact-graph/instruction-loader.ts`
|
||||
- `src/core/list.ts`
|
||||
- `src/utils/task-progress.ts`
|
||||
- `src/core/workspace/change-create.ts`
|
||||
- `src/core/workspace/apply.ts`
|
||||
- Confirmed the note still matches the current product surface:
|
||||
- workspace changes still scaffold coordination work at `tasks/coordination.md`
|
||||
- workspace changes still scaffold per-target draft work at `targets/<alias>/tasks.md`
|
||||
- `apply` still reuses the workspace change ID and writes `.openspec.materialization.yaml`
|
||||
- repo-local progress is still derived from `tasks.md` checkbox counts
|
||||
- generic `status --change` is still artifact-graph status, not a workspace-aware roll-up
|
||||
- Rebuilt the CLI:
|
||||
- `pnpm run build`
|
||||
- Result: passed
|
||||
- Re-ran the focused regression slice for the signals this phase depends on:
|
||||
- `pnpm vitest run test/core/workspace/apply.test.ts test/commands/artifact-workflow.test.ts test/core/artifact-graph/instruction-loader.test.ts`
|
||||
- Result: 3 files passed, 100/100 tests passed
|
||||
- Re-ran one fresh temp-fixture CLI probe using `test/fixtures/workspace-poc/happy-path`:
|
||||
- created `shared-refresh` in the copied workspace
|
||||
- confirmed workspace-root `status --change shared-refresh --json` still reported `proposal: done`, `design: done`, `specs: ready`, and `tasks: blocked`
|
||||
- materialized `shared-refresh` into the copied `app` repo with `apply --change shared-refresh --repo app --json`
|
||||
- confirmed repo-local `list --json` reported `shared-refresh` as `in-progress` at `0/2`, `in-progress` at `1/2`, and `complete` at `2/2`
|
||||
- confirmed `.openspec.materialization.yaml` still carried `source: workspace`, `workspaceName: happy-path`, and `targetAlias: app`
|
||||
- Re-validated the Phase 13 acceptance criteria against `DECISION.md`:
|
||||
- 13.5 one precise derivation rule is present for `planned`, `materialized`, `in-progress`, `blocked`, `complete`, `soft-done`, and `hard-done`
|
||||
- 13.6 the note explicitly separates workspace-only inspection from repo-local inspection
|
||||
- 13.7 the note resolves reverse links as required in v0, using the existing sidecar as the minimum backlink
|
||||
- Confirmed the Phase 13 checklist in `ROADMAP.md` already matched the verified state, so no checkbox changes were required in this pass.
|
||||
|
||||
## Issues found
|
||||
|
||||
- No product correctness issues were found in the reviewed boundary.
|
||||
- No acceptance-test gaps were found in `DECISION.md`.
|
||||
- No documentation-quality issues were found in the phase artifacts.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- Updated this verification note to reflect the exact fresh-context checks run in this pass.
|
||||
- No product, roadmap, or test changes were required.
|
||||
- No additional roadmap phases were needed.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No residual risks were found within the scope of this research phase.
|
||||
- Phase 14 still needs to implement the custom roll-up described here; that is a forward implementation dependency, not a Phase 13 verification gap.
|
||||
@@ -0,0 +1,63 @@
|
||||
# Phase 14 Manual Test
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `manual-test`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
Manual smoke re-run in a fresh local context for ROADMAP Phase 14 using copied workspace fixtures and the built CLI.
|
||||
|
||||
## Scenarios run
|
||||
|
||||
- Rebuilt the CLI with `pnpm run build`.
|
||||
- Copied `test/fixtures/workspace-poc/happy-path/workspace` and `test/fixtures/workspace-poc/happy-path/repos` into a fresh temp root and created repo-local `openspec/changes/` roots for `app`, `api`, and `docs`.
|
||||
- Ran the real CLI from the copied happy-path workspace with telemetry disabled:
|
||||
|
||||
```bash
|
||||
cd <tmp>/workspace
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js new change manual-status --targets app,api
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js status --change manual-status --json
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js apply --change manual-status --repo app --json
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js status --change manual-status --json
|
||||
# mark workspace coordination tasks complete
|
||||
# mark repos/app/openspec/changes/manual-status/tasks.md complete
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js apply --change manual-status --repo api --json
|
||||
# mark repos/api/openspec/changes/manual-status/tasks.md complete
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js status --change manual-status --json
|
||||
```
|
||||
|
||||
- Validated each raw `status --change <id> --json` output parsed cleanly and contained no ANSI escapes or spinner glyphs.
|
||||
- Copied `test/fixtures/workspace-poc/dirty/workspace` and `test/fixtures/workspace-poc/dirty/repos` into a second fresh temp root and created repo-local `openspec/changes/` roots for `app` and `api`.
|
||||
- Ran the real CLI from the copied dirty workspace:
|
||||
|
||||
```bash
|
||||
cd <dirty-tmp>/workspace
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js new change docs-repair --targets docs
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js status --change docs-repair --json
|
||||
```
|
||||
|
||||
- Validated the dirty-fixture raw `status --change docs-repair --json` output parsed cleanly and contained no ANSI escapes or spinner glyphs.
|
||||
|
||||
## Results
|
||||
|
||||
- `pnpm run build` passed.
|
||||
- In the happy-path smoke:
|
||||
- the first status output showed `change.state: "planned"` with both `api` and `app` as `planned` via `workspace`
|
||||
- after `apply --repo app`, status showed `change.state: "in-progress"` with `app: materialized via repo` and `api: planned via workspace`
|
||||
- after completing coordination plus both repo-local task files, status showed `change.state: "soft-done"` with both targets `complete via repo`
|
||||
- `hard-done` never appeared during the run
|
||||
- In the dirty-workspace smoke:
|
||||
- status showed `change.state: "blocked"`
|
||||
- the `docs` target reported `blocked via workspace`
|
||||
- the problem text was `repo alias 'docs' points to a missing repo path`
|
||||
- All status outputs were valid JSON with no spinner contamination.
|
||||
- No Phase 14 behavior drift was found between the implementation summary, verification notes, and this manual smoke re-run.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No product fixes were required from this manual smoke pass.
|
||||
- No manual-test-only fixes were needed beyond updating this artifact with the exact scenarios and observed assertions from the fresh run.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No additional Phase 14 residual risks were found in this manual smoke pass.
|
||||
- Explicit workspace archive and `hard-done` remain deferred to Phase 16 by design.
|
||||
@@ -0,0 +1,68 @@
|
||||
# Phase 14 Summary
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `implementation`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
## Changes made
|
||||
|
||||
- Added workspace-aware status roll-up in `src/core/workspace/status.ts`.
|
||||
- Extended `src/commands/workflow/status.ts` so `openspec status --change <id>` detects targeted workspace changes and uses the workspace roll-up instead of the repo-local artifact graph.
|
||||
- Implemented the Phase 14 state model:
|
||||
- overall workspace change: `planned`, `in-progress`, `blocked`, `soft-done`, `hard-done`
|
||||
- coordination: `planned`, `in-progress`, `blocked`, `complete`
|
||||
- targets: `planned`, `materialized`, `in-progress`, `blocked`, `complete`
|
||||
- Rolled coordination state from `tasks/coordination.md`.
|
||||
- Rolled target state from workspace draft tasks before materialization and from repo-local `tasks.md` after validating `.openspec.materialization.yaml`.
|
||||
- Kept JSON output small and stable:
|
||||
- `change.id`
|
||||
- `change.state`
|
||||
- `coordination.state`
|
||||
- `coordination.tasks`
|
||||
- `coordination.problems`
|
||||
- sorted `targets[]` with `alias`, `state`, `source`, `tasks`, and `problems`
|
||||
- Kept blocked output honest by reporting missing local overlay entries, stale repo paths, missing repo-local OpenSpec state, invalid materialization traces, and unreadable task files instead of inferring progress.
|
||||
- Added focused Phase 14 coverage in:
|
||||
- `test/core/workspace/status.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts`
|
||||
- Updated the Phase 14 checklist in `ROADMAP.md`.
|
||||
|
||||
## Tests or research performed
|
||||
|
||||
- Re-read the Phase 14 roadmap block in `ROADMAP.md`.
|
||||
- Re-read the Phase 13 decision in `notes/workspace-poc/phase-13-status-research/DECISION.md`.
|
||||
- Re-reviewed the current workspace implementation surface:
|
||||
- `src/core/workspace/change-create.ts`
|
||||
- `src/core/workspace/apply.ts`
|
||||
- `src/core/workspace/registry.ts`
|
||||
- `src/utils/task-progress.ts`
|
||||
- Built the CLI:
|
||||
- `pnpm run build`
|
||||
- Ran the repository test suite after the implementation landed:
|
||||
- `pnpm test -- test/core/workspace/status.test.ts test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts`
|
||||
- Result: Vitest ran the full suite; 87 files passed, 1453/1453 tests passed
|
||||
- Ran the focused Phase 14 verification slice in a fresh process:
|
||||
- `pnpm exec vitest run test/core/workspace/status.test.ts test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts`
|
||||
- Ran a fresh copied-fixture CLI smoke outside Vitest:
|
||||
- happy-path fixture: created `manual-status`, checked `planned`, materialized `app`, then completed coordination plus both repo-local task files to confirm `soft-done`
|
||||
- dirty fixture: created `docs-repair` and confirmed blocked status for the stale `docs` repo path
|
||||
|
||||
## Results
|
||||
|
||||
- `pnpm run build` passed.
|
||||
- The full Vitest suite passed: 87 files, 1453/1453 tests.
|
||||
- The focused Phase 14 verification slice passed: 2 files, 6/6 tests.
|
||||
- The workspace status contract now behaves as intended:
|
||||
- planning-only targets stay `planned` with `source: "workspace"`
|
||||
- valid repo-local materializations show `materialized` at `0/n` or `0/0`
|
||||
- partial repo-local progress shows `in-progress`
|
||||
- stale repo paths and invalid materialization traces show `blocked`
|
||||
- `soft-done` appears only after coordination and every target are task-complete
|
||||
- `hard-done` is not inferred and remained absent in the manual smoke
|
||||
- The JSON output stayed machine-readable with no spinner contamination or ANSI escape sequences.
|
||||
|
||||
## Blockers and next-step notes
|
||||
|
||||
- No blockers remain for Phase 14.
|
||||
- No new roadmap phases were required from this implementation pass.
|
||||
- Phase 15 can expand the status validation matrix, but the Phase 14 build contract is now implemented and passing.
|
||||
@@ -0,0 +1,49 @@
|
||||
# Phase 14 Verification
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `verification`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
Independent verification re-run in a fresh local context for ROADMAP Phase 14.
|
||||
|
||||
## Checks performed
|
||||
|
||||
- Re-read the Phase 14 roadmap block in `ROADMAP.md`.
|
||||
- Re-read the current implementation summary in `notes/workspace-poc/phase-14-workspace-status/SUMMARY.md`.
|
||||
- Re-read the Phase 13 status decision in `notes/workspace-poc/phase-13-status-research/DECISION.md`.
|
||||
- Re-inspected the Phase 14 implementation surface:
|
||||
- `src/core/workspace/status.ts`
|
||||
- `src/commands/workflow/status.ts`
|
||||
- `src/core/workspace/apply.ts`
|
||||
- `src/core/workspace/metadata.ts`
|
||||
- `src/utils/task-progress.ts`
|
||||
- Re-inspected the focused Phase 14 automated coverage:
|
||||
- `test/core/workspace/status.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts`
|
||||
- Rebuilt the CLI:
|
||||
- `pnpm run build`
|
||||
- Result: passed
|
||||
- Re-ran the focused Phase 14 regression slice in a fresh process:
|
||||
- `pnpm exec vitest run test/core/workspace/status.test.ts test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts`
|
||||
- Result: 2 files passed, 6/6 tests passed
|
||||
- Re-ran a direct CLI smoke on copied happy-path and dirty workspace fixtures outside Vitest:
|
||||
- created `manual-status`, confirmed initial `planned`
|
||||
- materialized `app`, confirmed mixed `in-progress` with `app: materialized` and `api: planned`
|
||||
- completed coordination plus both repo-local task files, confirmed `soft-done`
|
||||
- created `docs-repair` in the dirty fixture, confirmed overall `blocked` plus `repo alias 'docs' points to a missing repo path`
|
||||
- confirmed every `status --change <id> --json` response stayed parseable and wrote no spinner text or ANSI escapes
|
||||
- Re-reviewed `SUMMARY.md` and `MANUAL_TEST.md` for consistency with the implementation and the re-run checks.
|
||||
|
||||
## Issues found
|
||||
|
||||
- No Phase 14 product correctness issues were found.
|
||||
- No acceptance-test failures or documentation contradictions were found.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No product code changes were required during this verification pass.
|
||||
- Updated this verification record to reflect the fresh-context checks completed in this stage.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No additional Phase 14 residual risks were found beyond the intentional deferral of explicit workspace archive and `hard-done` behavior to Phase 16.
|
||||
@@ -0,0 +1,63 @@
|
||||
# Phase 15 Manual Test
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `manual-test`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
Fresh manual smoke run in a copied local fixture context for ROADMAP Phase 15 using the built CLI.
|
||||
|
||||
## Scenarios run
|
||||
|
||||
- Rebuilt the CLI with `pnpm run build`.
|
||||
- Copied `test/fixtures/workspace-poc/happy-path/workspace` and `test/fixtures/workspace-poc/happy-path/repos` into a fresh temp root, added an `ops` repo, and updated `.openspec/workspace.yaml` plus `.openspec/local.yaml` so `ops` participated as a fourth target.
|
||||
- Ran the real CLI from the copied happy-path workspace:
|
||||
|
||||
```bash
|
||||
cd <tmp>/happy-workspace
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js new change manual-phase15 --targets app,api,docs,ops
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js apply --change manual-phase15 --repo app
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js apply --change manual-phase15 --repo api
|
||||
cd <tmp>/happy-repos/app
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js archive manual-phase15 --yes --skip-specs --no-validate
|
||||
rm -rf <tmp>/happy-repos/docs
|
||||
cd <tmp>/happy-workspace
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js status --change manual-phase15 --json
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js status --change manual-phase15
|
||||
```
|
||||
|
||||
- Copied `test/fixtures/workspace-poc/dirty/workspace` and `test/fixtures/workspace-poc/dirty/repos` into a second fresh temp root, keeping the fixture’s stale `docs` path, and ran:
|
||||
|
||||
```bash
|
||||
cd <tmp>/dirty-workspace
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js new change manual-resume --targets app,api,docs
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js apply --change manual-resume --repo app
|
||||
# mark repos/app/openspec/changes/manual-resume/tasks.md as 1/2 complete
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js status --change manual-resume --json
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js status --change manual-resume
|
||||
```
|
||||
|
||||
- Validated each raw `status --change <id> --json` output parsed cleanly and contained no ANSI escapes, spinner glyphs, or `Loading change status...`.
|
||||
|
||||
## Results
|
||||
|
||||
- `pnpm run build` passed.
|
||||
- In the happy-path smoke:
|
||||
- text and JSON status both showed `api: materialized`, `app: archived`, `docs: blocked`, and `ops: planned`
|
||||
- the text output rendered the archived target as `- app: archived via repo (0/2 tasks)`, which matches the current command and e2e expectations
|
||||
- the text output remained readable and listed the stale `docs` problem inline
|
||||
- the JSON output remained machine-parseable
|
||||
- In the dirty-fixture smoke:
|
||||
- text and JSON status both showed `app: in-progress`, `api: planned`, and `docs: blocked`
|
||||
- overall change state remained `blocked`, which is the honest roll-up while the stale repo path is unresolved
|
||||
- the JSON output remained machine-parseable
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- This manual smoke reconfirmed the Phase 15 product fix: archived repo-local targets are surfaced as `archived` instead of being misreported as `planned`.
|
||||
- No product code changes were required during this manual-test pass.
|
||||
- Refreshed this note to record the currently observed archived text rendering and the fresh-context smoke coverage completed in this pass.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No additional Phase 15 residual risks were found in this manual smoke pass.
|
||||
- Explicit workspace archive/completion and `hard-done` remain deferred to Phase 16 by design.
|
||||
@@ -0,0 +1,57 @@
|
||||
# Phase 15 Summary
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `implementation`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
## Changes made
|
||||
|
||||
- Fixed `src/core/workspace/status.ts` so a repo-local change archived under `openspec/changes/archive/` is reported as `archived` instead of silently falling back to `planned`.
|
||||
- Exported the pure state-derivation helpers from `src/core/workspace/status.ts` and tightened the `soft-done` roll-up so archived targets only count once their archived task file is actually complete.
|
||||
- Added Phase 15 coverage in:
|
||||
- `test/core/workspace/status.test.ts`
|
||||
- `test/commands/workflow/status.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-status-cli.test.ts`
|
||||
- Kept `test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts` in the focused slice to preserve the existing planned-only workspace status contract.
|
||||
- Created the missing Phase 15 notes and updated the Phase 15 checklist in `ROADMAP.md`.
|
||||
|
||||
## Tests or research performed
|
||||
|
||||
- Re-read the Phase 15 roadmap block in `ROADMAP.md`.
|
||||
- Confirmed the Phase 15 notes were missing on disk before implementation.
|
||||
- Re-inspected the current workspace status implementation and existing coverage:
|
||||
- `src/core/workspace/status.ts`
|
||||
- `src/commands/workflow/status.ts`
|
||||
- `test/core/workspace/status.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts`
|
||||
- Built the CLI:
|
||||
- `pnpm run build`
|
||||
- Ran the focused Phase 15 automated slice:
|
||||
- `pnpm exec vitest run test/core/workspace/status.test.ts test/commands/workflow/status.test.ts test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts test/cli-e2e/workspace/workspace-status-cli.test.ts`
|
||||
- Re-ran the same focused slice in a fresh process after the first pass.
|
||||
- Ran `git diff --check`.
|
||||
- Ran a direct built-CLI smoke on copied fixtures outside Vitest:
|
||||
- happy-path workspace plus an added `ops` repo to validate `planned`, `materialized`, `archived`, and `blocked` targets in one workspace
|
||||
- dirty fixture to validate interruption/resume with `app: in-progress`, `api: planned`, and `docs: blocked`
|
||||
|
||||
## Results
|
||||
|
||||
- `pnpm run build` passed.
|
||||
- The focused Phase 15 slice passed twice in fresh Vitest processes: 4 files, 13/13 tests.
|
||||
- `git diff --check` passed.
|
||||
- The happy-path CLI smoke showed the intended mixed state matrix:
|
||||
- `api: materialized`
|
||||
- `app: archived`
|
||||
- `docs: blocked`
|
||||
- `ops: planned`
|
||||
- The dirty-fixture CLI smoke showed the intended interruption/resume state:
|
||||
- `app: in-progress`
|
||||
- `api: planned`
|
||||
- `docs: blocked`
|
||||
- All `status --change <id> --json` outputs stayed parseable and free of ANSI/spinner contamination.
|
||||
|
||||
## Blockers and next-step notes
|
||||
|
||||
- No blockers remain for Phase 15.
|
||||
- No new roadmap phases were required from this implementation pass.
|
||||
- Phase 16 can build explicit workspace completion and `hard-done` behavior on top of the now-tested `planned/materialized/in-progress/archived/blocked/complete` target surface.
|
||||
@@ -0,0 +1,66 @@
|
||||
# Phase 15 Verification
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `verification`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
Independent verification re-run in a fresh local context for ROADMAP Phase 15.
|
||||
|
||||
## Checks performed
|
||||
|
||||
- Re-read the Phase 15 roadmap block in `ROADMAP.md`.
|
||||
- Re-read the implementation summary in `notes/workspace-poc/phase-15-test-workspace-status/SUMMARY.md`.
|
||||
- Re-read the current manual smoke record in `notes/workspace-poc/phase-15-test-workspace-status/MANUAL_TEST.md`.
|
||||
- Re-inspected the implementation boundary for Phase 15:
|
||||
- `src/core/workspace/status.ts`
|
||||
- `src/commands/workflow/status.ts`
|
||||
- `test/core/workspace/status.test.ts`
|
||||
- `test/commands/workflow/status.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-status-cli.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts`
|
||||
- Confirmed the boundary stays within Phase 15 scope:
|
||||
- workspace status derivation and rendering live under the workspace status surface
|
||||
- no explicit workspace completion or archive state was introduced ahead of Phase 16
|
||||
- `hasExplicitWorkspaceCompletion()` remains a deliberate Phase 16 stub returning `false`
|
||||
- Rebuilt the CLI:
|
||||
- `pnpm run build`
|
||||
- Result: passed
|
||||
- Re-ran the focused Phase 15 regression slice in a fresh process:
|
||||
- `pnpm exec vitest run test/core/workspace/status.test.ts test/commands/workflow/status.test.ts test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts test/cli-e2e/workspace/workspace-status-cli.test.ts`
|
||||
- Result: 4 files passed, 13/13 tests passed
|
||||
- Ran `git diff --check`.
|
||||
- Result: passed
|
||||
- Reproduced the mixed-state scenario with the built CLI on copied fixtures outside Vitest:
|
||||
- added an `ops` repo to the happy-path workspace
|
||||
- created and materialized `manual-phase15`
|
||||
- archived the repo-local `app` change
|
||||
- removed the `docs` repo root to force a stale alias
|
||||
- verified status reported `api: materialized`, `app: archived`, `docs: blocked`, and `ops: planned`
|
||||
- Reproduced the interruption/resume scenario with the built CLI on copied dirty fixtures outside Vitest:
|
||||
- created and materialized `manual-resume` for `app`
|
||||
- marked the repo-local app tasks as 1/2 complete
|
||||
- verified status reported `app: in-progress`, `api: planned`, and `docs: blocked`
|
||||
- Performed a raw JSON cleanliness check outside Vitest for both scenarios:
|
||||
- captured `status --change <id> --json` output directly from the built CLI
|
||||
- parsed the raw output with `JSON.parse(...)`
|
||||
- checked that the raw output contained no ANSI escapes, spinner glyphs, or `Loading change status...`
|
||||
- Reviewed Phase 15 documentation quality:
|
||||
- `SUMMARY.md`, `VERIFY.md`, and `MANUAL_TEST.md` all match the observed behavior
|
||||
- the notes clearly distinguish automated coverage from direct CLI smoke coverage
|
||||
- the notes do not claim Phase 16 completion semantics are already implemented
|
||||
|
||||
## Issues found
|
||||
|
||||
- No Phase 15 product correctness issues were found.
|
||||
- No acceptance-test gap was found in the current Phase 15 test slice and direct CLI smoke.
|
||||
- No documentation mismatch was found between the phase artifacts and the current implementation.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No product code changes were required during this verification pass.
|
||||
- Refreshed this verification note to record the fresh-context checks completed in this pass, including implementation-boundary review and raw JSON cleanliness checks.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No additional Phase 15 residual risks were found.
|
||||
- Explicit workspace completion/archive semantics and `hard-done` remain intentionally deferred to Phase 16.
|
||||
@@ -0,0 +1,71 @@
|
||||
# Phase 16 Manual Test
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `manual-test`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
Fresh manual smoke run in copied local fixture contexts for ROADMAP Phase 16 using the built CLI.
|
||||
|
||||
## Scenarios run
|
||||
|
||||
- Rebuilt the CLI with `pnpm run build`.
|
||||
- Scenario 1: early top-level workspace archive rejection in a fresh copied fixture:
|
||||
|
||||
```bash
|
||||
cd <tmp-1>/workspace
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js new change manual-phase16-early --targets app,api
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js apply --change manual-phase16-early --repo app
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js archive manual-phase16-early --workspace
|
||||
```
|
||||
|
||||
- Scenario 2: repo-local archive first, then explicit workspace archive, in a second fresh copied fixture:
|
||||
|
||||
```bash
|
||||
cd <tmp-2>/workspace
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js new change manual-phase16 --targets app,api
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js apply --change manual-phase16 --repo app
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js apply --change manual-phase16 --repo api
|
||||
# mark workspace coordination plus both repo-local task files as 2/2 complete
|
||||
cd <tmp-2>/repos/app
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js archive manual-phase16 --yes --skip-specs --no-validate
|
||||
cd <tmp-2>/workspace
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js status --change manual-phase16 --json
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js status --change manual-phase16
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js archive manual-phase16 --workspace
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js status --change manual-phase16 --json
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js status --change manual-phase16
|
||||
```
|
||||
|
||||
- Parsed the raw JSON status output before and after the explicit workspace archive.
|
||||
- Inspected the copied workspace metadata and repo-local archive directories on disk after Scenario 2.
|
||||
|
||||
## Results
|
||||
|
||||
- `pnpm run build` passed.
|
||||
- Scenario 1 behaved as required for `16.6`:
|
||||
- `openspec archive manual-phase16-early --workspace` exited non-zero
|
||||
- the CLI reported `Workspace change 'manual-phase16-early' is 'in-progress'. Reach 'soft-done' before running 'openspec archive manual-phase16-early --workspace'.`
|
||||
- workspace hard-done was not implied or backfilled
|
||||
- Scenario 2 behaved as required for `16.5`, `16.7`, and `16.8`:
|
||||
- before the explicit workspace archive, JSON status parsed cleanly and overall state was `soft-done`
|
||||
- before the explicit workspace archive, targets rendered as `api: complete` and `app: archived`
|
||||
- before the explicit workspace archive, `workspace/changes/manual-phase16/.openspec.yaml` did not contain `workspaceArchivedAt`
|
||||
- after `openspec archive manual-phase16 --workspace`, JSON status parsed cleanly and overall state became `hard-done`
|
||||
- after the explicit workspace archive, target states stayed `api: complete` and `app: archived`
|
||||
- after the explicit workspace archive, `workspace/changes/manual-phase16/.openspec.yaml` contained `workspaceArchivedAt`
|
||||
- The filesystem boundaries stayed correct in Scenario 2:
|
||||
- the workspace change still existed under `workspace/changes/manual-phase16/`
|
||||
- the repo-local active `app` change no longer existed under `repos/app/openspec/changes/manual-phase16/`
|
||||
- the repo-local archived copy existed under `repos/app/openspec/changes/archive/2026-04-17-manual-phase16/`
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No product code changes were required during this manual-test pass.
|
||||
- Refreshed this note to capture both observed manual paths:
|
||||
- early `--workspace` archive rejection
|
||||
- repo-local archive first, explicit workspace archive second
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No additional Phase 16 residual risks were found in this manual smoke.
|
||||
- The broader command and CLI coverage expansion remains Phase 17 work.
|
||||
@@ -0,0 +1,66 @@
|
||||
# Phase 16 Summary
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `implementation`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
## Changes made
|
||||
|
||||
- Added the lean explicit workspace completion path on the existing archive surface: `openspec archive <id> --workspace`.
|
||||
- Implemented workspace archive handling in `src/core/workspace/archive.ts` and routed `src/core/archive.ts` to it only when `--workspace` is present, leaving repo-local archive behavior unchanged by default.
|
||||
- Recorded explicit workspace-level hard-done state in workspace change metadata via a new optional `workspaceArchivedAt` field on `.openspec.yaml`.
|
||||
- Updated `src/core/workspace/status.ts` so `hard-done` is derived only from that explicit workspace archive marker.
|
||||
- Kept repo-local archive semantics repo-local:
|
||||
- repo-local archive still moves only the repo-local change under `openspec/changes/archive/`
|
||||
- workspace archive does not move repo-local changes or touch canonical repo-local specs
|
||||
- Added focused Phase 16 coverage in `test/core/workspace/archive.test.ts`.
|
||||
- Extended `test/utils/change-metadata.test.ts` so the new workspace archive marker is parsed and persisted correctly.
|
||||
- Re-ran the existing repo-local archive and workspace status regression coverage to prove the new path did not collapse the repo/local boundary.
|
||||
- Created the missing Phase 16 notes and updated the Phase 16 checklist in `ROADMAP.md`.
|
||||
|
||||
## Tests or research performed
|
||||
|
||||
- Re-read the Phase 16 roadmap block in `ROADMAP.md`.
|
||||
- Confirmed the Phase 16 phase artifacts were missing on disk before implementation.
|
||||
- Re-read the Phase 13 decision and the Phase 15 status/archive notes to preserve the documented `soft-done` versus explicit `hard-done` boundary.
|
||||
- Re-inspected the touched implementation boundary:
|
||||
- `src/core/archive.ts`
|
||||
- `src/core/workspace/status.ts`
|
||||
- `src/utils/change-metadata.ts`
|
||||
- `src/core/artifact-graph/types.ts`
|
||||
- Built the CLI:
|
||||
- `pnpm run build`
|
||||
- Ran the focused Phase 16 automated slice:
|
||||
- `pnpm exec vitest run test/core/archive.test.ts test/core/workspace/status.test.ts test/core/workspace/archive.test.ts test/utils/change-metadata.test.ts`
|
||||
- Ran `git diff --check`.
|
||||
- Ran a direct built-CLI smoke on copied `happy-path` fixtures outside Vitest:
|
||||
- created `manual-phase16` for `app,api`
|
||||
- materialized both targets
|
||||
- completed coordination plus both repo-local task files
|
||||
- archived the repo-local `app` change
|
||||
- confirmed workspace status was still `soft-done`
|
||||
- ran `openspec archive manual-phase16 --workspace`
|
||||
- confirmed workspace status became `hard-done` and `.openspec.yaml` gained `workspaceArchivedAt`
|
||||
|
||||
## Results
|
||||
|
||||
- `pnpm run build` passed.
|
||||
- The focused Phase 16 automated slice passed: 4 files, 57/57 tests.
|
||||
- `git diff --check` passed.
|
||||
- Repo-local archive no longer risks implying workspace completion:
|
||||
- before the explicit workspace archive, status reported `soft-done`
|
||||
- after `archive --workspace`, status reported `hard-done`
|
||||
- The direct CLI smoke confirmed the intended separation of concerns:
|
||||
- `app` remained archived only in `repos/app/openspec/changes/archive/...`
|
||||
- the workspace change remained present at `workspace/changes/manual-phase16/`
|
||||
- the workspace metadata, not repo-local archive activity, became the source of truth for `hard-done`
|
||||
- Mixed repo cadences remained valid:
|
||||
- `api` stayed `complete`
|
||||
- `app` stayed `archived`
|
||||
- the overall workspace still transitioned cleanly from `soft-done` to `hard-done`
|
||||
|
||||
## Blockers and next-step notes
|
||||
|
||||
- No blockers remain for Phase 16.
|
||||
- No new roadmap phases were required from this implementation pass.
|
||||
- Phase 17 can now expand the command/CLI regression matrix around this shipped `--workspace` hard-done path.
|
||||
@@ -0,0 +1,65 @@
|
||||
# Phase 16 Verification
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `verification`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
Fresh verification pass for ROADMAP Phase 16 in a clean context after the implementation landed.
|
||||
|
||||
## Checks performed
|
||||
|
||||
- Re-read the Phase 16 roadmap block in `ROADMAP.md`.
|
||||
- Re-read the current Phase 16 implementation summary in `notes/workspace-poc/phase-16-workspace-archive/SUMMARY.md`.
|
||||
- Re-read `notes/workspace-poc/phase-16-workspace-archive/MANUAL_TEST.md` and checked that its documented user path still matches the implementation and current observed behavior.
|
||||
- Re-inspected the implementation boundary:
|
||||
- `src/core/archive.ts`
|
||||
- `src/core/workspace/archive.ts`
|
||||
- `src/core/workspace/status.ts`
|
||||
- `src/core/artifact-graph/types.ts`
|
||||
- `test/core/archive.test.ts`
|
||||
- `test/core/workspace/archive.test.ts`
|
||||
- `test/core/workspace/status.test.ts`
|
||||
- `test/utils/change-metadata.test.ts`
|
||||
- Confirmed the Phase 16 boundary stays lean:
|
||||
- the existing top-level `archive` surface is reused
|
||||
- repo-local archive behavior still runs unless `--workspace` is passed
|
||||
- workspace hard-done is represented only by workspace metadata
|
||||
- repo-local canonical spec/archive ownership is untouched
|
||||
- Rebuilt the CLI:
|
||||
- `pnpm run build`
|
||||
- Result: passed
|
||||
- Re-ran the focused verification slice:
|
||||
- `pnpm exec vitest run test/core/archive.test.ts test/core/workspace/status.test.ts test/core/workspace/archive.test.ts test/utils/change-metadata.test.ts`
|
||||
- Result: 4 files passed, 57/57 tests passed
|
||||
- Ran `git diff --check`.
|
||||
- Result: passed
|
||||
- Reproduced the full user-visible Phase 16 path with the built CLI on copied happy-path fixtures in a fresh temp root:
|
||||
- created and materialized `manual-phase16` for `app,api`
|
||||
- completed coordination and both repo-local task files
|
||||
- archived only the repo-local `app` change
|
||||
- confirmed `status --change manual-phase16 --json` still parsed and reported `soft-done`
|
||||
- ran `archive manual-phase16 --workspace`
|
||||
- confirmed `status --change manual-phase16 --json` then parsed and reported `hard-done`
|
||||
- confirmed the workspace change directory remained active while the repo-local archive stayed under `repos/app/openspec/changes/archive/`
|
||||
- Mapped the acceptance tests back to the implementation and checks above:
|
||||
- `16.5` verified by `test/core/workspace/archive.test.ts` and the fresh CLI smoke showing repo-local archive leaves the workspace change active
|
||||
- `16.6` verified by `test/core/workspace/archive.test.ts` rejecting early workspace archive and by the CLI smoke requiring explicit `--workspace`
|
||||
- `16.7` verified by `test/core/archive.test.ts`, `src/core/archive.ts`, and the CLI smoke showing repo-local archive still operates inside repo-local `openspec/changes/archive/`
|
||||
- `16.8` verified by `test/core/workspace/status.test.ts` and the CLI smoke showing `api: complete` plus `app: archived` still rolls up cleanly from `soft-done` to `hard-done`
|
||||
|
||||
## Issues found
|
||||
|
||||
- No Phase 16 product correctness issues were found.
|
||||
- No regression was found in repo-local archive behavior.
|
||||
- No acceptance-test gap was found in the focused automated slice plus the direct CLI smoke.
|
||||
- No documentation drift was found between `SUMMARY.md`, `MANUAL_TEST.md`, and the verified implementation behavior.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No additional product code changes were required during this verification pass.
|
||||
- Refreshed this verification note to capture the completed fresh checks, including the direct CLI confirmation of `soft-done` before explicit workspace archive and `hard-done` after it.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No additional Phase 16 residual risks were found.
|
||||
- Broader command and CLI matrix expansion remains Phase 17 work, but the shipped Phase 16 build contract is implemented and behaving as intended.
|
||||
@@ -0,0 +1,85 @@
|
||||
# Phase 17 Manual Test
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `manual-test`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
Fresh manual smoke run in copied local fixture contexts for ROADMAP Phase 17 using the built CLI.
|
||||
|
||||
## Scenarios run
|
||||
|
||||
- Rebuilt the CLI with `pnpm run build`.
|
||||
- Scenario 1: staggered repo archive should not force top-level done in a fresh copied fixture:
|
||||
|
||||
```bash
|
||||
cd <tmp>/workspace
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js new change manual-phase17-staggered --targets app,api
|
||||
# mark workspace coordination tasks 2/2 complete
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js apply --change manual-phase17-staggered --repo app
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js apply --change manual-phase17-staggered --repo api
|
||||
# mark repos/app/openspec/changes/manual-phase17-staggered/tasks.md as 2/2 complete
|
||||
# mark repos/api/openspec/changes/manual-phase17-staggered/tasks.md as 1/2 complete
|
||||
cd <tmp>/repos/app
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js archive manual-phase17-staggered --yes --skip-specs --no-validate
|
||||
cd <tmp>/workspace
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js status --change manual-phase17-staggered --json
|
||||
```
|
||||
|
||||
- Scenario 2: `soft-done` should appear before explicit workspace archive, and `hard-done` only after it, in a second fresh copied fixture:
|
||||
|
||||
```bash
|
||||
cd <tmp>/workspace
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js new change manual-phase17-harddone --targets app,api
|
||||
# mark workspace coordination tasks 2/2 complete
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js apply --change manual-phase17-harddone --repo app
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js apply --change manual-phase17-harddone --repo api
|
||||
# mark both repo-local task files as 2/2 complete
|
||||
cd <tmp>/repos/app
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js archive manual-phase17-harddone --yes --skip-specs --no-validate
|
||||
cd <tmp>/workspace
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js status --change manual-phase17-harddone --json
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js archive manual-phase17-harddone --workspace
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js status --change manual-phase17-harddone --json
|
||||
grep 'workspaceArchivedAt' <tmp>/workspace/changes/manual-phase17-harddone/.openspec.yaml
|
||||
ls -1 <tmp>/repos/app/openspec/changes/archive | grep 'manual-phase17-harddone'
|
||||
```
|
||||
|
||||
- Scenario 3: standalone repo-local archive should remain unchanged outside workspace flows:
|
||||
|
||||
```bash
|
||||
mkdir -p <tmp>/openspec/changes/archive <tmp>/openspec/specs <tmp>/openspec/changes/repo-local-regression
|
||||
# mark openspec/changes/repo-local-regression/tasks.md as 1/1 complete
|
||||
cd <tmp>
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js archive repo-local-regression --yes --skip-specs --no-validate
|
||||
ls -1 <tmp>/openspec/changes/archive | grep 'repo-local-regression'
|
||||
test ! -d <tmp>/openspec/changes/repo-local-regression
|
||||
```
|
||||
|
||||
## Results
|
||||
|
||||
- `pnpm run build` passed.
|
||||
- Scenario 1 matched `17.4`:
|
||||
- `status --change manual-phase17-staggered --json` parsed cleanly
|
||||
- overall workspace state was `in-progress`
|
||||
- targets rendered as `api: in-progress` and `app: archived`
|
||||
- repo-local archive did not force workspace `soft-done` or `hard-done`
|
||||
- Scenario 2 matched `17.5`:
|
||||
- before the explicit workspace archive, `status --change manual-phase17-harddone --json` parsed cleanly and overall state was `soft-done`
|
||||
- `openspec archive manual-phase17-harddone --workspace` printed `Workspace change 'manual-phase17-harddone' marked hard-done ...`
|
||||
- after the explicit workspace archive, `status --change manual-phase17-harddone --json` parsed cleanly and overall state became `hard-done`
|
||||
- `workspace/changes/manual-phase17-harddone/.openspec.yaml` contained `workspaceArchivedAt`
|
||||
- the repo-local archived copy remained under `repos/app/openspec/changes/archive/`
|
||||
- Scenario 3 matched `17.6`:
|
||||
- standalone `openspec archive repo-local-regression --yes --skip-specs --no-validate` succeeded outside any workspace root
|
||||
- the archived copy was created under `openspec/changes/archive/2026-04-17-repo-local-regression`
|
||||
- the active repo-local change directory was removed after archive
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No product code changes were required during this manual-test pass.
|
||||
- Refreshed this note to record the full fresh-context manual smoke for all three Phase 17 acceptance boundaries, including the standalone repo-local regression case that was missing from the earlier note.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No additional Phase 17 residual risks were found in this manual smoke pass.
|
||||
- The phase remains limited to workspace completion/archive semantics; no later roadmap work was started from this pass.
|
||||
@@ -0,0 +1,63 @@
|
||||
# Phase 17 Summary
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `implementation`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
## Changes made
|
||||
|
||||
- Added command-level workspace archive coverage in `test/commands/archive.workspace.test.ts`.
|
||||
- Added CLI e2e workspace archive coverage in `test/cli-e2e/workspace/workspace-archive-cli.test.ts`.
|
||||
- Covered the missing Phase 17 scenarios directly:
|
||||
- one repo archived while another repo remains in-progress
|
||||
- `soft-done` before explicit workspace archive
|
||||
- `hard-done` only after explicit workspace archive
|
||||
- repo-local archive behavior still working outside workspace flows
|
||||
- Created the missing Phase 17 notes and updated the Phase 17 checklist in `ROADMAP.md`.
|
||||
|
||||
## Tests or research performed
|
||||
|
||||
- Re-read the Phase 17 roadmap block in `ROADMAP.md`.
|
||||
- Re-read the shipped Phase 16 archive/status notes to preserve the intended repo-local versus workspace ownership boundary:
|
||||
- `notes/workspace-poc/phase-16-workspace-archive/SUMMARY.md`
|
||||
- `notes/workspace-poc/phase-16-workspace-archive/VERIFY.md`
|
||||
- Re-inspected the current archive/status implementation and existing coverage:
|
||||
- `src/core/archive.ts`
|
||||
- `src/core/workspace/archive.ts`
|
||||
- `src/core/workspace/status.ts`
|
||||
- `test/core/archive.test.ts`
|
||||
- `test/core/workspace/archive.test.ts`
|
||||
- `test/core/workspace/status.test.ts`
|
||||
- `test/commands/workflow/status.test.ts`
|
||||
- Built the CLI:
|
||||
- `pnpm run build`
|
||||
- Ran the focused Phase 17 automated slice:
|
||||
- `pnpm exec vitest run test/core/archive.test.ts test/core/workspace/archive.test.ts test/core/workspace/status.test.ts test/commands/workflow/status.test.ts test/commands/archive.workspace.test.ts test/cli-e2e/workspace/workspace-status-cli.test.ts test/cli-e2e/workspace/workspace-archive-cli.test.ts`
|
||||
- Ran `git diff --check`.
|
||||
- Ran a direct built-CLI smoke on copied happy-path fixtures outside Vitest for:
|
||||
- staggered repo archive with top-level status still `in-progress`
|
||||
- `soft-done` before `archive --workspace`
|
||||
- `hard-done` after `archive --workspace`
|
||||
|
||||
## Results
|
||||
|
||||
- `pnpm run build` passed.
|
||||
- The focused Phase 17 automated slice passed: 7 files, 42/42 tests.
|
||||
- `git diff --check` passed.
|
||||
- The new command and CLI coverage proved the expected boundaries:
|
||||
- repo-local archive can happen while another target is still active without forcing top-level done
|
||||
- overall status stays `soft-done` until the explicit workspace archive happens
|
||||
- explicit workspace archive flips only the workspace change to `hard-done`
|
||||
- repo-local archive behavior outside workspace flows still works unchanged
|
||||
- The direct CLI smoke confirmed the intended user-visible sequence on copied fixtures:
|
||||
- staggered case: `app` archived, `api` in-progress, overall workspace `in-progress`
|
||||
- completion case before workspace archive: overall workspace `soft-done`
|
||||
- completion case after workspace archive: overall workspace `hard-done`
|
||||
- the workspace change metadata gained `workspaceArchivedAt`
|
||||
- the repo-local archived copy remained under `repos/app/openspec/changes/archive/`
|
||||
|
||||
## Blockers and next-step notes
|
||||
|
||||
- No blockers remain for Phase 17.
|
||||
- No new roadmap phases were required from this implementation pass.
|
||||
- Phase 18 can stay focused on the deferred research list rather than archive/status regression work.
|
||||
@@ -0,0 +1,61 @@
|
||||
# Phase 17 Verification
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `verification`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
Fresh verification pass for ROADMAP Phase 17 after the new coverage landed.
|
||||
|
||||
## Checks performed
|
||||
|
||||
- Re-read the Phase 17 roadmap block in `ROADMAP.md`.
|
||||
- Re-read the current Phase 17 implementation summary in `notes/workspace-poc/phase-17-test-workspace-archive/SUMMARY.md`.
|
||||
- Re-read the current manual smoke note in `notes/workspace-poc/phase-17-test-workspace-archive/MANUAL_TEST.md`.
|
||||
- Reviewed the Phase 17 notes for documentation quality:
|
||||
- `SUMMARY.md` matches the implementation boundary and focused automated slice.
|
||||
- `MANUAL_TEST.md` matches the documented user-facing archive/status sequence.
|
||||
- Re-inspected the implementation and regression boundary:
|
||||
- `src/core/archive.ts`
|
||||
- `src/core/workspace/archive.ts`
|
||||
- `src/core/workspace/status.ts`
|
||||
- `test/core/archive.test.ts`
|
||||
- `test/core/workspace/archive.test.ts`
|
||||
- `test/core/workspace/status.test.ts`
|
||||
- `test/commands/workflow/status.test.ts`
|
||||
- `test/commands/archive.workspace.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-status-cli.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-archive-cli.test.ts`
|
||||
- Rebuilt the CLI:
|
||||
- `pnpm run build`
|
||||
- Result: passed
|
||||
- Re-ran the focused verification slice:
|
||||
- `pnpm exec vitest run test/core/archive.test.ts test/core/workspace/archive.test.ts test/core/workspace/status.test.ts test/commands/workflow/status.test.ts test/commands/archive.workspace.test.ts test/cli-e2e/workspace/workspace-status-cli.test.ts test/cli-e2e/workspace/workspace-archive-cli.test.ts`
|
||||
- Result: 7 files passed, 42/42 tests passed
|
||||
- Ran `git diff --check`.
|
||||
- Result: passed
|
||||
- Replayed the direct built-CLI smoke on copied `happy-path` fixtures outside Vitest:
|
||||
- staggered archive case result: overall workspace `in-progress`, `api` still `in-progress`, `app` `archived`
|
||||
- completion case before workspace archive: overall workspace `soft-done`
|
||||
- completion case after `archive --workspace`: overall workspace `hard-done`
|
||||
- metadata/archive boundary result: workspace `.openspec.yaml` gained `workspaceArchivedAt` and the repo-local archived copy remained under `repos/app/openspec/changes/archive/`
|
||||
- Mapped the acceptance tests back to the implementation and checks:
|
||||
- `17.4` verified by `test/commands/archive.workspace.test.ts`, `test/cli-e2e/workspace/workspace-archive-cli.test.ts`, and the direct CLI staggered smoke showing one repo can archive while another remains in-progress without forcing top-level done
|
||||
- `17.5` verified by `test/commands/archive.workspace.test.ts`, `test/cli-e2e/workspace/workspace-archive-cli.test.ts`, `test/core/workspace/status.test.ts`, and the direct CLI smoke showing `soft-done` before explicit workspace archive and `hard-done` after it
|
||||
- `17.6` verified by `test/core/archive.test.ts` plus the standalone repo-local CLI regression in `test/cli-e2e/workspace/workspace-archive-cli.test.ts`
|
||||
|
||||
## Issues found
|
||||
|
||||
- No Phase 17 product correctness issues were found.
|
||||
- No workspace archive/status regression was found in the focused automated slice.
|
||||
- No repo-local archive regression was found outside workspace flows.
|
||||
- No Phase 17 documentation drift was found between the implementation, `SUMMARY.md`, and `MANUAL_TEST.md`.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No additional product code changes were required after the new test coverage landed.
|
||||
- Refreshed this verification note to capture the completed build, focused test slice, direct CLI smoke, and documentation-quality review.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No additional Phase 17 residual risks were found.
|
||||
- The remaining roadmap work moves into deferred research and broader end-to-end signoff rather than archive/status correctness gaps.
|
||||
@@ -0,0 +1,221 @@
|
||||
# Phase 18 Decision
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `implementation`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
## Shipped POC contract to preserve
|
||||
|
||||
This phase is explicitly non-blocking. The working POC contract stays as shipped:
|
||||
|
||||
- committed workspace repo identity is alias-keyed in `.openspec/workspace.yaml`
|
||||
- machine-local repo attachment is alias-keyed in `.openspec/local.yaml` through `repoPaths`
|
||||
- workspace changes target aliases through `targets: [<alias>]`
|
||||
- per-target draft artifacts live at `changes/<id>/targets/<alias>/...`
|
||||
- `openspec apply --change <id> --repo <alias>` materializes one repo-local bundle and reuses the same change ID
|
||||
- repo linkage is recorded only through `.openspec.materialization.yaml`
|
||||
- canonical specs still live in owner repos, not in the workspace
|
||||
|
||||
Nothing in this phase changes `new change`, `apply`, `status`, `archive`, fixture layout, or the existing workspace metadata shape.
|
||||
|
||||
## Concrete decision
|
||||
|
||||
The recommended post-POC direction is:
|
||||
|
||||
- shared-contract promotion should be a separate explicit workflow into a canonical owner repo, not an implicit side effect of `apply`, `status`, or `archive`
|
||||
- stable project IDs should be added on top of the current alias-based contract first, not used as a flag-day replacement
|
||||
- team-shared workspace semantics should remain out of scope until stable project identity and a real shared storage/conflict model exist
|
||||
|
||||
That keeps the POC honest:
|
||||
|
||||
- v0 proves centralized planning plus local execution
|
||||
- future ownership and identity work can be layered on without rewriting the working demo contract
|
||||
- current tests and fixtures remain a stable baseline instead of moving during signoff
|
||||
|
||||
## Recommended next-step design
|
||||
|
||||
### 1. Shared-contract promotion
|
||||
|
||||
Future shared contracts should move into a canonical owner repo through an explicit command, for example:
|
||||
|
||||
`openspec workspace promote-contract --change <id> --owner <alias> --spec <namespace/path>`
|
||||
|
||||
Recommended behavior:
|
||||
|
||||
1. Resolve the owner repo through the existing workspace registry.
|
||||
2. Read the workspace change plus the shared-contract draft or summary being promoted.
|
||||
3. Write or update the canonical owner-repo spec under `openspec/specs/<namespace/path>/spec.md`.
|
||||
4. Record a promotion receipt back in the workspace change, but only as an opt-in artifact created by the promotion command.
|
||||
|
||||
Recommended receipt shape:
|
||||
|
||||
- location: `changes/<id>/promotions/<contract-id>.yaml`
|
||||
- fields:
|
||||
- `ownerAlias`
|
||||
- `ownerProjectId` when available later
|
||||
- `specPath`
|
||||
- `promotedAt`
|
||||
- `sourceChangeId`
|
||||
|
||||
Why this shape:
|
||||
|
||||
- it keeps canonical truth in the owner repo
|
||||
- it avoids turning the workspace into a second permanent spec store
|
||||
- it does not change the current `apply` authority handoff contract
|
||||
- it keeps any new file shape opt-in instead of changing default workspace scaffolding
|
||||
|
||||
### 2. Stable project IDs
|
||||
|
||||
Stable project identity should arrive additively in two layers.
|
||||
|
||||
First layer: committed metadata
|
||||
|
||||
- extend each repo entry in `.openspec/workspace.yaml` with an optional `projectId`
|
||||
- keep the alias key as the local ergonomic handle for CLI commands and existing tests
|
||||
|
||||
Example:
|
||||
|
||||
```yaml
|
||||
version: 1
|
||||
name: happy-path
|
||||
repos:
|
||||
app:
|
||||
projectId: github.com/acme/app
|
||||
description: Application repo
|
||||
```
|
||||
|
||||
Second layer: machine-local bindings
|
||||
|
||||
- keep `.openspec/local.yaml` for machine-local path resolution
|
||||
- add an optional `projectBindings` map keyed by stable `projectId`
|
||||
- continue reading the existing `repoPaths` alias map during the migration window
|
||||
|
||||
Example additive shape:
|
||||
|
||||
```yaml
|
||||
version: 2
|
||||
repoPaths:
|
||||
app: ../repos/app
|
||||
projectBindings:
|
||||
github.com/acme/app:
|
||||
path: ../repos/app
|
||||
```
|
||||
|
||||
Resolver order in the first migration step should be:
|
||||
|
||||
1. target alias from the current CLI or workspace change
|
||||
2. alias lookup in `.openspec/workspace.yaml`
|
||||
3. `projectId` on that repo entry when present
|
||||
4. `projectBindings[projectId].path` when present
|
||||
5. legacy `repoPaths[alias]` fallback
|
||||
|
||||
Important boundary:
|
||||
|
||||
- do not change `targets: [<alias>]`
|
||||
- do not change `changes/<id>/targets/<alias>/...`
|
||||
- do not change `--repo <alias>`
|
||||
|
||||
Those can stay alias-based until the identity layer is proven. A later phase can decide whether user-facing targets ever need to become ID-based at all.
|
||||
|
||||
### 3. Team-shared workspace semantics
|
||||
|
||||
No multi-writer committed workspace semantics should be added immediately after the POC.
|
||||
|
||||
Recommended rule:
|
||||
|
||||
- keep the workspace as a planner-local coordination home
|
||||
- keep shareable truth in committed workspace metadata, owner-repo specs, and optional promotion receipts
|
||||
- do not treat `.openspec/local.yaml` or a git-cloned workspace root as a team-shared execution surface
|
||||
|
||||
If collaboration is revisited later, it should be based on:
|
||||
|
||||
- stable `projectId`
|
||||
- owner-repo links and promotion receipts
|
||||
- possibly a remote summary or review surface
|
||||
|
||||
It should not be based on:
|
||||
|
||||
- committed absolute paths
|
||||
- shared mutable local overlays
|
||||
- the workspace becoming the canonical home for cross-repo specs
|
||||
|
||||
## Backward-compatible migration seam
|
||||
|
||||
The safest migration seam is dual-read, additive metadata:
|
||||
|
||||
- keep alias keys and `targets/<alias>/` as they are
|
||||
- add optional `repos.<alias>.projectId`
|
||||
- add optional `local.yaml.projectBindings.<projectId>.path`
|
||||
- keep reading legacy `repoPaths.<alias>` until every caller and fixture has migrated
|
||||
- add optional `projectId` to `.openspec.materialization.yaml` later without removing `workspaceName` or `targetAlias`
|
||||
|
||||
This seam preserves backward compatibility because existing workspaces, tests, and fixtures continue to function unchanged while new workspaces can start carrying stable IDs.
|
||||
|
||||
## What future changes would break the current tests or fixture shape
|
||||
|
||||
The following changes would break current tests or fixture layout if done as a direct replacement instead of an additive migration:
|
||||
|
||||
- Replacing alias-keyed `repos` or `repoPaths` with ID-keyed maps.
|
||||
- Breaks `test/fixtures/workspace-poc/*/workspace/.openspec/*.yaml`.
|
||||
- Breaks `test/core/workspace/registry.test.ts`.
|
||||
- Breaks `test/helpers/workspace-sandbox.ts`.
|
||||
|
||||
- Replacing `targets: ['app', 'api']` or `targets/<alias>/...` with object or ID-based target records.
|
||||
- Breaks `test/core/workspace/change-create.test.ts`.
|
||||
- Breaks `test/helpers/workspace-assertions.ts`.
|
||||
- Breaks `test/core/workspace/apply.test.ts` and `test/core/workspace/status.test.ts`.
|
||||
|
||||
- Making `apply` auto-promote shared contracts into an owner repo.
|
||||
- Breaks the v0 create-only contract in `notes/workspace-poc/phase-10-materialization-contract-research/DECISION.md`.
|
||||
- Breaks tests that assert only the selected target repo is modified:
|
||||
- `test/core/workspace/apply.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-apply-cli.test.ts`
|
||||
|
||||
- Replacing `.openspec.materialization.yaml` fields with IDs only.
|
||||
- Breaks status/apply assertions that currently validate `workspaceName` and `targetAlias`:
|
||||
- `test/core/workspace/apply.test.ts`
|
||||
- `test/core/workspace/status.test.ts`
|
||||
|
||||
- Adding new default directories to every workspace change, such as `promotions/` or `shared-contracts/`.
|
||||
- Breaks the locked workspace-change layout assertion in `test/helpers/workspace-assertions.ts`.
|
||||
- Breaks `test/core/workspace/change-create.test.ts` if scaffolding changes by default.
|
||||
|
||||
## Rejected alternatives
|
||||
|
||||
### Rejected: promote shared contracts during `apply`
|
||||
|
||||
Why rejected:
|
||||
|
||||
- `apply` is currently a narrow per-target materialization step
|
||||
- promotion has different ownership and overwrite concerns than repo-local execution
|
||||
- coupling them would blur the current authority handoff contract and expand Phase 10 behavior retroactively
|
||||
|
||||
### Rejected: replace aliases with stable IDs in one cut
|
||||
|
||||
Why rejected:
|
||||
|
||||
- it would force fixture and test churn across the whole workspace POC at signoff time
|
||||
- it would mix identity migration with unrelated execution behavior
|
||||
- the current alias contract is already working and should be the compatibility baseline
|
||||
|
||||
### Rejected: commit a shared team workspace as the next step
|
||||
|
||||
Why rejected:
|
||||
|
||||
- local repo path bindings are still machine-specific
|
||||
- multi-writer semantics need a conflict model the POC does not have
|
||||
- canonical truth already belongs in owner repos, not in a shared mutable workspace clone
|
||||
|
||||
### Rejected: let the workspace become the canonical shared-contract store
|
||||
|
||||
Why rejected:
|
||||
|
||||
- it violates the POC principle that canonical specs live in owner repos
|
||||
- it would create dual authority between workspace drafts and repo-owned specs
|
||||
- it would make archive and review semantics less clear, not more
|
||||
|
||||
## Blockers and next-step notes
|
||||
|
||||
- No blockers remain for Phase 18.
|
||||
- No new roadmap phase is required for the working POC because this decision is intentionally deferred and non-blocking.
|
||||
- If this work is pursued after signoff, the first implementation step should be additive `projectId` support plus an explicit promotion command, not a redesign of the shipped workspace contract.
|
||||
@@ -0,0 +1,76 @@
|
||||
# Phase 18 Manual Test
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `manual-test`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
Manual smoke run in a fresh local context for ROADMAP Phase 18 only.
|
||||
|
||||
## Scenarios run
|
||||
|
||||
- Built the current CLI with `pnpm run build`.
|
||||
- Created a fresh temp root and copied:
|
||||
- `test/fixtures/workspace-poc/happy-path/workspace` to `<tmp>/workspace`
|
||||
- `test/fixtures/workspace-poc/happy-path/repos` to `<tmp>/repos`
|
||||
- Inspected the copied workspace metadata to confirm the current shipped identity model:
|
||||
|
||||
```bash
|
||||
cd <tmp>/workspace
|
||||
sed -n '1,120p' .openspec/workspace.yaml
|
||||
sed -n '1,120p' .openspec/local.yaml
|
||||
```
|
||||
|
||||
- Ran the real CLI from the copied workspace with telemetry disabled:
|
||||
|
||||
```bash
|
||||
cd <tmp>/workspace
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js new change shared-refresh --targets app,api
|
||||
OPEN_SPEC_TELEMETRY_DISABLED=1 node /Users/tabishbidiwale/fission/repos/openspec/dist/cli/index.js apply --change shared-refresh --repo app --json
|
||||
test -d <tmp>/repos/app/openspec/changes/shared-refresh
|
||||
test ! -d <tmp>/repos/api/openspec/changes/shared-refresh
|
||||
sed -n '1,120p' <tmp>/repos/app/openspec/changes/shared-refresh/.openspec.materialization.yaml
|
||||
```
|
||||
|
||||
- Inspected the generated workspace target layout to confirm alias-named target directories were still the active scaffold:
|
||||
|
||||
```bash
|
||||
find <tmp>/workspace/changes/shared-refresh/targets -maxdepth 2 -type f | sort
|
||||
```
|
||||
|
||||
## Results
|
||||
|
||||
- `pnpm run build` passed.
|
||||
- The copied `workspace.yaml` still used alias-keyed committed repo entries:
|
||||
- `repos.app`
|
||||
- `repos.api`
|
||||
- `repos.docs`
|
||||
- The copied `local.yaml` still used alias-keyed local path bindings under `repoPaths`.
|
||||
- `new change shared-refresh --targets app,api` succeeded and created the workspace change using alias targets.
|
||||
- `apply --change shared-refresh --repo app --json` succeeded and returned the current user-visible contract surface:
|
||||
- top-level fields: `workspaceRoot`, `workspaceName`, `change`, `target`, `materializedAt`, `authority`
|
||||
- `change.id: shared-refresh`
|
||||
- `target.alias: app`
|
||||
- `target.changePath: <tmp>/repos/app/openspec/changes/shared-refresh`
|
||||
- Only `repos/app` gained the materialized repo-local change; `repos/api` remained untouched.
|
||||
- The generated workspace draft still used alias-named target directories:
|
||||
- `changes/shared-refresh/targets/app/tasks.md`
|
||||
- `changes/shared-refresh/targets/api/tasks.md`
|
||||
- The materialization sidecar still contained the live v0 fields:
|
||||
- `source: workspace`
|
||||
- `workspaceName: happy-path`
|
||||
- `targetAlias: app`
|
||||
- `materializedAt: <iso-timestamp>`
|
||||
- The manual smoke therefore matched the Phase 18 decision exactly:
|
||||
- alias-based workspace identity is still the shipped contract
|
||||
- the same change ID is still reused at materialization time
|
||||
- the repo-local trace is still the compatibility surface a future stable-ID migration must preserve additively
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No product or test code fixes were required from this manual pass.
|
||||
- Refreshed this note to capture the exact current `apply --json` response shape and alias-target layout from the fresh smoke run.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- None found within the scope of Phase 18.
|
||||
- Future stable-ID and promotion work should preserve the exercised alias-and-trace contract until a dedicated migration step exists.
|
||||
@@ -0,0 +1,71 @@
|
||||
# Phase 18 Summary
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `implementation`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
## Changes made
|
||||
|
||||
- Added the Phase 18 deferred-research decision in `notes/workspace-poc/phase-18-deferred-research/DECISION.md`.
|
||||
- Added the missing Phase 18 artifacts:
|
||||
- `notes/workspace-poc/phase-18-deferred-research/VERIFY.md`
|
||||
- `notes/workspace-poc/phase-18-deferred-research/MANUAL_TEST.md`
|
||||
- Chose one concrete post-POC direction while keeping the shipped workspace POC contract fixed:
|
||||
- shared-contract promotion becomes an explicit future owner-repo command
|
||||
- stable project IDs arrive additively on top of the alias-based v0 contract
|
||||
- team-shared multi-writer workspace semantics stay out of scope after the POC
|
||||
- Captured the exact backward-compatible migration seam:
|
||||
- optional `repos.<alias>.projectId`
|
||||
- optional `local.yaml.projectBindings.<projectId>.path`
|
||||
- legacy `targets`, `targets/<alias>/...`, `repoPaths.<alias>`, and `.openspec.materialization.yaml` remain valid during migration
|
||||
- Updated the Phase 18 checklist in `ROADMAP.md`.
|
||||
|
||||
## Tests or research performed
|
||||
|
||||
- Re-read the Phase 18 roadmap block in `ROADMAP.md`.
|
||||
- Confirmed the phase directory was missing and created the Phase 18 artifacts from scratch.
|
||||
- Re-read the current workspace POC anchors:
|
||||
- `WORKSPACE_POC_PRD.md`
|
||||
- `WORKSPACE_POC_DECISION_RECORD.md`
|
||||
- `notes/workspace-poc/phase-07-open-contract-research/DECISION.md`
|
||||
- `notes/workspace-poc/phase-10-materialization-contract-research/DECISION.md`
|
||||
- `notes/workspace-poc/phase-13-status-research/DECISION.md`
|
||||
- Re-inspected the implementation and fixture surfaces that define the shipped contract:
|
||||
- `src/core/workspace/metadata.ts`
|
||||
- `src/core/workspace/registry.ts`
|
||||
- `src/core/workspace/change-create.ts`
|
||||
- `src/core/workspace/apply.ts`
|
||||
- `src/core/workspace/status.ts`
|
||||
- `test/helpers/workspace-assertions.ts`
|
||||
- `test/helpers/workspace-sandbox.ts`
|
||||
- `test/fixtures/workspace-poc/happy-path/workspace/.openspec/workspace.yaml`
|
||||
- `test/fixtures/workspace-poc/happy-path/workspace/.openspec/local.yaml`
|
||||
- Ran focused automated validation for the current alias, overlay, target-layout, and materialization contract:
|
||||
- `pnpm run build`
|
||||
- `pnpm exec vitest run test/core/workspace/registry.test.ts test/core/workspace/change-create.test.ts test/core/workspace/open.test.ts test/core/workspace/apply.test.ts test/core/workspace/status.test.ts test/commands/workspace/registry.test.ts test/commands/workspace/open.test.ts test/cli-e2e/workspace/workspace-open-cli.test.ts test/cli-e2e/workspace/workspace-apply-cli.test.ts`
|
||||
- `git diff --check`
|
||||
- Ran a fresh copied-fixture manual smoke with the built CLI against `test/fixtures/workspace-poc/happy-path`:
|
||||
- inspected `.openspec/workspace.yaml` and `.openspec/local.yaml`
|
||||
- created `shared-refresh` with `new change shared-refresh --targets app,api`
|
||||
- materialized `app` with `apply --change shared-refresh --repo app --json`
|
||||
- confirmed only `repos/app` received `openspec/changes/shared-refresh`
|
||||
- inspected `.openspec.materialization.yaml`
|
||||
|
||||
## Results
|
||||
|
||||
- `pnpm run build` passed.
|
||||
- The focused workspace slice passed: 9 files, 39/39 tests.
|
||||
- `git diff --check` passed.
|
||||
- The manual smoke confirmed the currently shipped contract the Phase 18 note depends on:
|
||||
- committed workspace metadata is still alias-keyed in `.openspec/workspace.yaml`
|
||||
- machine-local repo bindings are still alias-keyed in `.openspec/local.yaml`
|
||||
- `new change` still records alias targets and creates alias-named target directories
|
||||
- `apply` still reuses the same change ID and writes `.openspec.materialization.yaml` with `workspaceName` and `targetAlias`
|
||||
- only the selected target repo is modified by `apply`
|
||||
- `DECISION.md` now cleanly separates deferred post-POC work from the shipped contract, names concrete breakpoints in current tests and fixtures, and identifies an additive migration seam that preserves backward compatibility.
|
||||
|
||||
## Blockers and next-step notes
|
||||
|
||||
- No blockers remain for Phase 18.
|
||||
- No new roadmap phase is required for the working POC because this research is explicitly deferred and non-blocking.
|
||||
- If the post-POC work is pursued later, start with additive `projectId` support and an explicit promotion command rather than changing the current alias-based workspace contract in place.
|
||||
@@ -0,0 +1,55 @@
|
||||
# Phase 18 Verification
|
||||
|
||||
Independent verification re-run in a fresh local context on 2026-04-17 (Australia/Sydney) for ROADMAP Phase 18, cycle 1.
|
||||
|
||||
## Checks performed
|
||||
|
||||
- Re-read the Phase 18 roadmap block in `ROADMAP.md`.
|
||||
- Re-read the phase artifacts under `notes/workspace-poc/phase-18-deferred-research/`, with focus on `SUMMARY.md` and `DECISION.md`.
|
||||
- Re-checked the live workspace contract the deferred note depends on:
|
||||
- `src/core/workspace/metadata.ts`
|
||||
- `src/core/workspace/registry.ts`
|
||||
- `src/core/workspace/change-create.ts`
|
||||
- `src/core/workspace/apply.ts`
|
||||
- `src/core/workspace/status.ts`
|
||||
- `test/helpers/workspace-assertions.ts`
|
||||
- `test/helpers/workspace-sandbox.ts`
|
||||
- Confirmed the note still matches the current product surface:
|
||||
- `.openspec/workspace.yaml` is still an alias-keyed committed repo registry
|
||||
- `.openspec/local.yaml` is still an alias-keyed local path overlay
|
||||
- workspace changes still store `targets` as alias strings and draft artifacts under `targets/<alias>/...`
|
||||
- `apply` still reuses the workspace change ID and writes `.openspec.materialization.yaml`
|
||||
- the materialization trace still carries `workspaceName` and `targetAlias`
|
||||
- Rebuilt the CLI:
|
||||
- `pnpm run build`
|
||||
- Result: passed
|
||||
- Re-ran the focused regression slice for the contract this phase documents:
|
||||
- `pnpm exec vitest run test/core/workspace/registry.test.ts test/core/workspace/change-create.test.ts test/core/workspace/open.test.ts test/core/workspace/apply.test.ts test/core/workspace/status.test.ts test/commands/workspace/registry.test.ts test/commands/workspace/open.test.ts test/cli-e2e/workspace/workspace-open-cli.test.ts test/cli-e2e/workspace/workspace-apply-cli.test.ts`
|
||||
- Result: 9 files passed, 39/39 tests passed
|
||||
- Re-ran `git diff --check`.
|
||||
- Result: passed
|
||||
- Re-validated the Phase 18 acceptance criteria against `DECISION.md`:
|
||||
- 18.4 deferred concerns are separated from the shipped alias/materialization contract in the `Shipped POC contract to preserve` section
|
||||
- 18.5 the note explicitly names which future changes would break current tests or fixture shape and cites the affected files
|
||||
- 18.6 the note defines an additive dual-read migration seam for `projectId`, `projectBindings`, and legacy alias fields
|
||||
- Re-checked the manual smoke observations captured in `MANUAL_TEST.md`:
|
||||
- alias-keyed metadata is still present in the copied fixture workspace
|
||||
- `apply` still materializes only the selected repo and writes the existing trace fields
|
||||
|
||||
## Issues found
|
||||
|
||||
- No product correctness issues were found in the reviewed boundary.
|
||||
- No acceptance-test gaps were found in `DECISION.md`.
|
||||
- Documentation wording issue in `DECISION.md`: the shipped local overlay contract was described as "path-keyed", but the live shape is alias-keyed `repoPaths` with path values.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- Corrected `DECISION.md` to describe `.openspec/local.yaml` accurately as alias-keyed through `repoPaths`.
|
||||
- Refreshed this verification note to reflect the exact checks and the documentation fix from this pass.
|
||||
- No product or test code changes were required.
|
||||
- No additional roadmap phases were needed.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No residual risks were found within the scope of this research phase.
|
||||
- Shared-contract promotion and stable-ID work remain forward-looking design work; that is the intended deferred outcome of Phase 18, not a verification gap.
|
||||
@@ -0,0 +1,61 @@
|
||||
# Phase 19 Manual Test
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `manual-test`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
Fresh manual smoke rerun in isolated temp roots against the built CLI from the current worktree.
|
||||
|
||||
## Scenarios run
|
||||
|
||||
- Rebuilt the CLI with `pnpm run build`.
|
||||
- Scenario 1: golden happy path in a fresh XDG-isolated workspace with copied `happy-path` repos.
|
||||
- Ran `workspace create phase19-manual-happy --json`, then registered `app`, `api`, and `docs`.
|
||||
- Ran `new change phase19-manual-happy-change --targets app,api`, `workspace open --change phase19-manual-happy-change`, and `apply --change phase19-manual-happy-change --repo app --json`.
|
||||
- Marked workspace coordination tasks `2/2`, marked `app` repo tasks `2/2`, and archived the repo-local `app` change from the repo root.
|
||||
- Ran `apply --change phase19-manual-happy-change --repo api --json`, marked `api` repo tasks `2/2`, then checked `status --change phase19-manual-happy-change --json` before and after `archive phase19-manual-happy-change --workspace`.
|
||||
- Confirmed the repo-local archive entry was preserved under `repos/app/openspec/changes/archive/` and that `docs` was never materialized.
|
||||
- Scenario 2: interruption and re-entry in a fresh copy of the `dirty` fixture.
|
||||
- Copied `test/fixtures/workspace-poc/dirty/workspace` and `test/fixtures/workspace-poc/dirty/repos` into a new temp root.
|
||||
- Rewrote `.openspec/local.yaml` so `app` and `api` used canonical copied repo paths while `docs` pointed at an intentionally missing `docs-missing` path, matching the helper behavior used by the e2e suite.
|
||||
- Ran `new change phase19-manual-resume --targets app,api,docs`, `apply --change phase19-manual-resume --repo app`, marked `app` repo tasks `1/2`, then ran `status --change phase19-manual-resume` and `workspace doctor`.
|
||||
- Scenario 3: failure recovery in a second fresh copy of the `dirty` fixture with the same overlay normalization.
|
||||
- Ran `workspace add-repo app <existing-app-path>` to confirm duplicate alias rejection.
|
||||
- Ran `new change phase19-manual-unknown --targets app,missing` to confirm unknown-target rejection and no partial change creation.
|
||||
- Ran `new change phase19-manual-recovery --targets app,docs`, then `apply --change phase19-manual-recovery --repo app`, marked `app` repo tasks `1/2`, reran `apply` for `app`, ran `apply` for stale `docs`, and inspected `status --change phase19-manual-recovery --json`.
|
||||
|
||||
## Results
|
||||
|
||||
- `pnpm run build` passed.
|
||||
- Scenario 1 matched `19.4` and `19.7`.
|
||||
- After the first materialization, `status --json` reported workspace state `in-progress`.
|
||||
- After coordination completion, repo-local `app` archive, and repo-local `api` completion, `status --json` reported `soft-done`.
|
||||
- After `openspec archive phase19-manual-happy-change --workspace`, `status --json` reported `hard-done`.
|
||||
- Final targets were `api: complete` and `app: archived`.
|
||||
- The repo-local archive entry remained under `repos/app/openspec/changes/archive/2026-04-17-phase19-manual-happy-change`.
|
||||
- `docs` stayed untouched, which preserved targeted execution and repo ownership boundaries.
|
||||
- Scenario 2 matched `19.5`.
|
||||
- `status --change phase19-manual-resume` reported workspace state `blocked`.
|
||||
- `status` printed `Next step: run 'openspec workspace doctor' and repair repo alias 'docs' before resuming 'phase19-manual-resume'.`
|
||||
- `workspace doctor` exited non-zero, named the stale `docs` path explicitly, and printed `Next step: repair '.openspec/local.yaml' for alias 'docs', then rerun 'openspec workspace doctor'.`
|
||||
- The workspace was resumed from on-disk state alone; no manual reconstruction was needed.
|
||||
- Scenario 3 matched `19.6`.
|
||||
- Duplicate alias registration failed explicitly.
|
||||
- Unknown target creation failed explicitly and did not create a new workspace change directory.
|
||||
- Repeat apply failed with the documented create-only collision.
|
||||
- Stale `docs` apply failed with explicit alias naming plus `workspace doctor` guidance.
|
||||
- Final workspace status stayed coherent at `blocked`, with targets rendered as `app: in-progress (1/2)` and `docs: blocked (0/2)`.
|
||||
- Combined outcome matched `19.7`.
|
||||
- Planning remained central in the workspace.
|
||||
- Execution materialized only into the explicitly targeted repos.
|
||||
- Repo-local archive ownership stayed repo-local even after explicit workspace completion.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No product or test code changes were required during this manual-test pass.
|
||||
- Refreshed this note to record the fresh direct built-CLI rerun against current on-disk state.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No new Phase 19 residual risks were found in this manual smoke pass.
|
||||
- `ROADMAP.md` Phase 19 checkboxes were already accurate, so no checkbox changes were needed in this pass.
|
||||
@@ -0,0 +1,57 @@
|
||||
# Phase 19 Summary
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `implementation`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
## Changes made
|
||||
|
||||
- Added actionable `Next step:` guidance to workspace text status output in `src/core/workspace/status.ts`.
|
||||
- Added actionable `Next step:` guidance to `openspec workspace doctor` text output in `src/commands/workspace.ts`.
|
||||
- Extended the focused command coverage to lock the new guidance into place:
|
||||
- `test/commands/workspace/registry.test.ts`
|
||||
- `test/commands/workflow/status.test.ts`
|
||||
- Added the consolidated final acceptance suite in `test/cli-e2e/workspace/workspace-poc-acceptance-cli.test.ts`.
|
||||
- Covered the three Phase 19 scenarios directly in one realistic CLI layer:
|
||||
- golden happy path from managed workspace creation through explicit workspace hard-done
|
||||
- interruption and re-entry with one repo already in-flight and one stale repo target
|
||||
- failure recovery across duplicate aliases, unknown targets, repeat apply, stale repo paths, and partial completion
|
||||
- Created the missing Phase 19 notes and updated the Phase 19 checklist in `ROADMAP.md`.
|
||||
|
||||
## Tests or research performed
|
||||
|
||||
- Re-read the Phase 19 roadmap block in `ROADMAP.md`.
|
||||
- Re-read the existing workspace CLI and command coverage to avoid duplicating fragmented scenarios:
|
||||
- `test/cli-e2e/workspace/workspace-create-cli.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-registry-cli.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-open-cli.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-apply-cli.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-status-cli.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-archive-cli.test.ts`
|
||||
- Rebuilt the CLI:
|
||||
- `pnpm run build`
|
||||
- Ran the focused Phase 19 automated slice:
|
||||
- `pnpm exec vitest run test/commands/workspace/registry.test.ts test/commands/workflow/status.test.ts test/cli-e2e/workspace/workspace-create-cli.test.ts test/cli-e2e/workspace/workspace-registry-cli.test.ts test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts test/cli-e2e/workspace/workspace-open-cli.test.ts test/cli-e2e/workspace/workspace-apply-cli.test.ts test/cli-e2e/workspace/workspace-status-cli.test.ts test/cli-e2e/workspace/workspace-archive-cli.test.ts test/cli-e2e/workspace/workspace-poc-acceptance-cli.test.ts`
|
||||
- Ran `git diff --check`.
|
||||
- Replayed direct built-CLI smokes outside Vitest for:
|
||||
- the end-to-end happy path with explicit workspace archive
|
||||
- interruption/re-entry with stale target diagnostics
|
||||
- failure recovery with partial completion preserved after multiple error cases
|
||||
|
||||
## Results
|
||||
|
||||
- `pnpm run build` passed.
|
||||
- The focused Phase 19 automated slice passed: 10 files, 27/27 tests.
|
||||
- `git diff --check` passed.
|
||||
- The new acceptance suite proved the required scenarios on real filesystem state and real CLI invocations:
|
||||
- happy path: `in-progress` after first materialization, `soft-done` before workspace archive, `hard-done` after explicit workspace archive, with repo-local archive preserved under `openspec/changes/archive/`
|
||||
- interruption/re-entry: `status` and `workspace doctor` both surfaced the next action without reconstructing context manually
|
||||
- failure recovery: duplicate aliases, unknown targets, repeat apply, and stale repo paths all failed with actionable errors while the workspace change stayed coherent and partial repo-local progress remained visible
|
||||
- The final suite now demonstrates the POC promise from `WORKSPACE_POC_PRD.md`: plan centrally, execute locally, preserve repo ownership.
|
||||
|
||||
## Blockers and next-step notes
|
||||
|
||||
- No blockers remain for Phase 19.
|
||||
- No new bounded follow-up phases were required from this implementation pass.
|
||||
- Phase 20 can proceed to the PRD satisfaction audit rather than backfilling missing end-to-end workspace coverage.
|
||||
@@ -0,0 +1,62 @@
|
||||
# Phase 19 Verification
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `verification`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
Fresh verification pass for ROADMAP Phase 19 in a new agent context.
|
||||
|
||||
## Checks performed
|
||||
|
||||
- Re-read the Phase 19 roadmap block in `ROADMAP.md`.
|
||||
- Re-read the current implementation and manual-test notes:
|
||||
- `notes/workspace-poc/phase-19-e2e-acceptance/SUMMARY.md`
|
||||
- `notes/workspace-poc/phase-19-e2e-acceptance/MANUAL_TEST.md`
|
||||
- Re-inspected the Phase 19 implementation and acceptance boundary:
|
||||
- `src/commands/workspace.ts`
|
||||
- `src/commands/workflow/status.ts`
|
||||
- `src/core/workspace/status.ts`
|
||||
- `src/core/workspace/registry.ts`
|
||||
- `test/helpers/run-cli.ts`
|
||||
- `test/helpers/workspace-sandbox.ts`
|
||||
- `test/helpers/workspace-assertions.ts`
|
||||
- `test/commands/workspace/registry.test.ts`
|
||||
- `test/commands/workflow/status.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-status-cli.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-poc-acceptance-cli.test.ts`
|
||||
- Verified the e2e execution model directly from the helper layer:
|
||||
- `runCLI()` executes the built `dist/cli/index.js` in a child process
|
||||
- `workspaceSandbox()` copies fixture workspaces and repos into temp directories and rewrites overlay paths against real filesystem state
|
||||
- the Phase 19 acceptance suite therefore exercises the built CLI with real file IO and narrow mocks only at prompt/spinner boundaries
|
||||
- Rebuilt the CLI:
|
||||
- `pnpm run build`
|
||||
- Result: passed
|
||||
- Re-ran the focused Phase 19 verification slice:
|
||||
- `pnpm exec vitest run test/commands/workspace/registry.test.ts test/commands/workflow/status.test.ts test/cli-e2e/workspace/workspace-create-cli.test.ts test/cli-e2e/workspace/workspace-registry-cli.test.ts test/cli-e2e/workspace/workspace-targeted-change-create-cli.test.ts test/cli-e2e/workspace/workspace-open-cli.test.ts test/cli-e2e/workspace/workspace-apply-cli.test.ts test/cli-e2e/workspace/workspace-status-cli.test.ts test/cli-e2e/workspace/workspace-archive-cli.test.ts test/cli-e2e/workspace/workspace-poc-acceptance-cli.test.ts`
|
||||
- Result: 10 files passed, 27/27 tests passed
|
||||
- Ran `git diff --check`.
|
||||
- Result: passed
|
||||
- Re-mapped the acceptance tests to observed implementation evidence:
|
||||
- `19.4` verified by the happy-path branch in `test/cli-e2e/workspace/workspace-poc-acceptance-cli.test.ts`, which creates a workspace, registers three repos, opens the targeted change, materializes repo-local work, observes status transitions, preserves repo-local archive state, and explicitly archives the workspace
|
||||
- `19.5` verified by the interruption/re-entry branch in `test/cli-e2e/workspace/workspace-poc-acceptance-cli.test.ts` plus the focused `status` and `workspace doctor` command coverage in `test/commands/workflow/status.test.ts` and `test/commands/workspace/registry.test.ts`
|
||||
- `19.6` verified by the failure-recovery branch in `test/cli-e2e/workspace/workspace-poc-acceptance-cli.test.ts`, which exercises duplicate aliases, unknown targets, repeat apply, stale repo paths, and preserved partial completion
|
||||
- `19.7` verified by the combined assertions that planning stays centralized in the workspace, execution materializes only into targeted repos, committed workspace metadata does not leak repo paths, and repo-local archive ownership is preserved after explicit workspace completion
|
||||
- Reviewed documentation quality for this phase:
|
||||
- `SUMMARY.md` is consistent with the current implementation and focused test slice
|
||||
- `MANUAL_TEST.md` remains aligned with the implemented scenarios and does not claim behavior contradicted by the current code or tests
|
||||
|
||||
## Issues found
|
||||
|
||||
- No product correctness issues were found in this verification pass.
|
||||
- No acceptance-boundary gaps were found in this verification pass.
|
||||
- No documentation drift was found in the current Phase 19 notes.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No product or test code changes were required.
|
||||
- Refreshed `notes/workspace-poc/phase-19-e2e-acceptance/VERIFY.md` to record this fresh verification run.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No Phase 19 residual risks were found in this verification pass.
|
||||
- Phase 19 remains complete; later roadmap work stays in Phase 20 and beyond.
|
||||
@@ -0,0 +1,73 @@
|
||||
# Phase 20 Manual Test
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `manual-test`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
Fresh manual-test pass for PRD alignment in a new temp workspace.
|
||||
|
||||
## 1. Scenarios run
|
||||
|
||||
- Rebuilt the current CLI with `pnpm run build`.
|
||||
- Scenario 1: help-surface audit.
|
||||
- Ran `node dist/cli/index.js workspace --help`.
|
||||
- Ran `node dist/cli/index.js new change --help`.
|
||||
- Ran `node dist/cli/index.js apply --help`.
|
||||
- Ran `node dist/cli/index.js archive --help`.
|
||||
- Scenario 2: fresh workspace smoke in an isolated managed workspace.
|
||||
- Created a new temp root with fresh `XDG_CONFIG_HOME` and `XDG_DATA_HOME`.
|
||||
- Copied the `happy-path` fixture repos for `app`, `api`, and `docs`.
|
||||
- Ran `node dist/cli/index.js workspace create phase20-manual --json`.
|
||||
- Ran `node dist/cli/index.js workspace add-repo app <repo-path> --json`.
|
||||
- Ran `node dist/cli/index.js workspace add-repo api <repo-path> --json`.
|
||||
- Ran `node dist/cli/index.js workspace add-repo docs <repo-path> --json`.
|
||||
- Ran `node dist/cli/index.js new change phase20-manual-change --targets app,api`.
|
||||
- Ran `node dist/cli/index.js workspace open --change phase20-manual-change --json`.
|
||||
- Ran `node dist/cli/index.js status --change phase20-manual-change --json`.
|
||||
- Inspected `.openspec/workspace.yaml` and `.openspec/local.yaml` in the fresh managed workspace.
|
||||
- Scenario 3: shipped-doc audit.
|
||||
- Ran `rg -n "workspace create|workspace add-repo|workspace doctor|workspace open|when to use workspace|repo-local" README* docs openspec/specs -S`.
|
||||
|
||||
## 2. Results
|
||||
|
||||
- `pnpm run build` passed.
|
||||
- The supported workspace flow is visible at the CLI surface:
|
||||
- `workspace create`
|
||||
- `workspace add-repo`
|
||||
- `workspace doctor`
|
||||
- `workspace open`
|
||||
- `new change --targets`
|
||||
- `apply --change --repo`
|
||||
- `archive --workspace`
|
||||
- `new change --help` still exposes `--targets` only at change creation time. No later target-adjustment command is advertised anywhere in the shipped help surface.
|
||||
- The fresh managed workspace was created under the XDG data root, not inside the current repo.
|
||||
- In the fresh workspace:
|
||||
- `.openspec/workspace.yaml` stored committed repo aliases as empty mappings only.
|
||||
- `.openspec/local.yaml` stored the machine-specific absolute repo paths.
|
||||
- `workspace open --change` attached only `app` and `api`, not `docs`.
|
||||
- `status --change` returned the expected planned coordination plus planned `app` and `api` targets.
|
||||
- The fresh user-visible surfaces showed aliases, paths, task counts, state, source, and problems, but no owner or handoff metadata:
|
||||
- `workspace open --change ... --json`
|
||||
- `status --change ... --json`
|
||||
- `.openspec/workspace.yaml`
|
||||
- The shipped-doc audit returned no matches. There is still no shipped README, docs, or spec guide covering:
|
||||
- when to use workspace mode
|
||||
- the end-to-end workspace workflow
|
||||
- onboarding, handoff, or re-entry guidance
|
||||
- Conclusion: the implemented workspace flow still behaves correctly for what is shipped, and the remaining PRD misses are still visible from the outside:
|
||||
- missing owner or handoff visibility
|
||||
- missing shipped workspace guidance
|
||||
- no user-facing target-adjustment path after change creation
|
||||
|
||||
## 3. Fixes applied
|
||||
|
||||
- No product code fixes were required in this manual-test pass.
|
||||
- Updated this manual-test note so a fresh agent can see the exact scenarios, evidence, and remaining PRD gaps without relying on prior chat state.
|
||||
|
||||
## 4. Residual risks
|
||||
|
||||
- No new runtime correctness issue was found in the shipped workspace flow.
|
||||
- PRD signoff is still blocked until the remediation phases land for:
|
||||
- workspace guidance and re-entry onboarding
|
||||
- owner or handoff visibility
|
||||
- target-set adjustment after change creation
|
||||
@@ -0,0 +1,105 @@
|
||||
# Phase 20 Summary
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `implementation`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
## Changes made
|
||||
|
||||
- Created the missing Phase 20 audit artifacts under `notes/workspace-poc/phase-20-prd-audit/`.
|
||||
- Audited the shipped workspace POC against `WORKSPACE_POC_PRD.md` and `WORKSPACE_POC_DECISION_RECORD.md` across code, tests, prior phase notes, help text, and direct CLI behavior.
|
||||
- Updated `ROADMAP.md` to mark Phase 20 complete.
|
||||
- Inserted concrete PRD-remediation phases before final signoff:
|
||||
- Phase 21: workspace guidance and owner visibility
|
||||
- Phase 22: validation for guidance and owner visibility
|
||||
- Phase 23: workspace target-set adjustment
|
||||
- Phase 24: validation for target-set adjustment
|
||||
- moved final PRD signoff to Phase 25
|
||||
|
||||
## Tests or research performed
|
||||
|
||||
- Re-read:
|
||||
- `WORKSPACE_POC_PRD.md`
|
||||
- `WORKSPACE_POC_DECISION_RECORD.md`
|
||||
- `notes/workspace-poc/phase-07-open-contract-research/DECISION.md`
|
||||
- `notes/workspace-poc/phase-10-materialization-contract-research/DECISION.md`
|
||||
- `notes/workspace-poc/phase-13-status-research/DECISION.md`
|
||||
- `notes/workspace-poc/phase-18-deferred-research/DECISION.md`
|
||||
- `notes/workspace-poc/phase-19-e2e-acceptance/SUMMARY.md`
|
||||
- `notes/workspace-poc/phase-19-e2e-acceptance/VERIFY.md`
|
||||
- Re-inspected the current workspace implementation surface:
|
||||
- `src/core/workspace/create.ts`
|
||||
- `src/core/workspace/registry.ts`
|
||||
- `src/core/workspace/change-create.ts`
|
||||
- `src/core/workspace/open.ts`
|
||||
- `src/core/workspace/apply.ts`
|
||||
- `src/core/workspace/status.ts`
|
||||
- `src/core/workspace/archive.ts`
|
||||
- `src/commands/workspace.ts`
|
||||
- `src/commands/workflow/new-change.ts`
|
||||
- `src/commands/workflow/apply.ts`
|
||||
- `src/commands/workflow/status.ts`
|
||||
- Re-searched the current shipped docs and specs for workspace guidance and owner visibility:
|
||||
- `rg -n "workspace create|workspace add-repo|workspace doctor|workspace open|when to use workspace|repo-local" README* docs openspec/specs -S`
|
||||
- `rg -n -S -- "--owner|owner|owners|handoff" src test README* docs openspec/specs`
|
||||
- `rg -n "target add|target remove|remove target|add target|update targets|workspace target|--targets" src test README* docs openspec/specs -S`
|
||||
- Rebuilt the CLI:
|
||||
- `pnpm run build`
|
||||
- Re-ran the focused workspace automated slice:
|
||||
- `pnpm exec vitest run test/core/workspace/*.test.ts test/commands/workspace/*.test.ts test/commands/workflow/*.test.ts test/commands/archive.workspace.test.ts test/cli-e2e/workspace/*.test.ts`
|
||||
- Re-checked the currently shipped help surface:
|
||||
- `node dist/cli/index.js workspace --help`
|
||||
- `node dist/cli/index.js new change --help`
|
||||
- `node dist/cli/index.js apply --help`
|
||||
- `node dist/cli/index.js archive --help`
|
||||
- Ran a fresh manual CLI smoke in a new temp workspace:
|
||||
- created a managed workspace
|
||||
- attached `app`, `api`, and `docs` fixture repos
|
||||
- created `phase20-manual-change` with `--targets app,api`
|
||||
- inspected `workspace open --change phase20-manual-change --json`
|
||||
- inspected `status --change phase20-manual-change --json`
|
||||
|
||||
## Results
|
||||
|
||||
### PRD areas that are satisfied
|
||||
|
||||
- Persistent managed workspace home: implemented by `workspace create`, with `.openspec/` metadata plus top-level `changes/`, no inner repo-local `openspec/`, and a default managed location.
|
||||
- Central planning with the existing `change` primitive and `spec-driven` methodology: implemented by workspace-aware `new change --targets`, shared proposal/design, coordination tasks, and per-target draft slices.
|
||||
- Change-scoped repo attachment and local execution authority: implemented by `workspace open --change <id>` and create-only `apply --change <id> --repo <alias>`, with the same change ID reused in repo-local execution.
|
||||
- Explicit top-level completion semantics: implemented by workspace-aware `status` plus `archive --workspace`, with `soft-done` and `hard-done` kept separate from repo-local archive.
|
||||
- Key guardrails from the PRD and decision record are still respected:
|
||||
- committed workspace metadata stays under `.openspec/`
|
||||
- machine-specific repo paths stay in `.openspec/local.yaml`
|
||||
- repo attachment is change-scoped, not workspace-wide
|
||||
- workspace planning remains central while repo-local execution and archive stay repo-local
|
||||
- create-only materialization preserves clear authority handoff
|
||||
- End-to-end resilience is strong: the fresh automated slice passed and the Phase 19 acceptance suite still proves the happy path, interruption/re-entry, and failure recovery.
|
||||
|
||||
### PRD areas mapped to explicit non-goals or deferred scope
|
||||
|
||||
- Multi-agent parity for `workspace open` is still intentionally out of scope for v0. Phase 07 locked the supported demo path to Claude, which remains consistent with the PRD's "Claude headline, Codex secondary if straightforward" positioning.
|
||||
- Refresh or re-materialization, shared-contract promotion, stable project IDs, and team-shared mutable workspaces remain open questions or deferred work rather than shipped v0 promises.
|
||||
|
||||
### Remaining PRD gaps that block final signoff
|
||||
|
||||
- Owner visibility is missing.
|
||||
- The PRD says users should be able to identify affected repos, owners, and next actions from one planning surface.
|
||||
- Current evidence: `workspace add-repo` accepts only `<alias> <path>`, committed repo entries are written as empty mappings by default, and current `workspace open` / workspace-aware `status` surfaces expose aliases, paths, and task state only.
|
||||
- Shipped workspace guidance is missing.
|
||||
- The PRD says users should be able to recognize when workspace mode is the right tool, onboard another engineer, and re-enter an in-flight workspace without relying on scattered notes.
|
||||
- Current evidence: the shipped surface exposes CLI help text, but the doc/spec search found no README, docs, or canonical spec content that explains when to use workspace mode, the supported workflow, or the handoff/re-entry model.
|
||||
- Target-set adjustment after change creation is missing.
|
||||
- The PRD says teams should be able to adjust targets and continue when repos move at different cadences.
|
||||
- Current evidence: different cadences are supported by the shipped status and archive behavior, but target membership can only be declared at `new change --targets ...`; there is no add/remove target command or guarded update path after creation.
|
||||
|
||||
### Audit conclusion
|
||||
|
||||
- The shipped workspace POC is stable and aligned with the roadmap on the features it implements.
|
||||
- The PRD is not yet fully satisfied.
|
||||
- Final signoff must wait for the newly inserted remediation phases, because the remaining gaps are concrete product omissions rather than vague polish.
|
||||
|
||||
## Blockers and next-step notes
|
||||
|
||||
- No correctness regressions were found in the shipped workspace implementation.
|
||||
- The blocker is PRD completeness, not failing code or failing tests.
|
||||
- The next actionable phase is Phase 21, which should add shipped workspace guidance plus owner or handoff visibility before the PRD is checked again.
|
||||
@@ -0,0 +1,77 @@
|
||||
# Phase 20 Verification
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `verification`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
Fresh verification pass for ROADMAP Phase 20 in a new agent context.
|
||||
|
||||
## Checks performed
|
||||
|
||||
- Re-read the Phase 20 roadmap block in `ROADMAP.md`.
|
||||
- Re-read the current audit summary plus the source PRD and decision record:
|
||||
- `notes/workspace-poc/phase-20-prd-audit/SUMMARY.md`
|
||||
- `WORKSPACE_POC_PRD.md`
|
||||
- `WORKSPACE_POC_DECISION_RECORD.md`
|
||||
- Re-checked the implementation boundary that backs the Phase 20 conclusions:
|
||||
- `src/core/workspace/create.ts`
|
||||
- `src/core/workspace/registry.ts`
|
||||
- `src/core/workspace/change-create.ts`
|
||||
- `src/core/workspace/open.ts`
|
||||
- `src/core/workspace/apply.ts`
|
||||
- `src/core/workspace/status.ts`
|
||||
- `src/core/workspace/archive.ts`
|
||||
- `src/commands/workspace.ts`
|
||||
- `src/commands/workflow/new-change.ts`
|
||||
- `src/commands/workflow/apply.ts`
|
||||
- `src/commands/workflow/status.ts`
|
||||
- Rebuilt the CLI:
|
||||
- `pnpm run build`
|
||||
- Result: passed
|
||||
- Re-ran the workspace-focused automated slice:
|
||||
- `pnpm exec vitest run test/core/workspace/*.test.ts test/commands/workspace/*.test.ts test/commands/workflow/*.test.ts test/commands/archive.workspace.test.ts test/cli-e2e/workspace/*.test.ts`
|
||||
- Result: 24 files passed, 77/77 tests passed
|
||||
- Re-checked the shipped help surface:
|
||||
- `node dist/cli/index.js workspace --help`
|
||||
- `node dist/cli/index.js new change --help`
|
||||
- `node dist/cli/index.js apply --help`
|
||||
- `node dist/cli/index.js archive --help`
|
||||
- Re-ran the focused absence checks that support the documented PRD gaps:
|
||||
- `rg -n "workspace create|workspace add-repo|workspace doctor|workspace open|when to use workspace|repo-local" README* docs openspec/specs -S`
|
||||
- Result: no matches; no shipped workspace operator guide was found in README/docs/spec content
|
||||
- `rg -n -S -- "--owner|owner|owners|handoff" src test README* docs openspec/specs`
|
||||
- Result: only `apply` authority-handoff text was found in `src/commands/workflow/apply.ts` and related tests; no repo owner or handoff metadata surface was found for workspace registry, `workspace open`, `status`, or shipped docs/spec content
|
||||
- `rg -n "target add|target remove|remove target|add target|update targets|workspace target|--targets" src test README* docs openspec/specs -S`
|
||||
- Result: target handling exists only at change creation time through `--targets`; no shipped target-adjustment path was found
|
||||
- Re-ran a fresh isolated CLI smoke to confirm the user-facing Phase 20 audit claims:
|
||||
- created a new workspace under fresh `XDG_CONFIG_HOME` and `XDG_DATA_HOME`
|
||||
- attached copied `app`, `api`, and `docs` happy-path fixture repos
|
||||
- created `phase20-verify-change` with `--targets app,api`
|
||||
- checked `workspace open --change phase20-verify-change --json`
|
||||
- checked `status --change phase20-verify-change --json`
|
||||
- Result: `workspace open` attached only `app` and `api`; `status` reported the planned change with target entries keyed by `alias`, `problems`, `source`, `state`, and `tasks`; neither JSON surface exposed owner or handoff metadata
|
||||
- Verified the roadmap update logic:
|
||||
- Phase 20 is checked complete
|
||||
- the remaining PRD gaps are converted into concrete remediation phases
|
||||
- final PRD signoff is moved after those remediation phases
|
||||
|
||||
## Issues found
|
||||
|
||||
- No failing workspace behavior was found in the current implementation.
|
||||
- The previous Phase 20 verification note overstated one search result and blurred another:
|
||||
- the README/docs/spec search returned no matches, not CLI help strings
|
||||
- the owner or handoff search found only `apply` authority-handoff messaging, which is separate from the missing repo owner or handoff metadata gap
|
||||
- Three PRD-completeness gaps remain and are real:
|
||||
- owner or handoff visibility is missing from the shipped workspace surface
|
||||
- shipped workspace guidance is missing outside internal phase notes and CLI descriptions
|
||||
- target-set adjustment after workspace change creation is not implemented
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- Corrected this verification note so its search evidence matches the repository exactly and distinguishes authority-handoff messaging from missing owner metadata.
|
||||
- No product code changes were needed in this verification pass.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- The product is close to signoff technically, but PRD signoff would be dishonest until the newly inserted remediation phases land.
|
||||
- Later agents should treat Phase 21 as the next required step, not optional polish.
|
||||
@@ -0,0 +1,45 @@
|
||||
# Phase 21 Manual Test
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `manual-test`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
Fresh manual smoke run for ROADMAP Phase 21 using the built CLI, shipped docs/help surfaces, a new temp workspace, and an existing ownerless workspace fixture.
|
||||
|
||||
## Scenarios run
|
||||
|
||||
- Rebuilt the CLI with `pnpm run build`.
|
||||
- Scenario 1: checked the fresh-user help surface with `node dist/cli/index.js workspace --help`.
|
||||
- Scenario 2: checked the shipped docs and link surfaces with `rg -n "Workspace Mode|when to use cross-repo workspaces|workspace update-repo|When To Use Workspace Mode|Supported CLI Flow|Hand Off Work To Another Repo Owner" README.md docs/cli.md docs/workspace.md`.
|
||||
- Scenario 3: created a fresh isolated workspace with the built CLI, registered `app` and `api` aliases, captured owner or handoff guidance, created a targeted workspace change, updated repo guidance in place, then checked both `workspace open --change owner-visibility --json` and `status --change owner-visibility --json`.
|
||||
- Scenario 4: copied the existing ownerless `test/fixtures/workspace-poc/happy-path` workspace and repos into a new temp root, created `ownerless-check` with `--targets app,docs`, then checked `workspace open --change ownerless-check --json` and `status --change ownerless-check --json`.
|
||||
|
||||
## Results
|
||||
|
||||
- `pnpm run build` passed.
|
||||
- Scenario 1 passed:
|
||||
- `workspace --help` still describes workspace mode as `cross-repo planning`.
|
||||
- the help output exposes `create`, `add-repo`, `update-repo`, `doctor`, and `open`.
|
||||
- Scenario 2 passed:
|
||||
- `README.md` links to `docs/workspace.md`.
|
||||
- `docs/cli.md` exposes workspace mode in the CLI reference and points to the guide.
|
||||
- `docs/workspace.md` contains `When To Use Workspace Mode`, `Supported CLI Flow`, and the owner or handoff guidance section.
|
||||
- Scenario 3 passed:
|
||||
- `.openspec/workspace.yaml` stored only committed repo guidance:
|
||||
- `app` had `owner: App Platform` and `handoff: Materialize app after shared review`
|
||||
- `api` had `owner: API Platform` and, after `workspace update-repo`, `handoff: API owner picks up after contract sign-off`
|
||||
- no machine-local temp path leaked into `.openspec/workspace.yaml`.
|
||||
- `workspace open --change owner-visibility --json` returned both attached repos with the expected `owner` and `handoff` fields.
|
||||
- `status --change owner-visibility --json` returned both workspace targets with the expected `owner` and `handoff` fields.
|
||||
- Scenario 4 passed:
|
||||
- the copied ownerless fixture workspace stayed readable without migration or new required fields.
|
||||
- `workspace open --change ownerless-check --json` returned attached repos without `owner` or `handoff`.
|
||||
- `status --change ownerless-check --json` returned workspace targets without `owner` or `handoff`.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No product or test fixes were required during this manual-test pass.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No additional Phase 21 residual risks were found in this manual smoke.
|
||||
@@ -0,0 +1,95 @@
|
||||
# Phase 21 Summary
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `implementation`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
## Changes made
|
||||
|
||||
- Extended committed workspace repo metadata in `src/core/workspace/metadata.ts` to support optional `owner` and `handoff` fields alongside existing repo entries, with validation and backward-compatible reads for older ownerless workspaces.
|
||||
- Extended `src/core/workspace/registry.ts` so:
|
||||
- `addWorkspaceRepo()` can capture optional owner or handoff guidance at registration time
|
||||
- a new `updateWorkspaceRepoGuidance()` path updates committed owner or handoff metadata for an already-registered alias without touching `.openspec/local.yaml`
|
||||
- Updated `src/commands/workspace.ts` to ship the CLI surface for Phase 21:
|
||||
- `openspec workspace add-repo <alias> <path> [--owner ...] [--handoff ...]`
|
||||
- `openspec workspace update-repo <alias> [--owner ...] [--handoff ...]`
|
||||
- refreshed `workspace --help` descriptions to make workspace mode explicitly about cross-repo planning
|
||||
- Surfaced owner or handoff information anywhere this phase required it:
|
||||
- `src/core/workspace/open.ts` now includes repo owner or handoff guidance in attached repo JSON plus the generated instruction surface
|
||||
- `src/core/workspace/status.ts` now includes repo owner or handoff guidance in workspace target JSON and text rendering
|
||||
- `src/commands/workspace.ts` text output for `workspace open` also renders the same guidance
|
||||
- Added shipped user-facing guidance:
|
||||
- new guide: `docs/workspace.md`
|
||||
- linked from `README.md`
|
||||
- linked and summarized in `docs/cli.md`
|
||||
- Added focused regression coverage for the new metadata contract and surfaces:
|
||||
- `test/core/workspace/registry.test.ts`
|
||||
- `test/core/workspace/open.test.ts`
|
||||
- `test/commands/workspace/registry.test.ts`
|
||||
- `test/commands/workflow/status.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-create-cli.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-registry-cli.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-open-cli.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-status-cli.test.ts`
|
||||
- Created the missing Phase 21 notes and marked the Phase 21 checklist complete in `ROADMAP.md`.
|
||||
|
||||
## Tests or research performed
|
||||
|
||||
- Re-read the Phase 21 roadmap block in `ROADMAP.md`.
|
||||
- Confirmed the Phase 21 summary, verification, and manual-test artifacts were missing on disk before implementation.
|
||||
- Re-read the current PRD gap audit in:
|
||||
- `notes/workspace-poc/phase-20-prd-audit/SUMMARY.md`
|
||||
- `notes/workspace-poc/phase-20-prd-audit/VERIFY.md`
|
||||
- Re-inspected the touched implementation boundary:
|
||||
- `src/core/workspace/metadata.ts`
|
||||
- `src/core/workspace/registry.ts`
|
||||
- `src/core/workspace/open.ts`
|
||||
- `src/core/workspace/status.ts`
|
||||
- `src/commands/workspace.ts`
|
||||
- `docs/cli.md`
|
||||
- `README.md`
|
||||
- Built the CLI:
|
||||
- `pnpm run build`
|
||||
- Ran the focused workspace regression slice:
|
||||
- `pnpm exec vitest run test/core/workspace/*.test.ts test/commands/workspace/*.test.ts test/commands/workflow/status.test.ts test/cli-e2e/workspace/*.test.ts`
|
||||
- Ran `git diff --check`.
|
||||
- Checked the shipped help and doc surfaces:
|
||||
- `node dist/cli/index.js workspace --help`
|
||||
- `rg -n "Workspace Mode|when to use cross-repo workspaces|workspace update-repo|When To Use Workspace Mode|Supported CLI Flow|Hand Off Work To Another Repo Owner" README.md docs/cli.md docs/workspace.md`
|
||||
- Ran a fresh built-CLI manual smoke in an isolated temp workspace:
|
||||
- created a new workspace via `workspace create`
|
||||
- registered `app` and `api` with owner or handoff metadata
|
||||
- created `owner-visibility` with `--targets app,api`
|
||||
- updated the `api` handoff note with `workspace update-repo`
|
||||
- checked `workspace open --change owner-visibility --json`
|
||||
- checked `status --change owner-visibility --json`
|
||||
|
||||
## Results
|
||||
|
||||
- `pnpm run build` passed.
|
||||
- The focused workspace regression slice passed: 21 files, 77/77 tests.
|
||||
- `git diff --check` passed.
|
||||
- The shipped workspace contract now supports optional committed repo guidance without path leakage:
|
||||
- `.openspec/workspace.yaml` stores `owner` and `handoff` only when configured
|
||||
- `.openspec/local.yaml` remains the only place local repo paths are stored
|
||||
- The new CLI path is backward-compatible and phase-scoped:
|
||||
- existing `workspace add-repo <alias> <path>` behavior still works unchanged
|
||||
- `workspace add-repo` can now capture guidance on first registration
|
||||
- `workspace update-repo` updates that guidance later without modifying the local overlay
|
||||
- Owner or handoff visibility now appears on the existing workspace surfaces this phase targeted:
|
||||
- `workspace open` text and JSON
|
||||
- generated workspace-open instruction content
|
||||
- workspace-aware `status` text and JSON
|
||||
- Existing ownerless workspaces remained readable:
|
||||
- the full workspace regression slice still passed
|
||||
- Phase 19 acceptance CLI coverage still passed inside the same run
|
||||
- Fresh-user guidance is now shipped in-repo instead of being implied by roadmap notes:
|
||||
- `README.md` links to `docs/workspace.md`
|
||||
- `docs/cli.md` now exposes workspace mode in the CLI reference
|
||||
- `docs/workspace.md` explains when to use workspace mode, the supported CLI flow, and how to re-enter or hand off in-flight work
|
||||
|
||||
## Blockers and next-step notes
|
||||
|
||||
- No blockers remain for Phase 21.
|
||||
- No new roadmap phases were required from this implementation pass.
|
||||
- Phase 22 can now validate the shipped owner or handoff surfaces and workspace guidance in a fresh verification-focused pass.
|
||||
@@ -0,0 +1,66 @@
|
||||
# Phase 21 Verification
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `verification`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
Fresh independent verification pass for ROADMAP Phase 21.
|
||||
|
||||
## Checks performed
|
||||
|
||||
- Re-read the Phase 21 roadmap block in `ROADMAP.md`.
|
||||
- Re-read the current Phase 21 implementation summary in `notes/workspace-poc/phase-21-workspace-guidance-and-owners/SUMMARY.md`.
|
||||
- Re-inspected the Phase 21 implementation boundary:
|
||||
- `src/core/workspace/metadata.ts`
|
||||
- `src/core/workspace/registry.ts`
|
||||
- `src/core/workspace/open.ts`
|
||||
- `src/core/workspace/status.ts`
|
||||
- `src/commands/workspace.ts`
|
||||
- `docs/workspace.md`
|
||||
- `docs/cli.md`
|
||||
- `README.md`
|
||||
- Confirmed the Phase 21 contract stayed lean:
|
||||
- owner or handoff info remains optional repo-alias metadata, not a new workspace model
|
||||
- committed guidance stays separate from machine-local repo paths
|
||||
- `workspace update-repo` updates committed metadata only
|
||||
- ownerless workspaces still read without migration
|
||||
- Rebuilt the CLI:
|
||||
- `pnpm run build`
|
||||
- Result: passed
|
||||
- Re-ran the focused Phase 21 regression slice:
|
||||
- `pnpm exec vitest run test/core/workspace/*.test.ts test/commands/workspace/*.test.ts test/commands/workflow/status.test.ts test/cli-e2e/workspace/*.test.ts`
|
||||
- Result: 21 files passed, 77/77 tests passed
|
||||
- Ran `git diff --check`.
|
||||
- Result: passed
|
||||
- Re-checked the shipped help and documentation surfaces for fresh-user discovery and wording quality:
|
||||
- `node dist/cli/index.js workspace --help`
|
||||
- `rg -n "Workspace Mode|when to use cross-repo workspaces|workspace update-repo|When To Use Workspace Mode|Supported CLI Flow|Hand Off Work To Another Repo Owner" README.md docs/cli.md docs/workspace.md`
|
||||
- Ran a direct built-CLI smoke in fresh temp roots:
|
||||
- created a new `phase21-verify` workspace
|
||||
- registered `app` with owner and handoff guidance, and `api` without guidance
|
||||
- created `owner-visibility` with `--targets app,api`
|
||||
- updated `api` with `workspace update-repo --owner ... --handoff ...`
|
||||
- checked `workspace open --change owner-visibility --json`
|
||||
- checked `status --change owner-visibility --json`
|
||||
- inspected `.openspec/workspace.yaml` to confirm committed metadata stayed path-clean
|
||||
- copied the existing ownerless `happy-path` fixture workspace and repos into a fresh temp root
|
||||
- created `ownerless-check` with `--targets app,docs`
|
||||
- checked `workspace open --change ownerless-check --json`
|
||||
- checked `status --change ownerless-check --json`
|
||||
- confirmed the ownerless workspace remained readable with no `owner` or `handoff` fields required
|
||||
- Mapped the acceptance tests to the implementation and checks above:
|
||||
- `21.5` verified by the new `docs/workspace.md`, the linked `README.md`/`docs/cli.md` surfaces, and `workspace --help`
|
||||
- `21.6` verified by the registry/open/status tests plus the fresh built-CLI smoke showing owner or handoff info on workspace surfaces while committed metadata stayed path-clean
|
||||
- `21.7` verified by the passing workspace regression slice and the fresh ownerless fixture smoke, which remained readable without migration or new required fields
|
||||
|
||||
## Issues found
|
||||
|
||||
- No correctness, compatibility, or documentation-quality issues were found in the Phase 21 implementation during this verification pass.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No product or test fixes were required in this verification pass.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No additional Phase 21 residual risks were found within this phase boundary.
|
||||
@@ -0,0 +1,43 @@
|
||||
# Phase 22 Manual Test
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `manual-test`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
Fresh manual smoke run for ROADMAP Phase 22 using the built CLI, shipped help/docs surfaces, and new temp workspaces in isolated XDG roots.
|
||||
|
||||
## Scenarios run
|
||||
|
||||
- Rebuilt the CLI with `pnpm run build`.
|
||||
- Scenario 1: checked the fresh-user help surface with `node dist/cli/index.js workspace --help`.
|
||||
- Scenario 2: checked the shipped docs/help text with `rg -n "When To Use Workspace Mode|Supported CLI Flow|Re-Enter An Existing Workspace|Hand Off Work To Another Repo Owner|workspace update-repo|Workspace Mode" README.md docs/cli.md docs/workspace.md`.
|
||||
- Scenario 3: created a fresh isolated workspace with the built CLI, copied the `app` and `api` fixture repos into a temp root, registered both aliases, recorded owner or handoff guidance, created a targeted workspace change, updated repo guidance in place, then checked both text and JSON output for `workspace open --change phase22-guidance` and `status --change phase22-guidance`.
|
||||
- Scenario 4: created a second fresh isolated workspace against the older ownerless fixture shape, registered `app` and `docs` without any owner or handoff metadata, created a targeted workspace change, then checked both text and JSON output for `workspace open --change ownerless-guidance` and `status --change ownerless-guidance`.
|
||||
|
||||
## Results
|
||||
|
||||
- `pnpm run build` passed.
|
||||
- Scenario 1 passed:
|
||||
- `workspace --help` still describes workspace mode as `cross-repo planning`.
|
||||
- the help output exposes `create`, `add-repo`, `update-repo`, `doctor`, and `open`.
|
||||
- Scenario 2 passed:
|
||||
- `README.md` links to `docs/workspace.md`.
|
||||
- `docs/cli.md` exposes workspace mode in the CLI reference and points to the guide.
|
||||
- `docs/workspace.md` contains `When To Use Workspace Mode`, `Supported CLI Flow`, `Re-Enter An Existing Workspace`, and `Hand Off Work To Another Repo Owner`.
|
||||
- Scenario 3 passed:
|
||||
- the fresh workspace stored only committed owner or handoff guidance in `.openspec/workspace.yaml`.
|
||||
- `.openspec/local.yaml` remained free of owner or handoff strings.
|
||||
- `workspace open --change phase22-guidance` text plus JSON both returned the expected `owner` and `handoff` guidance for `app` and the expected `owner` guidance for `api`.
|
||||
- `status --change phase22-guidance` text plus JSON returned the same owner or handoff values as `workspace open`.
|
||||
- Scenario 4 passed:
|
||||
- the ownerless workspace remained readable without adding any new metadata.
|
||||
- `workspace open --change ownerless-guidance` text plus JSON did not emit `owner` or `handoff` fields.
|
||||
- `status --change ownerless-guidance` text plus JSON also stayed free of `owner` or `handoff` fields.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No product or test fixes were required during this manual smoke.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No additional Phase 22 residual risks were found in this manual smoke.
|
||||
@@ -0,0 +1,64 @@
|
||||
# Phase 22 Summary
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `implementation`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
## Changes made
|
||||
|
||||
- Added command-layer help coverage in `test/commands/workspace/help.test.ts` to lock the shipped workspace command wording around cross-repo planning plus the `update-repo`, `--owner`, and `--handoff` surfaces.
|
||||
- Added shipped docs/help coverage in `test/cli-e2e/workspace/workspace-guidance-cli.test.ts` to prove the current repo contains the user-facing workspace guidance required for fresh discovery:
|
||||
- `workspace --help`
|
||||
- `docs/workspace.md`
|
||||
- `docs/cli.md`
|
||||
- `README.md`
|
||||
- Extended workspace open/status regression coverage for older ownerless fixtures:
|
||||
- `test/core/workspace/open.test.ts`
|
||||
- `test/core/workspace/status.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-open-cli.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-status-cli.test.ts`
|
||||
- Tightened the Phase 19 acceptance flow in `test/cli-e2e/workspace/workspace-poc-acceptance-cli.test.ts` so the golden path now also proves `workspace open` stays clean when no owner or handoff metadata is configured.
|
||||
- Created the missing Phase 22 notes and updated the Phase 22 checklist in `ROADMAP.md`.
|
||||
|
||||
## Tests or research performed
|
||||
|
||||
- Re-read the Phase 22 roadmap block in `ROADMAP.md`.
|
||||
- Confirmed the Phase 22 artifacts were missing on disk before this run.
|
||||
- Re-read the Phase 21 implementation summary in `notes/workspace-poc/phase-21-workspace-guidance-and-owners/SUMMARY.md`.
|
||||
- Rebuilt the CLI:
|
||||
- `pnpm run build`
|
||||
- Ran the focused Phase 22 regression slice:
|
||||
- `pnpm exec vitest run test/core/workspace/open.test.ts test/core/workspace/status.test.ts test/commands/workspace/help.test.ts test/commands/workspace/registry.test.ts test/commands/workspace/open.test.ts test/commands/workflow/status.test.ts test/cli-e2e/workspace/workspace-guidance-cli.test.ts test/cli-e2e/workspace/workspace-open-cli.test.ts test/cli-e2e/workspace/workspace-status-cli.test.ts test/cli-e2e/workspace/workspace-poc-acceptance-cli.test.ts`
|
||||
- Ran `git diff --check`.
|
||||
- Re-checked the shipped docs/help wording:
|
||||
- `rg -n "When To Use Workspace Mode|Supported CLI Flow|Re-Enter An Existing Workspace|Hand Off Work To Another Repo Owner|workspace update-repo|Workspace Mode" README.md docs/cli.md docs/workspace.md`
|
||||
- Ran a fresh built-CLI smoke in isolated temp/XDG roots:
|
||||
- `node dist/cli/index.js workspace --help`
|
||||
- `node dist/cli/index.js workspace create phase22-manual --json`
|
||||
- `node dist/cli/index.js workspace add-repo ...`
|
||||
- `node dist/cli/index.js workspace update-repo ...`
|
||||
- `node dist/cli/index.js new change phase22-guidance --targets app,api`
|
||||
- `node dist/cli/index.js workspace open --change phase22-guidance --json`
|
||||
- `node dist/cli/index.js status --change phase22-guidance --json`
|
||||
|
||||
## Results
|
||||
|
||||
- `pnpm run build` passed.
|
||||
- The focused Phase 22 regression slice passed: 10 files, 40/40 tests.
|
||||
- `git diff --check` passed.
|
||||
- Shipped workspace guidance is now explicitly covered instead of being implied:
|
||||
- `workspace --help` still describes workspace mode as cross-repo planning and exposes `update-repo`
|
||||
- `docs/workspace.md` contains the workflow guidance, re-entry path, and handoff guidance sections
|
||||
- `docs/cli.md` and `README.md` point users to the shipped workspace guide
|
||||
- Owner or handoff visibility remains consistent across the targeted workspace surfaces:
|
||||
- `workspace open` text/JSON
|
||||
- workspace-aware `status` text/JSON
|
||||
- Older ownerless workspaces remain backward-compatible:
|
||||
- explicit open/status regression coverage now proves ownerless fixtures stay readable with no `owner` or `handoff` fields required
|
||||
- the Phase 19 acceptance flow still passes unchanged and now also proves the `workspace open` happy path stays free of owner or handoff text when nothing is configured
|
||||
- Fresh manual smoke passed on a newly created workspace with configured owner or handoff metadata, and both `workspace open` and workspace-aware `status` exposed that data consistently.
|
||||
|
||||
## Blockers and next-step notes
|
||||
|
||||
- No blockers remain for Phase 22.
|
||||
- No new roadmap phases were required from this validation pass.
|
||||
@@ -0,0 +1,62 @@
|
||||
# Phase 22 Verification
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `verification`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
Fresh independent verification pass for ROADMAP Phase 22.
|
||||
|
||||
## Checks performed
|
||||
|
||||
- Re-read the Phase 22 roadmap block in `ROADMAP.md`.
|
||||
- Re-read the current Phase 22 implementation summary in `notes/workspace-poc/phase-22-test-workspace-guidance-and-owners/SUMMARY.md`.
|
||||
- Re-inspected the Phase 22 boundary:
|
||||
- `test/commands/workspace/help.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-guidance-cli.test.ts`
|
||||
- `test/core/workspace/open.test.ts`
|
||||
- `test/core/workspace/status.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-open-cli.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-status-cli.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-poc-acceptance-cli.test.ts`
|
||||
- `docs/workspace.md`
|
||||
- `docs/cli.md`
|
||||
- `README.md`
|
||||
- Rebuilt the CLI:
|
||||
- `pnpm run build`
|
||||
- Result: passed
|
||||
- Re-ran the focused Phase 22 regression slice:
|
||||
- `pnpm exec vitest run test/core/workspace/open.test.ts test/core/workspace/status.test.ts test/commands/workspace/help.test.ts test/commands/workspace/registry.test.ts test/commands/workspace/open.test.ts test/commands/workflow/status.test.ts test/cli-e2e/workspace/workspace-guidance-cli.test.ts test/cli-e2e/workspace/workspace-open-cli.test.ts test/cli-e2e/workspace/workspace-status-cli.test.ts test/cli-e2e/workspace/workspace-poc-acceptance-cli.test.ts`
|
||||
- Result: 10 files passed, 40/40 tests passed
|
||||
- Ran `git diff --check`.
|
||||
- Result: passed
|
||||
- Re-checked the shipped docs/help surfaces:
|
||||
- `rg -n "When To Use Workspace Mode|Supported CLI Flow|Re-Enter An Existing Workspace|Hand Off Work To Another Repo Owner|workspace update-repo|Workspace Mode" README.md docs/cli.md docs/workspace.md`
|
||||
- Result: passed
|
||||
- Ran a fresh built-CLI smoke in isolated XDG roots with telemetry disabled for JSON assertions:
|
||||
- `node dist/cli/index.js workspace --help`
|
||||
- `node dist/cli/index.js workspace create phase22-manual --json`
|
||||
- `node dist/cli/index.js workspace add-repo app ... --owner "App Platform" --json`
|
||||
- `node dist/cli/index.js workspace add-repo api ... --owner "API Platform" --json`
|
||||
- `node dist/cli/index.js workspace update-repo app --handoff "Materialize the app slice after the shared review is approved" --json`
|
||||
- `node dist/cli/index.js new change phase22-guidance --targets app,api`
|
||||
- `node dist/cli/index.js workspace open --change phase22-guidance`
|
||||
- `node dist/cli/index.js workspace open --change phase22-guidance --json`
|
||||
- `node dist/cli/index.js status --change phase22-guidance`
|
||||
- `node dist/cli/index.js status --change phase22-guidance --json`
|
||||
- Result: passed; the created workspace root lived under the isolated XDG data directory, and both text plus JSON surfaces exposed the expected owner or handoff guidance without leaking that guidance into `.openspec/local.yaml`
|
||||
- Mapped the acceptance tests to the Phase 22 contract:
|
||||
- `22.4` verified by the new command help regression, the new docs/help CLI regression, and the checked `README.md`/`docs/cli.md`/`docs/workspace.md` surfaces
|
||||
- `22.5` verified by the existing owner or handoff regression coverage plus the fresh manual smoke showing the same guidance in both `workspace open` and workspace-aware `status`
|
||||
- `22.6` verified by the explicit ownerless fixture tests in core and CLI layers plus the passing Phase 19 acceptance suite
|
||||
|
||||
## Issues found
|
||||
|
||||
- No correctness, compatibility, or documentation-quality issues were found during this verification pass.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No additional product or test fixes were required during verification.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No additional Phase 22 residual risks were found within this phase boundary.
|
||||
@@ -0,0 +1,46 @@
|
||||
# Phase 23 Manual Test
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `manual-test`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
Fresh independent manual smoke run for ROADMAP Phase 23 using the built CLI and copied `happy-path` workspace and repo fixtures in a new temp sibling layout so the relative repo overlay stayed valid.
|
||||
|
||||
## Scenarios run
|
||||
|
||||
- Rebuilt the CLI with `pnpm run build`.
|
||||
- Copied `test/fixtures/workspace-poc/happy-path/workspace` and `test/fixtures/workspace-poc/happy-path/repos` into a fresh temp root so the checked-in relative local overlay stayed valid.
|
||||
- Scenario 1: created `manual-add` with `app,api`, then ran:
|
||||
- `node dist/cli/index.js workspace targets manual-add --add docs`
|
||||
- `node dist/cli/index.js workspace open --change manual-add --json`
|
||||
- `node dist/cli/index.js status --change manual-add --json`
|
||||
- `node dist/cli/index.js apply --change manual-add --repo docs`
|
||||
- `node dist/cli/index.js workspace targets manual-add --remove docs`
|
||||
- Scenario 2: created `manual-remove` with `app,api,docs`, then ran:
|
||||
- `node dist/cli/index.js workspace targets manual-remove --remove docs`
|
||||
- `node dist/cli/index.js workspace open --change manual-remove --json`
|
||||
- `node dist/cli/index.js status --change manual-remove --json`
|
||||
- `node dist/cli/index.js apply --change manual-remove --repo docs`
|
||||
|
||||
## Results
|
||||
|
||||
- `pnpm run build` passed.
|
||||
- Scenario 1 passed:
|
||||
- `workspace targets manual-add --add docs` updated the workspace change metadata and scaffolded the `targets/docs/` draft slice.
|
||||
- `workspace open --change manual-add --json` attached `app`, `api`, and `docs`.
|
||||
- `status --change manual-add --json` reported `api`, `app`, and `docs` as planned targets.
|
||||
- `apply --change manual-add --repo docs` materialized the docs slice into `repos/docs/openspec/changes/manual-add`.
|
||||
- `workspace targets manual-add --remove docs` failed with the explicit authority-handoff guardrail once that repo-local change existed.
|
||||
- Scenario 2 passed:
|
||||
- `workspace targets manual-remove --remove docs` removed `docs` from `.openspec.yaml` and deleted `changes/manual-remove/targets/docs/`.
|
||||
- `workspace open --change manual-remove --json` attached only `app` and `api`.
|
||||
- `status --change manual-remove --json` reported only `api` and `app`.
|
||||
- `apply --change manual-remove --repo docs` failed cleanly because `docs` was no longer targeted.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No additional product or test fixes were required during this manual smoke.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No additional Phase 23 residual risks were found in this manual smoke.
|
||||
@@ -0,0 +1,66 @@
|
||||
# Phase 23 Summary
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `implementation`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
## Changes made
|
||||
|
||||
- Added a new explicit command path, `openspec workspace targets <change>`, with `--add` and `--remove` options plus JSON output in `src/commands/workspace.ts`.
|
||||
- Implemented the target-set mutation engine in `src/core/workspace/target-set.ts`:
|
||||
- validates add or remove requests against the workspace registry
|
||||
- appends added aliases to the current target set
|
||||
- removes unmaterialized aliases by deleting their per-target draft slice
|
||||
- blocks mutations when the alias already has repo-local active or archived execution
|
||||
- rolls back filesystem mutations if metadata write fails
|
||||
- Refactored `src/core/workspace/change-create.ts` to export shared target-scaffolding helpers so new target slices reuse the same draft layout as `new change --targets`.
|
||||
- Updated `src/core/workspace/change.ts` so missing-target remediation points to the new command path instead of manual file edits.
|
||||
- Added Phase 23 regression coverage:
|
||||
- `test/core/workspace/target-set.test.ts`
|
||||
- `test/commands/workspace/targets.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-target-set-cli.test.ts`
|
||||
- `test/commands/workspace/help.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-guidance-cli.test.ts`
|
||||
- Updated shipped docs for the new command and guardrail:
|
||||
- `docs/workspace.md`
|
||||
- `docs/cli.md`
|
||||
- Marked Phase 23 complete in `ROADMAP.md`.
|
||||
|
||||
## Tests or research performed
|
||||
|
||||
- Re-read the Phase 23 roadmap block in `ROADMAP.md`.
|
||||
- Confirmed the Phase 23 notes directory was missing before this run.
|
||||
- Rebuilt the CLI:
|
||||
- `pnpm run build`
|
||||
- Ran the focused Phase 23 regression slice:
|
||||
- `pnpm exec vitest run test/core/workspace/target-set.test.ts test/core/workspace/open.test.ts test/core/workspace/apply.test.ts test/core/workspace/status.test.ts test/commands/workspace/targets.test.ts test/commands/workspace/help.test.ts test/cli-e2e/workspace/workspace-target-set-cli.test.ts test/cli-e2e/workspace/workspace-guidance-cli.test.ts`
|
||||
- Ran the broader workspace regression slice:
|
||||
- `pnpm exec vitest run test/core/workspace/*.test.ts test/commands/workspace/*.test.ts test/commands/workflow/apply.test.ts test/commands/workflow/status.test.ts test/commands/workflow/new-change.workspace.test.ts test/cli-e2e/workspace/*.test.ts`
|
||||
- Ran `git diff --check`.
|
||||
- Ran a fresh built-CLI manual smoke on copied `happy-path` fixtures covering:
|
||||
- add target after change creation
|
||||
- remove unmaterialized target
|
||||
- reject removal after repo-local materialization
|
||||
|
||||
## Results
|
||||
|
||||
- `pnpm run build` passed.
|
||||
- The focused Phase 23 slice passed: 8 files, 32/32 tests.
|
||||
- The broader workspace regression slice passed: 28 files, 98/98 tests.
|
||||
- `git diff --check` passed.
|
||||
- The new command updates `.openspec.yaml` plus `targets/<alias>/` draft slices without requiring manual metadata edits.
|
||||
- `workspace open`, `apply`, and workspace-aware `status` all honor the adjusted target set:
|
||||
- added targets immediately appear in open and status, and can be materialized with `apply`
|
||||
- removed unmaterialized targets disappear from open and status, and `apply` rejects them as untargeted
|
||||
- Guardrails now prevent silent authority drift:
|
||||
- removing a materialized target fails with an explicit authority-handoff error
|
||||
- adding an alias that already has same-ID repo-local execution also fails
|
||||
- The fresh manual smoke passed:
|
||||
- added `docs` showed up in status and materialized successfully
|
||||
- removing materialized `docs` failed with the explicit guardrail
|
||||
- removing unmaterialized `docs` on a second change removed the draft slice cleanly and left only `app` and `api` in open or status
|
||||
|
||||
## Blockers and next-step notes
|
||||
|
||||
- No blockers remain for Phase 23.
|
||||
- No new roadmap phases were required from this implementation pass.
|
||||
@@ -0,0 +1,59 @@
|
||||
# Phase 23 Verification
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `verification`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
Fresh independent verification pass for ROADMAP Phase 23.
|
||||
|
||||
## Checks performed
|
||||
|
||||
- Re-read the Phase 23 roadmap block in `ROADMAP.md`.
|
||||
- Re-read the current Phase 23 implementation summary in `notes/workspace-poc/phase-23-workspace-target-set-adjustment/SUMMARY.md`.
|
||||
- Re-inspected the implementation and contract boundary:
|
||||
- `src/core/workspace/change-create.ts`
|
||||
- `src/core/workspace/change.ts`
|
||||
- `src/core/workspace/target-set.ts`
|
||||
- `src/commands/workspace.ts`
|
||||
- `docs/workspace.md`
|
||||
- `docs/cli.md`
|
||||
- `test/core/workspace/target-set.test.ts`
|
||||
- `test/core/workspace/open.test.ts`
|
||||
- `test/core/workspace/apply.test.ts`
|
||||
- `test/core/workspace/status.test.ts`
|
||||
- `test/commands/workspace/targets.test.ts`
|
||||
- `test/commands/workspace/help.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-target-set-cli.test.ts`
|
||||
- `test/cli-e2e/workspace/workspace-guidance-cli.test.ts`
|
||||
- Rebuilt the CLI:
|
||||
- `pnpm run build`
|
||||
- Result: passed
|
||||
- Re-ran the focused Phase 23 regression slice:
|
||||
- `pnpm exec vitest run test/core/workspace/target-set.test.ts test/core/workspace/open.test.ts test/core/workspace/apply.test.ts test/core/workspace/status.test.ts test/commands/workspace/targets.test.ts test/commands/workspace/help.test.ts test/cli-e2e/workspace/workspace-target-set-cli.test.ts test/cli-e2e/workspace/workspace-guidance-cli.test.ts`
|
||||
- Result: 8 files passed, 32/32 tests passed
|
||||
- Re-ran the broader workspace regression slice:
|
||||
- `pnpm exec vitest run test/core/workspace/*.test.ts test/commands/workspace/*.test.ts test/commands/workflow/apply.test.ts test/commands/workflow/status.test.ts test/commands/workflow/new-change.workspace.test.ts test/cli-e2e/workspace/*.test.ts`
|
||||
- Result: 28 files passed, 98/98 tests passed
|
||||
- Ran `git diff --check`.
|
||||
- Result: passed
|
||||
- Mapped the acceptance tests to explicit checks:
|
||||
- `23.5` verified by `test/core/workspace/target-set.test.ts` and `test/cli-e2e/workspace/workspace-target-set-cli.test.ts` add-target scenarios
|
||||
- `23.6` verified by the remove-unmaterialized scenarios in the same core and CLI suites
|
||||
- `23.7` verified by the materialized-removal guardrail scenarios in core, command, and CLI suites
|
||||
|
||||
## Issues found
|
||||
|
||||
- Documentation gap: `docs/workspace.md` only described the remove-side guardrail for `workspace targets`, while the implementation also refuses add-side mutations when the same change ID already exists or was archived repo-local for that alias. The CLI reference also did not state that authority-handoff guardrail explicitly.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- Updated `docs/workspace.md` to state that `workspace targets` refuses add or remove mutations once the same change ID has already crossed into repo-local execution or archive state for that alias.
|
||||
- Updated `docs/cli.md` to document that `workspace targets` only mutates workspace-owned planning state and fails rather than silently rewriting authority after repo-local execution exists.
|
||||
- Tightened `test/cli-e2e/workspace/workspace-guidance-cli.test.ts` so this guardrail stays documented.
|
||||
- Re-ran the focused Phase 23 regression slice after the documentation and guidance-test update:
|
||||
- `pnpm exec vitest run test/core/workspace/target-set.test.ts test/core/workspace/open.test.ts test/core/workspace/apply.test.ts test/core/workspace/status.test.ts test/commands/workspace/targets.test.ts test/commands/workspace/help.test.ts test/cli-e2e/workspace/workspace-target-set-cli.test.ts test/cli-e2e/workspace/workspace-guidance-cli.test.ts`
|
||||
- Result: 8 files passed, 32/32 tests passed
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No additional Phase 23 residual risks were found within this phase boundary.
|
||||
@@ -0,0 +1,60 @@
|
||||
# Phase 24 Manual Test
|
||||
|
||||
Phase cycle: 1
|
||||
Stage: `manual-test`
|
||||
Date: 2026-04-17 (Australia/Sydney)
|
||||
|
||||
Fresh manual smoke run for ROADMAP Phase 24 using the built CLI, a fresh isolated managed workspace, copied `happy-path` fixture repos under a new temp root, and direct inspection of workspace change metadata after each target-set mutation.
|
||||
|
||||
## Scenarios run
|
||||
|
||||
- Rebuilt the CLI with `pnpm run build`.
|
||||
- Created a new isolated temp root with dedicated `XDG_CONFIG_HOME` and `XDG_DATA_HOME`.
|
||||
- Copied the `app`, `api`, and `docs` fixture repos from `test/fixtures/workspace-poc/happy-path/repos` into that temp root.
|
||||
- Created a fresh managed workspace with `node dist/cli/index.js workspace create phase24-manual --json`.
|
||||
- Registered `app`, `api`, and `docs` with `workspace add-repo ... --json`.
|
||||
- Inspected workspace change metadata after each mutation to confirm `.openspec.yaml` stayed aligned with the CLI-visible target set.
|
||||
- Scenario 1: add target plus re-entry checks
|
||||
- `node dist/cli/index.js new change manual-add --targets app,api`
|
||||
- `node dist/cli/index.js workspace targets manual-add --add docs --json`
|
||||
- `node dist/cli/index.js workspace open --change manual-add --json`
|
||||
- `node dist/cli/index.js status --change manual-add --json`
|
||||
- `node dist/cli/index.js apply --change manual-add --repo docs --json`
|
||||
- re-entry check: `node dist/cli/index.js workspace open --change manual-add --json`
|
||||
- re-entry check: `node dist/cli/index.js status --change manual-add --json`
|
||||
- guardrail check: `node dist/cli/index.js workspace targets manual-add --remove docs`
|
||||
- Scenario 2: remove target plus re-entry checks
|
||||
- `node dist/cli/index.js new change manual-remove --targets app,api,docs`
|
||||
- `node dist/cli/index.js workspace targets manual-remove --remove docs --json`
|
||||
- `node dist/cli/index.js workspace open --change manual-remove --json`
|
||||
- `node dist/cli/index.js status --change manual-remove --json`
|
||||
- `node dist/cli/index.js apply --change manual-remove --repo docs`
|
||||
|
||||
## Results
|
||||
|
||||
- `pnpm run build` passed.
|
||||
- Scenario 1 passed:
|
||||
- `workspace targets manual-add --add docs --json` updated the target set to `app`, `api`, `docs`.
|
||||
- Workspace change metadata also recorded `app`, `api`, `docs` after the add-target mutation.
|
||||
- `workspace open --change manual-add --json` attached `app`, `api`, and `docs`.
|
||||
- `status --change manual-add --json` reported all three targets as planned before materialization.
|
||||
- `apply --change manual-add --repo docs --json` materialized `docs`.
|
||||
- fresh re-entry via `workspace open` still attached `app`, `api`, and `docs`.
|
||||
- fresh re-entry via `status` reported `docs` as `materialized` via `repo` while `app` and `api` remained planned.
|
||||
- `workspace targets manual-add --remove docs` failed with the expected authority-handoff guardrail once repo-local execution existed.
|
||||
- Scenario 2 passed:
|
||||
- `workspace targets manual-remove --remove docs --json` reduced the target set to `app` and `api`.
|
||||
- Workspace change metadata also recorded only `app` and `api` after the remove-target mutation.
|
||||
- `workspace open --change manual-remove --json` attached only `app` and `api`.
|
||||
- `status --change manual-remove --json` reported only `app` and `api`.
|
||||
- `apply --change manual-remove --repo docs` failed cleanly because `docs` was no longer part of the workspace target set.
|
||||
- On this macOS temp-root run, the registered repo paths were canonicalized to `/private/...` realpaths and `workspace open --json` reflected those same canonical paths consistently.
|
||||
|
||||
## Fixes applied
|
||||
|
||||
- No repository code or test changes were required during this manual-test rerun.
|
||||
- Corrected the manual assertion harness during the rerun to compare against the canonical repo realpaths emitted by `workspace add-repo` and `workspace open` under macOS temp roots.
|
||||
|
||||
## Residual risks
|
||||
|
||||
- No additional Phase 24 residual risks were found in this manual smoke.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user