diff --git a/openspec/changes/add-workspace-control-plane/.openspec.yaml b/openspec/changes/add-workspace-control-plane/.openspec.yaml new file mode 100644 index 000000000..11393eacc --- /dev/null +++ b/openspec/changes/add-workspace-control-plane/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-04-11 diff --git a/openspec/changes/add-workspace-control-plane/design.md b/openspec/changes/add-workspace-control-plane/design.md new file mode 100644 index 000000000..7fa03519c --- /dev/null +++ b/openspec/changes/add-workspace-control-plane/design.md @@ -0,0 +1,174 @@ +## Context + +OpenSpec's current initialization and instruction-loading model is repo-local: + +- `openspec init` scaffolds one project path at a time +- `openspec/config.yaml` is loaded relative to one project root +- legacy cleanup explicitly treats root `AGENTS.md` as user-owned content + +That makes the current model a poor fit for multi-repo workspaces where teams want one shared control plane plus several sibling implementation repos. + +The proposed solution is to add a first-class workspace layer above project repos without regressing the current single-repo flow. + +## Goals / Non-Goals + +**Goals:** + +- provide a checked-in source of truth for multi-repo workspace topology +- support a dedicated control-plane repo pattern without requiring a monorepo +- scaffold and sync workspace files from a stable manifest +- generate a root router file for AGENTS-compatible assistants +- preserve repo-local `AGENTS.md` ownership boundaries +- keep single-repo `openspec init` behavior intact + +**Non-Goals:** + +- replacing per-repo OpenSpec initialization with workspace-only setup +- standardizing every possible assistant-specific router format in the first change +- recursively inferring arbitrary nested repository graphs +- making network calls or SCM-host assumptions during workspace discovery + +## Decisions + +### 1. Use a manifest as the source of truth + +The workspace root SHALL store `openspec-workspace.yaml` as the authoritative description of the multi-repo topology. + +Example shape: + +```yaml +version: 1 +controlPlane: + path: ./openspec-management +repos: + - name: auth + path: ./service-auth + role: implementation + instructions: ./service-auth/AGENTS.md + - name: payments + path: ./service-payments + role: implementation + instructions: ./service-payments/AGENTS.md +generation: + agentsRouter: + enabled: true + path: ./.agents.md +``` + +**Rationale:** a manifest is easier to validate, diff, and evolve than treating `.agents.md` as the primary contract. + +### 2. Keep router files generated, not authoritative + +Workspace router files such as `.agents.md` SHALL be rendered from manifest state. + +**Rationale:** this keeps OpenSpec from reintroducing the older pattern of directly owning root and nested `AGENTS.md` files. User-authored repo-local instructions remain user-managed; OpenSpec only references them. + +### 3. Add a separate `workspace` command group + +Workspace behavior belongs under a dedicated command surface: + +- `openspec workspace init` +- `openspec workspace sync` +- `openspec workspace doctor` + +**Rationale:** `openspec init` is already well established as project-scoped. Mixing workspace semantics into that command would blur scope and make safety guarantees harder to communicate. + +### 4. Default to sibling-directory discovery with explicit confirmation + +Workspace discovery SHOULD scan immediate child directories of the chosen workspace root for: + +- git repos +- existing `openspec/` directories +- `AGENTS.md` files + +Discovered repos SHALL be presented for review before they are written to the manifest. + +**Rationale:** sibling discovery matches the common `scm/` layout while avoiding hidden implicit behavior. + +### 5. Keep control-plane scaffolding lightweight + +The generated control-plane repo SHOULD start with: + +- `AGENTS.md` for control-plane instructions +- `specs/` for shared schemas or cross-repo specs +- optional `README.md` describing the workspace contract + +It MAY omit initializing a nested OpenSpec project until the team explicitly requests it. + +**Rationale:** some teams want only a workspace map first; forcing full repo initialization would add ceremony. + +## Command Behavior + +### `openspec workspace init` + +Responsibilities: + +- choose or confirm workspace root +- discover sibling repos and candidate instruction files +- create `openspec-workspace.yaml` +- scaffold the control-plane repo if missing +- generate `.agents.md` when enabled + +Key safety rules: + +- SHALL not overwrite existing repo-local `AGENTS.md` +- SHALL not add discovered repos without review +- SHALL fail clearly if the target workspace root is not writable + +### `openspec workspace sync` + +Responsibilities: + +- re-read `openspec-workspace.yaml` +- regenerate `.agents.md` and other generated workspace files +- optionally refresh control-plane boilerplate files that are OpenSpec-managed +- report drift between manifest and generated outputs + +### `openspec workspace doctor` + +Responsibilities: + +- validate manifest structure +- detect missing repo paths or instruction files +- warn when generated router files are stale +- report collisions such as duplicate repo names or duplicate paths + +## Router Generation + +The initial generated `.agents.md` SHOULD be intentionally small and mechanical: + +```md +# Workspace Router + +@control-plane: ./openspec-management/AGENTS.md +@auth: ./service-auth/AGENTS.md +@payments: ./service-payments/AGENTS.md +``` + +Generation rules: + +- include only repos present in the manifest +- use relative paths from the workspace root +- skip missing instruction files with a warning unless the manifest marks them required + +## Risks / Trade-offs + +**Risk: assistants interpret router syntax differently** +→ Mitigation: keep the manifest primary and router generation pluggable. `.agents.md` is only one output surface. + +**Risk: discovery includes unrelated sibling repos** +→ Mitigation: review step before write, plus `workspace doctor` warnings for low-confidence entries. + +**Risk: control-plane repo scope creeps into per-repo config** +→ Mitigation: keep project-root OpenSpec config unchanged; workspace manifest lives one level above individual repos. + +**Trade-off: another config file to learn** +→ Acceptable because multi-repo topology is a distinct problem that does not fit cleanly into `openspec/config.yaml`. + +## Rollout Plan + +1. Add manifest types, parser, validator, and path-normalization helpers +2. Add `workspace init` with discovery and manifest writing +3. Add `.agents.md` generation and `workspace sync` +4. Add `workspace doctor` diagnostics +5. Document the control-plane pattern and migration guidance for existing teams diff --git a/openspec/changes/add-workspace-control-plane/proposal.md b/openspec/changes/add-workspace-control-plane/proposal.md new file mode 100644 index 000000000..c71bca10d --- /dev/null +++ b/openspec/changes/add-workspace-control-plane/proposal.md @@ -0,0 +1,122 @@ +## Why + +OpenSpec currently assumes one active project root at a time. That works well for single-repo setups, but it leaves multi-repo teams without a standard way to keep agents grounded across a shared workspace. + +A common real-world setup looks like this: + +```text +scm/ +├── openspec-management/ +├── service-auth/ +└── service-payments/ +``` + +In this model, teams want: + +- a dedicated control-plane repo for shared specs, schemas, and workspace metadata +- a predictable workspace manifest that maps sibling repos and their local agent instructions +- generated router files that help AGENTS-compatible assistants discover the full project map +- automation for initial scaffolding and later resync without requiring a monorepo + +Today, users must assemble that structure by hand. OpenSpec has no first-class workspace concept, no checked-in manifest for multi-repo topology, and no CLI support for scaffolding or syncing a control-plane repo. + +## What Changes + +### 1. Add a first-class workspace model + +Introduce a checked-in workspace manifest at the shared workspace root. This manifest becomes the source of truth for multi-repo topology and control-plane settings. + +The initial format is `openspec-workspace.yaml` and includes: + +- control-plane repo path +- member repo paths +- optional repo roles and tags +- local agent-instruction file paths when present +- generation settings for workspace-level router files + +### 2. Add a dedicated workspace command surface + +Introduce a new `openspec workspace` command group for multi-repo setup and maintenance: + +- `openspec workspace init` +- `openspec workspace sync` +- `openspec workspace doctor` + +These commands are distinct from `openspec init`, which remains project-scoped. + +### 3. Scaffold a control-plane repo and workspace files + +`openspec workspace init` scaffolds a control-plane repo such as `openspec-management/`, creates the workspace manifest, and optionally generates a root router file for AGENTS-compatible assistants. + +The command SHOULD support starting from either: + +- an existing shared parent directory containing sibling repos +- an empty target directory where the control-plane repo will be created first + +### 4. Treat router files as generated outputs + +OpenSpec SHALL treat agent-facing router files such as `.agents.md` as generated artifacts derived from the workspace manifest, not as the primary persisted contract. + +This keeps the system tool-agnostic and avoids making OpenSpec responsible for owning every repo-local `AGENTS.md` file. + +### 5. Support auto-discovery with explicit review + +Workspace init/sync can scan sibling directories for candidate repos and local `AGENTS.md` files, but discovered entries SHALL be reviewed before being written into the manifest. + +This avoids accidentally sweeping unrelated repos into the workspace map. + +## Capabilities + +### New Capabilities + +- `cli-workspace`: Workspace-focused CLI commands for multi-repo scaffolding, sync, and diagnostics +- `workspace-manifest`: Checked-in manifest for control-plane configuration and repo topology + +### Modified Capabilities + +- `docs-agent-instructions`: Document workspace-generated router files and clarify ownership boundaries between user-authored local instructions and OpenSpec-generated workspace routing + +## Impact + +### New Files + +- `src/commands/workspace.ts` - Register `workspace init|sync|doctor` +- `src/core/workspace/manifest.ts` - Manifest types, parsing, validation +- `src/core/workspace/discovery.ts` - Sibling repo and instruction-file discovery +- `src/core/workspace/sync.ts` - Manifest-driven file generation and drift checks +- `src/core/workspace/router-generation.ts` - Generate `.agents.md` and related router outputs + +### Modified Files + +- `src/cli/index.ts` - Register workspace commands +- `docs/cli.md` - Document workspace command group +- `docs/getting-started.md` or new workspace docs - Explain control-plane setup and workspace lifecycle + +## Recommended UX + +```text +$ openspec workspace init + +Workspace root: /Users/alex/dev/scm +Control plane: ./openspec-management + +Discovered sibling repos: + [x] service-auth ./service-auth + [x] service-payments ./service-payments + [ ] playground-scratch ./playground-scratch + +Detected instruction files: + service-auth ./service-auth/AGENTS.md + service-payments ./service-payments/AGENTS.md + +Create: + - openspec-workspace.yaml + - openspec-management/ + - .agents.md +``` + +## Notes + +- This proposal intentionally does not overload `openspec init` with workspace behavior. +- This proposal intentionally does not make OpenSpec the owner of every repo-local `AGENTS.md`. +- Tool-specific router generation beyond `.agents.md` can follow later once the manifest and command surface are in place. diff --git a/openspec/changes/add-workspace-control-plane/specs/cli-workspace/spec.md b/openspec/changes/add-workspace-control-plane/specs/cli-workspace/spec.md new file mode 100644 index 000000000..34e8ae2a9 --- /dev/null +++ b/openspec/changes/add-workspace-control-plane/specs/cli-workspace/spec.md @@ -0,0 +1,49 @@ +## ADDED Requirements + +### Requirement: Workspace command group +The CLI SHALL provide a dedicated `openspec workspace` command group for multi-repo workspace management. + +#### Scenario: Workspace commands are available +- **WHEN** a user runs `openspec --help` +- **THEN** the CLI SHALL list a `workspace` command group +- **AND** that group SHALL include `init`, `sync`, and `doctor` subcommands + +### Requirement: Workspace initialization +`openspec workspace init` SHALL scaffold a multi-repo workspace from an explicit root directory. + +#### Scenario: Initialize a sibling-repo workspace +- **GIVEN** a workspace root containing multiple sibling repositories +- **WHEN** the user runs `openspec workspace init` +- **THEN** the command SHALL discover candidate repos and instruction files +- **AND** SHALL present the discovered entries for review before writing files +- **AND** SHALL create `openspec-workspace.yaml` at the workspace root +- **AND** SHALL scaffold the configured control-plane repo when missing + +#### Scenario: Preserve repo-local instruction ownership +- **WHEN** `openspec workspace init` encounters an existing repo-local `AGENTS.md` +- **THEN** the command SHALL reference that file in the workspace manifest or router output +- **AND** SHALL NOT overwrite the repo-local file + +### Requirement: Workspace sync +`openspec workspace sync` SHALL regenerate workspace-managed outputs from the manifest. + +#### Scenario: Regenerate workspace router +- **GIVEN** a valid `openspec-workspace.yaml` +- **WHEN** the user runs `openspec workspace sync` +- **THEN** the command SHALL regenerate `.agents.md` when router generation is enabled +- **AND** SHALL use relative paths derived from the manifest +- **AND** SHALL report generated or updated files in its summary + +### Requirement: Workspace diagnostics +`openspec workspace doctor` SHALL validate workspace topology and generated outputs. + +#### Scenario: Missing referenced repo path +- **GIVEN** a manifest entry whose `path` does not exist +- **WHEN** the user runs `openspec workspace doctor` +- **THEN** the command SHALL report the missing path as a validation problem + +#### Scenario: Stale generated router +- **GIVEN** `.agents.md` content that does not match the current manifest +- **WHEN** the user runs `openspec workspace doctor` +- **THEN** the command SHALL report the router as stale +- **AND** SHALL suggest running `openspec workspace sync` diff --git a/openspec/changes/add-workspace-control-plane/specs/workspace-manifest/spec.md b/openspec/changes/add-workspace-control-plane/specs/workspace-manifest/spec.md new file mode 100644 index 000000000..f4c692c05 --- /dev/null +++ b/openspec/changes/add-workspace-control-plane/specs/workspace-manifest/spec.md @@ -0,0 +1,45 @@ +## ADDED Requirements + +### Requirement: Checked-in workspace manifest +The system SHALL represent multi-repo workspace topology in a checked-in manifest file at the workspace root. + +#### Scenario: Workspace manifest path +- **WHEN** a workspace is initialized +- **THEN** the system SHALL create `openspec-workspace.yaml` at the workspace root +- **AND** that file SHALL be treated as the source of truth for workspace topology + +### Requirement: Manifest schema +The workspace manifest SHALL describe the control-plane repo, member repos, and generated router settings. + +#### Scenario: Manifest includes control-plane and repos +- **WHEN** a valid workspace manifest is loaded +- **THEN** it SHALL include a control-plane path +- **AND** it SHALL support a list of member repos with name and relative path +- **AND** it MAY include repo role, tags, and instruction-file path metadata + +#### Scenario: Generated router settings +- **WHEN** router generation is configured +- **THEN** the manifest SHALL support generation settings including whether `.agents.md` is enabled and where it should be written + +### Requirement: Relative path normalization +The manifest SHALL store paths relative to the workspace root. + +#### Scenario: Persisting discovered repos +- **WHEN** `openspec workspace init` persists discovered sibling repos +- **THEN** the manifest SHALL normalize their paths as relative paths from the workspace root +- **AND** SHALL use cross-platform-safe path handling + +### Requirement: Validation of collisions and missing data +The manifest loader SHALL reject invalid or ambiguous workspace definitions. + +#### Scenario: Duplicate repo names +- **WHEN** two manifest entries declare the same repo name +- **THEN** validation SHALL fail with a clear error + +#### Scenario: Duplicate repo paths +- **WHEN** two manifest entries resolve to the same relative path +- **THEN** validation SHALL fail with a clear error + +#### Scenario: Missing required control-plane path +- **WHEN** the manifest omits the control-plane path +- **THEN** validation SHALL fail before workspace sync proceeds diff --git a/openspec/changes/add-workspace-control-plane/tasks.md b/openspec/changes/add-workspace-control-plane/tasks.md new file mode 100644 index 000000000..ddf9574e8 --- /dev/null +++ b/openspec/changes/add-workspace-control-plane/tasks.md @@ -0,0 +1,34 @@ +## 1. Workspace Command Surface + +- [ ] 1.1 Add `src/commands/workspace.ts` with `init`, `sync`, and `doctor` subcommands +- [ ] 1.2 Register the workspace command group in `src/cli/index.ts` +- [ ] 1.3 Add CLI help text and examples for workspace commands + +## 2. Workspace Manifest + +- [ ] 2.1 Define manifest types and validation for `openspec-workspace.yaml` +- [ ] 2.2 Implement manifest read/write helpers with cross-platform relative path handling +- [ ] 2.3 Add validation for duplicate repo names, duplicate paths, and invalid control-plane paths +- [ ] 2.4 Add tests for manifest parsing and validation + +## 3. Discovery and Scaffolding + +- [ ] 3.1 Implement sibling repo discovery for immediate child directories +- [ ] 3.2 Detect candidate `AGENTS.md` instruction files +- [ ] 3.3 Implement reviewed selection flow before persisting discovered repos +- [ ] 3.4 Scaffold control-plane repo boilerplate when missing +- [ ] 3.5 Add tests for discovery confidence and path normalization + +## 4. Router Generation + +- [ ] 4.1 Implement manifest-driven `.agents.md` generation at workspace root +- [ ] 4.2 Ensure generation never overwrites repo-local instruction files +- [ ] 4.3 Add drift detection for generated router files +- [ ] 4.4 Add tests for router rendering and sync behavior + +## 5. Diagnostics and Docs + +- [ ] 5.1 Implement `openspec workspace doctor` validation and warnings +- [ ] 5.2 Document the control-plane workspace pattern in CLI/docs +- [ ] 5.3 Clarify ownership boundaries between generated router files and user-authored local instructions +- [ ] 5.4 Add end-to-end tests for init → sync → doctor on a sample sibling-repo workspace