diff --git a/openspec/changes/support-multi-library-cli/.openspec.yaml b/openspec/changes/support-multi-library-cli/.openspec.yaml new file mode 100644 index 0000000000..29382a2c80 --- /dev/null +++ b/openspec/changes/support-multi-library-cli/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-09-29 diff --git a/openspec/changes/support-multi-library-cli/design.md b/openspec/changes/support-multi-library-cli/design.md new file mode 100644 index 0000000000..179c9292f3 --- /dev/null +++ b/openspec/changes/support-multi-library-cli/design.md @@ -0,0 +1,95 @@ +# Design + +## Context + +Root selection currently returns one project-shaped root through `root-selection.ts`. Command adapters assume that root determines schema resolution, task counting, spec comparison, archive destinations, and workflow edit boundaries. Listing PR #2009 introduces a bounded descendant scanner and aggregate ownership metadata. See proposal.md for motivation and specs/cli-library-selection/spec.md for the shared contract. + +## Goals / Non-Goals + +**Goals:** Reuse one discovered library set per invocation; resolve an owner before delegation; preserve command-specific parsers, options, and output schemas; keep every write tied to one verified project root. + +**Non-Goals:** A registered workspace, new layout, cross-library spec merging, bulk archive/update/init, or changing machine-level registry/config commands. + +## Decisions + +### Use an invocation-local library set + +Promote #2009's small discovery helper to a shared library-discovery module. Keep the existing root resolver authoritative for explicit stores, project pointers, nearest local roots, and fallback provenance. Derive a local discovery base from the nearest selected project or, without a local selection, the original cwd. Never scan local descendants for a store-selected invocation. + +Cache the discovery result within that command invocation, including canonical project paths, normalized relative labels, and diagnostics. Command adapters receive this result; they do not implement their own traversal. The scanner's exclusion list and legacy qualification rules stay shared. Avoid a process-global cache because tests and sequential CLI invocations must not retain stale filesystem state. + +### Separate discovered scope from resolved command target + +Discovery determines where a command may look. A target resolver determines exactly where it will execute. + +- Aggregate commands iterate the library set and retain relative ownership labels. +- Existing-item commands collect candidates by `(canonical library, item type, item id)`. A unique candidate becomes the command root. Resolve `--type` before evaluating library ambiguity. Do not give a root-local duplicate priority over a descendant duplicate. +- Root-level operations use an explicit selection or the existing nearest root. Without either, a sole discovered library is usable; several require selection. +- `--library ` selects one eligible library within the invocation's discovered scope and suppresses aggregation. It resolves from the original cwd, not from whichever root was found first. It accepts the project directory containing `openspec/`, matching existing init/update positional targets. CLI hints quote paths with spaces. +- Existing explicit init/update positional paths keep their setup semantics, including initializing a new project without an existing library. Conflicting explicit targets or a combined store/library selection fail before execution. + +A generic workspace abstraction and item identifiers encoded as `library:item` were considered. The former adds machinery without changing the required behavior; the latter conflicts with existing nested spec identifiers and shell/path syntax. An optional explicit selector keeps item IDs intact and default unique lookup automatic. + +### Command coverage + +| Command family | Default local behavior | Explicit target / write boundary | +| --- | --- | --- | +| `list`, `view` | Aggregate selected local library plus descendants | `--library` or store selects one library | +| `show`, `change show`, `spec show` | Unique owning-library lookup; labeled interactive choices | `--type` resolves type ambiguity; `--library` resolves owner ambiguity | +| `validate --all/--changes/--specs` and legacy bulk forms | Iterate libraries; keep each library's baseline and schema separate | Explicit library/store narrows validation | +| `validate ` and noun validation forms | Unique owning-library lookup | No arbitrary choice when names repeat | +| `status`, `instructions`, apply/archive instructions | Resolve named change owner; label candidate choices when omitted | Artifact paths and allowed edit roots come from the owner | +| `archive` and legacy archive forms | Resolve one change owner before preparing any write | Specs and archive destination stay in that library | +| `new change` | Existing nearest local root; otherwise sole discovered library | `--library` selects creation target; ambiguous targetless creation fails | +| `doctor`, `context` | Aggregate local health/working sets with library and reference provenance | Explicit library/store preserves single-root output | +| `schemas`, `templates` | Group inventories by library without merging same-named definitions | Explicit library chooses one project's definitions | +| `schema which/validate` | Resolve requested project schema in library scope; built-in names retain nearest/selected-root semantics | Duplicate project-local definitions require owner selection | +| `schema init/fork` | Nearest root or sole discovered library | Every schema write has one target | +| `init` / `experimental` | Existing cwd setup behavior and explicit positional path remain valid | `--library` targets a discovered product; never initialize all descendants | +| `update` | Nearest selected project or sole discovered library | Existing positional path / `--library` targets one project | +| `change list`, `spec list` | Aggregate matching inventories with ownership labels | Preserve noun-command deprecation warnings and single-root format | +| Store registry/setup, machine config, completion installation, feedback, version | Existing machine-level behavior | No local-library traversal | +| Workset management | Existing explicit member paths and saved selections | Members continue to identify their own roots | + +`apply` is an agent workflow supported by apply instructions, not a newly invented CLI mutation command. Keep the owning product's implementation/edit scope in its action context. Root-library edits remain root scoped. + +### Reuse data collectors and keep presentation separate + +Extract view's existing change/spec collectors and section renderer only as needed to render several libraries. Build one aggregate summary, then per-library sections. Keep active-change percentage sorting, workflow artifact states, and per-library schema lookup. Empty libraries remain visible. Preserve a single-library dashboard layout where practical; no repeated absolute-path banners. + +Show and named validation resolve an owner, then delegate to their existing change/spec implementations. Bulk validation retains the existing concurrency limit across the whole invocation rather than multiplying it per library. Compare each change delta against its owner's baseline. Archive receives the resolved owner before task checks, merge preparation, and move calculation. + +Schema and template inventories identify owner-specific definitions even when names match. Context runs existing assembly for each local library and records declaration origin when deduplicating referenced store roots; local duplicate item names never collapse. Doctor retains established diagnostic codes and annotates aggregate results by library. + +### Add metadata without replacing payloads + +Preserve every single-library JSON shape, including errors and legacy noun arrays. Aggregated top-level results retain existing command payload arrays and add `library` to entries plus `roots` metadata. Validation issues retain locations relative to the owning root, with the library label making them unambiguous. Context keeps the selected root as `root` when one exists and adds discovered `roots`; without a selected local root, expose `root: null` with the discovered roots rather than inventing a project owner. + +Legacy noun JSON remains an array; aggregated entries add library/root ownership fields instead of replacing that array with an envelope. Raw Markdown show stays raw; owner verification and ambiguity diagnostics use the existing stderr/error channels. Banners and ANSI styles never enter JSON. + +### Do not choose through unreadable candidates + +Aggregate reads collect one actionable diagnostic per library and continue with readable libraries. Existing-item mutations require complete candidate inspection before concluding that a name is unique. A failed library read can conceal a duplicate; therefore stop selection before any write. Explicitly selecting a healthy library can recover without touching an unhealthy sibling. + +### Support native paths and existing terminal behavior + +Use Node path operations and the shared canonicalization utilities for filesystem identity. Normalize display identifiers to relative forward-slash labels. Test native Windows separators, case/short-name aliases where supported, junctions, directory symlinks, and quoted path hints. Terminal colors inherit the existing theme, and plain/narrow output remains readable. Screenshots use fictional temporary fixture data. + +## Risks / Trade-offs + +- Duplicate names change formerly root-local direct behavior → return explicit candidates and copyable selection commands; preserve product cwd scope. +- An unavailable library can conceal a mutation target → require complete ownership resolution or explicit selection before delegating a write. +- Schema names are commonly repeated → preserve selected-root resolution for built-in schemas and label project-local schema inventories instead of merging definitions. +- Aggregate validation can increase work → prune traversal and share the existing concurrency bound; do not introduce configuration or background indexing. +- Global default stores and project pointers could leak unrelated work → reuse existing store precedence and suppress local aggregation for selected stores. +- Broad adapter coverage can leave aliases behind → maintain the command matrix as a test inventory, including deprecated noun forms, hints, and completion flags. + +## Migration Plan + +1. Obtain proposal approval before implementation, following CONTRIBUTING.md. +2. Land or reuse #2009's listing scanner and presentation conventions. +3. Introduce shared discovery/selection and wire aggregate reads, then named reads/workflows, then one-library mutations and aliases. +4. Update help, docs, agent guidance, completions, and a user-facing changeset in the implementation PR. +5. Run the contribution checks and Windows CI; publish fictional-data captures of view and cross-library inspection/validation. + +Rollback the implementation changeset and adapters together; the repository layout and artifacts require no data migration. diff --git a/openspec/changes/support-multi-library-cli/proposal.md b/openspec/changes/support-multi-library-cli/proposal.md new file mode 100644 index 0000000000..f270a08989 --- /dev/null +++ b/openspec/changes/support-multi-library-cli/proposal.md @@ -0,0 +1,36 @@ +# Proposal + +## Why + +Recursive listing exposes work in descendant OpenSpec libraries, but the remaining CLI still treats the repository as one library. Users should be able to browse, inspect, validate, and work on that discovered change from the same directory without moving or registering their libraries. + +## What Changes + +- Extend local-library discovery from list to view, show, validate, change/workflow commands, context, doctor, and library-specific schema/setup commands. +- Combine dashboards and bulk validation across the selected local library and its valid descendants, with relative library labels and distinct item ownership. +- Resolve named changes/specs to their owning library. Duplicate matches produce actionable ambiguity diagnostics before any command runs against an item. +- Add an optional `--library ` selector to library-aware commands. It selects one discovered local project, using the same project-path convention as existing init/update positional paths. Default browsing and unique item lookup require no configuration or flag. +- Keep registered stores scoped to the selected store. Keep every mutation and schema/config write scoped to one library; never infer a repository-wide write from recursive discovery. +- Preserve nearest-project behavior, legacy layouts, existing item parsing/status logic, and single-library JSON. Aggregate results include owning-library metadata and partial-failure diagnostics. +- Update CLI help, user/agent guidance, completion definitions, and examples so hints remain inside the resolved library. + +## Capabilities + +### New Capabilities + +- `cli-library-selection`: Local-library discovery, explicit selection, owning-library lookup, ambiguity handling, command scope, and cross-platform path identity. + +### Modified Capabilities + +- `cli-view`: Combined dashboard with aggregate totals and per-library sections. +- `cli-show`: Inspect and select items from discovered descendant libraries. +- `cli-validate`: Bulk validation across libraries and owning-library direct validation. +- `cli-artifact-workflow`: Resolve workflow operations from the owning library and explicitly target new changes. +- `cli-archive`: Archive exactly one unambiguously owned change into its own library. +- `cli-update`: Update one selected library using its configuration and integrations. + +## Impact + +Shared root/item discovery, CLI command adapters, JSON ownership metadata, interactive pickers, workflow action/edit-root context, schema resolution, follow-up hints, and completion flags. No external dependency or new workspace configuration is needed. This follows listing PR #2009; reuse its helper when it merges rather than introduce another scanner. + +Named commands that previously chose a root-local duplicate implicitly will now require a library selection when the same item exists elsewhere within the discovered scope. This is an intentional error-path compatibility change; commands run inside a product retain their product-local scope. diff --git a/openspec/changes/support-multi-library-cli/specs/cli-archive/spec.md b/openspec/changes/support-multi-library-cli/specs/cli-archive/spec.md new file mode 100644 index 0000000000..051ea65623 --- /dev/null +++ b/openspec/changes/support-multi-library-cli/specs/cli-archive/spec.md @@ -0,0 +1,16 @@ +## ADDED Requirements + +### Requirement: Archive owning library selection +Archive SHALL resolve a named change within the discovered scope before any task check, spec write, or archive move. It SHALL require an explicit library selection for duplicate names and keep all existing archive checks and prompts within the selected library. + +#### Scenario: Archive a unique descendant change +- **WHEN** archive names a change found only in a descendant library +- **THEN** merge its delta into that library's specs and move it to that library's archive + +#### Scenario: Duplicate archive names +- **WHEN** two discovered libraries contain the named change +- **THEN** report both paths and exit without modifying either library + +#### Scenario: Unreadable candidate library +- **WHEN** a candidate library cannot be inspected when establishing archive ownership +- **THEN** report incomplete selection and leave all artifacts unchanged diff --git a/openspec/changes/support-multi-library-cli/specs/cli-artifact-workflow/spec.md b/openspec/changes/support-multi-library-cli/specs/cli-artifact-workflow/spec.md new file mode 100644 index 0000000000..bb929892ff --- /dev/null +++ b/openspec/changes/support-multi-library-cli/specs/cli-artifact-workflow/spec.md @@ -0,0 +1,16 @@ +## ADDED Requirements + +### Requirement: Owning library workflow execution +Status, instructions, apply instructions, and archive instructions SHALL resolve named changes to their unique owning library. New change and library-specific template/schema commands SHALL honor explicit library selection. Workflow output SHALL retain the selected library in artifact paths, action/edit-root context, and follow-up hints. + +#### Scenario: Descendant change status +- **WHEN** status --change names a unique descendant change +- **THEN** resolve schema, task artifacts, and all output paths from its owning library + +#### Scenario: Descendant apply instructions +- **WHEN** instructions apply targets a descendant change +- **THEN** return instructions and allowed edit roots for that product, retaining existing artifact prerequisites + +#### Scenario: Explicit new change +- **WHEN** new change is run with --library batch-worker +- **THEN** create only that product's change and preserve selection in the printed next command diff --git a/openspec/changes/support-multi-library-cli/specs/cli-library-selection/spec.md b/openspec/changes/support-multi-library-cli/specs/cli-library-selection/spec.md new file mode 100644 index 0000000000..caf0d454da --- /dev/null +++ b/openspec/changes/support-multi-library-cli/specs/cli-library-selection/spec.md @@ -0,0 +1,124 @@ +# Spec Delta + +## Purpose + +Let users operate on product-specific OpenSpec libraries from a shared repository directory while keeping each item and write associated with its owning library. + +## ADDED Requirements + +### Requirement: Local library scope +The CLI SHALL discover the selected local root and valid descendant libraries for library-aware commands. Without a local root it SHALL discover below the current directory. Discovery SHALL preserve legacy layouts, excluded directories, symlink boundaries, and physical-root deduplication established for recursive listing. + +#### Scenario: Product-local scope +- **WHEN** a command runs inside a product with its own OpenSpec root +- **THEN** its discovery scope includes that product and its descendants +- **AND** sibling product libraries remain outside the scope + +#### Scenario: Parent without a root +- **WHEN** a command runs above valid descendant libraries without a local root +- **THEN** those libraries are available before any machine-level default store fallback + +#### Scenario: Excluded paths +- **WHEN** dependencies, caches, builds, worktrees, virtual environments, planning contents, or directory symlinks contain apparent libraries +- **THEN** discovery omits those paths and lists each remaining physical library once + +### Requirement: Explicit library selection +Library-aware commands SHALL accept an optional --library project-path selector that selects exactly one discovered local library. Relative paths SHALL resolve from the command's original working directory. Store and library selectors SHALL be mutually exclusive. Existing init/update positional project paths SHALL remain valid explicit targets. + +#### Scenario: Select a descendant +- **WHEN** a user runs show, validate, status, archive, or another library-aware command with --library batch-worker +- **THEN** the command targets only that discovered project's library +- **AND** command hints retain the selection + +#### Scenario: Invalid selection +- **WHEN** the selected path is outside the discovered scope, is excluded, or is a directory symlink +- **THEN** report an actionable selection error before reading an item or writing files + +#### Scenario: Conflicting selectors +- **WHEN** --store and --library are supplied together or --library conflicts with a positional project path +- **THEN** report the conflict before executing the command + +### Requirement: Owning library lookup +Commands naming an existing change, spec, or local schema SHALL resolve the item within the discovered scope. Exactly one matching library SHALL select that owner. Multiple matches SHALL produce a library ambiguity error containing relative paths and explicit-selection examples. Existing change-versus-spec type ambiguity SHALL remain separately actionable. + +#### Scenario: Unique descendant item +- **WHEN** a named item exists only in a descendant library +- **THEN** operate on that item using its library's configuration, schemas, specs, and paths + +#### Scenario: Duplicate names +- **WHEN** the same item name exists in the root and a descendant or two descendants +- **THEN** list every candidate library and require selection before executing the item command + +#### Scenario: Nested spec identifier +- **WHEN** a spec identifier contains path separators such as platform/session +- **THEN** preserve it as a spec identifier and use --library to disambiguate its owner + +### Requirement: Store scope +Commands selecting a registered store explicitly or through a project pointer SHALL keep that store's existing scope. A default store SHALL remain a fallback when no local library resolves. Local discovery SHALL preserve the provenance of store-selected roots. + +#### Scenario: Explicit store +- **WHEN** --store selects a store while unrelated local libraries exist +- **THEN** browse, validate, inspect, and modify only the selected store + +#### Scenario: Project store pointer +- **WHEN** a config-only project declares a store +- **THEN** resolve that store through the existing store identity and health checks +- **AND** unrelated descendant projects remain outside the selection + +### Requirement: Single-library writes +Commands that create, update, archive, initialize, or otherwise write library-specific files SHALL resolve one target before making changes. Existing named items SHALL use their unique owning library. Apart from initialization's existing cwd setup behavior, new items and root-level writes SHALL use an explicit target or the nearest selected local root; without either, one discovered library SHALL be selected and multiple libraries SHALL produce a target-selection error. + +#### Scenario: Archive ownership +- **WHEN** a unique descendant change is archived from the repository root +- **THEN** update specs and archive the change inside its owning library only +- **AND** retain existing task checks, prompts, and archive options + +#### Scenario: New change with local root +- **WHEN** a new change is created from a repository with its own selected root and descendants +- **THEN** create it in the selected root unless --library chooses another project + +#### Scenario: Targetless write above several libraries +- **WHEN** a creation or root-level write has several possible libraries and no nearest or explicit target +- **THEN** print candidate project paths and selection examples before writing any file + +#### Scenario: Default initialization +- **WHEN** init runs without a positional project path or --library +- **THEN** retain its existing cwd initialization behavior for one project + +#### Scenario: Explicit initialization +- **WHEN** init receives an explicit project path that does not yet have an OpenSpec library +- **THEN** initialize exactly that project using existing initialization behavior + +### Requirement: Library-aware health and context +Doctor and context SHALL report discovered local libraries with owning-library metadata. Schema and template inventories SHALL keep library-specific definitions separately labeled. A single-root response SHALL keep its existing shape; aggregated JSON SHALL retain command payload arrays and add library and roots metadata. + +#### Scenario: Multiple local contexts +- **WHEN** context runs in a split-library repository +- **THEN** include each local library's working set with its ownership and reference provenance +- **AND** preserve distinct items and diagnostics when names repeat + +#### Scenario: Health and schema inventories +- **WHEN** doctor, schemas, or templates runs across several local libraries +- **THEN** label each library's health or definitions without merging same-named local schemas + +### Requirement: Partial failures and clean JSON +Read-only aggregate commands SHALL retain successful library results and report one actionable diagnostic per unreadable or malformed library. Failures SHALL produce a nonzero exit status. JSON SHALL contain no banners, colors, or presentation text, and single-library payloads SHALL preserve their existing shape. + +#### Scenario: One failing library +- **WHEN** one library cannot be read during a combined dashboard, context, doctor, or bulk validation +- **THEN** show successful libraries and identify the failing relative library path with a suggested fix + +#### Scenario: Failed mutation lookup +- **WHEN** an unreadable candidate library prevents establishing a unique mutation target +- **THEN** report incomplete selection and write nothing + +### Requirement: Cross-platform library paths +Library selection SHALL support native platform paths and canonical physical identity on macOS, Linux, and Windows. Human labels and JSON library identifiers SHALL consistently use relative forward-slash labels, while filesystem operations and absolute root paths SHALL follow platform conventions. + +#### Scenario: Windows selection +- **WHEN** a Windows user selects a discovered project using native backslash separators +- **THEN** resolve the same owning library as its normalized label and preserve the selected root in follow-up commands + +#### Scenario: Path aliases +- **WHEN** two path spellings identify the same permitted physical library +- **THEN** report that library once and use canonical identity for ambiguity checks diff --git a/openspec/changes/support-multi-library-cli/specs/cli-show/spec.md b/openspec/changes/support-multi-library-cli/specs/cli-show/spec.md new file mode 100644 index 0000000000..8399bc899f --- /dev/null +++ b/openspec/changes/support-multi-library-cli/specs/cli-show/spec.md @@ -0,0 +1,16 @@ +## ADDED Requirements + +### Requirement: Library-aware item display +The show command SHALL discover items across the local library scope, show library labels in interactive choices, and resolve a named item to its unique owner. It SHALL honor --library and existing --type flags and emit ambiguity diagnostics containing the candidate libraries. + +#### Scenario: Show a descendant spec +- **WHEN** show names a spec that exists in one descendant library +- **THEN** show that library's spec content using existing formatting and JSON options + +#### Scenario: Select duplicate changes interactively +- **WHEN** two libraries contain a change with the same name +- **THEN** offer separate labeled choices and display the selected owner's change + +#### Scenario: Ambiguous direct show +- **WHEN** direct show names an item in multiple libraries +- **THEN** report their relative project paths and --library examples without displaying an arbitrary item diff --git a/openspec/changes/support-multi-library-cli/specs/cli-update/spec.md b/openspec/changes/support-multi-library-cli/specs/cli-update/spec.md new file mode 100644 index 0000000000..13050c376f --- /dev/null +++ b/openspec/changes/support-multi-library-cli/specs/cli-update/spec.md @@ -0,0 +1,12 @@ +## ADDED Requirements + +### Requirement: Library-specific integration updates +Update SHALL select one project library before rewriting integrations or generated files. It SHALL preserve explicit positional project paths, honor --library, and use the nearest selected local project by default. Multiple descendant targets without a nearest root SHALL require explicit selection. + +#### Scenario: Update a descendant project +- **WHEN** update selects a descendant with --library batch-worker +- **THEN** update only that project's configured integrations and generated files + +#### Scenario: No nearest update target +- **WHEN** update runs above several libraries without an explicit project +- **THEN** list possible project paths and exit before writing integrations diff --git a/openspec/changes/support-multi-library-cli/specs/cli-validate/spec.md b/openspec/changes/support-multi-library-cli/specs/cli-validate/spec.md new file mode 100644 index 0000000000..4faa5e2985 --- /dev/null +++ b/openspec/changes/support-multi-library-cli/specs/cli-validate/spec.md @@ -0,0 +1,51 @@ +## MODIFIED Requirements + +### Requirement: Bulk and filtered validation + +The validate command SHALL support flags for bulk validation (--all) and filtered validation by type (--changes, --specs). + +#### Scenario: Validate everything + +- **WHEN** executing `openspec validate --all` +- **THEN** validate all changes in each discovered library's openspec/changes/ (excluding archive) +- **AND** validate all specs in each discovered library's openspec/specs/ +- **AND** display a summary showing passed/failed items +- **AND** exit with code 1 if any validation fails + +#### Scenario: Scope of bulk validation + +- **WHEN** validating with `--all` or `--changes` +- **THEN** include all change proposals under each discovered library's `openspec/changes/` +- **AND** exclude the `openspec/changes/archive/` directory + +- **WHEN** validating with `--specs` +- **THEN** include all specs that have a `spec.md` under each discovered library's `openspec/specs//spec.md` + +#### Scenario: Validate all changes + +- **WHEN** executing `openspec validate --changes` +- **THEN** validate all changes in each discovered library's openspec/changes/ (excluding archive) +- **AND** display results for each change +- **AND** show summary statistics + +#### Scenario: Validate all specs + +- **WHEN** executing `openspec validate --specs` +- **THEN** validate all specs in each discovered library's openspec/specs/ +- **AND** display results for each spec +- **AND** show summary statistics + +#### Scenario: Library-aware validation results +- **WHEN** bulk validation spans multiple local libraries +- **THEN** group results by relative library and include owning library metadata in JSON items +- **AND** retain distinct results for repeated item identifiers + +#### Scenario: Direct descendant validation +- **WHEN** validate names an item found uniquely in a descendant library +- **THEN** validate against that library's specs and schemas + +#### Scenario: Partial validation failure +- **WHEN** one discovered library cannot be inspected +- **THEN** continue validating readable libraries and report an actionable library diagnostic +- **AND** exit nonzero + diff --git a/openspec/changes/support-multi-library-cli/specs/cli-view/spec.md b/openspec/changes/support-multi-library-cli/specs/cli-view/spec.md new file mode 100644 index 0000000000..b98e2166e1 --- /dev/null +++ b/openspec/changes/support-multi-library-cli/specs/cli-view/spec.md @@ -0,0 +1,27 @@ +## MODIFIED Requirements + +### Requirement: Dashboard Display + +The system SHALL provide a `view` command that displays a dashboard overview of specs and changes. + +#### Scenario: Basic dashboard display + +- **WHEN** user runs `openspec view` +- **THEN** system displays a formatted dashboard with sections for summary, active changes, completed changes, and specifications + +#### Scenario: No OpenSpec directory + +- **WHEN** user runs `openspec view` in a directory without a local or descendant OpenSpec library +- **THEN** system displays error message "✗ No openspec directory found" + +#### Scenario: Combined dashboard +- **WHEN** view runs with multiple discovered local libraries +- **THEN** display aggregate metrics and per-library draft, active, completed, archived, and spec sections +- **AND** label libraries by relative path in stable order, root first +- **AND** keep empty libraries visible and duplicate item names distinct + +#### Scenario: Partially unreadable dashboard +- **WHEN** one discovered library is unreadable or malformed +- **THEN** retain readable libraries and report one actionable diagnostic for the failing library +- **AND** exit nonzero + diff --git a/openspec/changes/support-multi-library-cli/tasks.md b/openspec/changes/support-multi-library-cli/tasks.md new file mode 100644 index 0000000000..0286a2d182 --- /dev/null +++ b/openspec/changes/support-multi-library-cli/tasks.md @@ -0,0 +1,39 @@ +# Tasks + +## 1. Shared local library discovery and selection + +- [ ] 1.1 Reuse the listing scanner as a shared invocation-local library set; verify fixtures cover root/descendant/no-root/legacy libraries, pruning, symlinks, physical deduplication, and malformed/unreadable roots. +- [ ] 1.2 Add optional library selection and selector conflict checks; verify native relative paths, spaces, invalid/outside/excluded targets, and store/pointer/default precedence with CLI fixtures. +- [ ] 1.3 Add typed item-owner resolution and duplicate diagnostics; verify root-versus-descendant and sibling duplicates, nested spec IDs, type ambiguity, unknown items, and unreadable candidate handling. +- [ ] 1.4 Add shared completion/help entries and library-preserving command hints; verify generated hints run with paths containing spaces and document scope and selection examples. + +## 2. Aggregate read commands + +- [ ] 2.1 Render view with one combined summary and per-library sections using existing status/schema collectors; verify duplicate names, empty libraries, workflow states, category/spec sorting, narrow/plain/color output, and partial failures. +- [ ] 2.2 Extend bulk validation across libraries using one existing concurrency limit; verify owner-local baselines, repeated IDs, filtered modes, partial failures, aggregate JSON ownership, and unchanged single-library responses. +- [ ] 2.3 Extend context and doctor across local libraries with ownership/provenance metadata; verify same-named items, shared referenced stores, per-library diagnostics, clean JSON, and explicitly selected store/library scope. +- [ ] 2.4 Group schema/template inventories without merging library-local definitions; verify matching names, built-in definitions, explicit selection, and one-library output compatibility. +- [ ] 2.5 Update browse/validate/context/doctor/schema reference documentation and verify each sample against temporary fixtures with fictional product names. + +## 3. Named reads and workflow ownership + +- [ ] 3.1 Route show and interactive choices through owning-library resolution; verify Markdown/JSON formats, type-specific flags, duplicate diagnostics, labeled choices, and existing noninteractive behavior. +- [ ] 3.2 Route named validate, status, instructions, and apply/archive instructions through the resolved owner; verify schema/artifact paths, task counts, prerequisites, action context, and allowed product edit roots. +- [ ] 3.3 Route schema which/validate to project-local owners while preserving selected-root built-in behavior; verify duplicate custom schemas and explicit library selection. +- [ ] 3.4 Wire deprecated change/spec display, list, and validation adapters; verify deprecation channels, library ownership, aggregate array compatibility, and unchanged single-library formats. +- [ ] 3.5 Update user and generated agent guidance for duplicate names and owning-library workflows; verify printed next steps retain the selected product and store flags. + +## 4. Single-library mutations and setup + +- [ ] 4.1 Route archive through complete owner resolution before write preparation; verify only the owning library's specs/archive change and all siblings stay byte-identical for unique, duplicate, unreadable, and explicit-target cases. +- [ ] 4.2 Target new change using explicit/nearest/sole-library selection; verify ambiguous parent directories write nothing and duplicate names in other selected-out libraries do not block creation. +- [ ] 4.3 Add library targeting to update and schema init/fork while preserving existing options and positional paths; verify generated files and schemas change only inside the selected project. +- [ ] 4.4 Support explicit library selection in init/experimental while retaining existing cwd/new-project setup behavior; verify explicit new paths work and integrations are never initialized across all descendants. +- [ ] 4.5 Update mutation/setup help, completions, documentation, and a patch changeset; verify copyable examples and no required configuration or registration for default reads. + +## 5. Integration verification and review artifacts + +- [ ] 5.1 Run build, complete tests, TypeScript, lint, and strict change validation against one unchanged build; record results and confirm all command-matrix adapters are covered. +- [ ] 5.2 Verify Windows CI for native separators, canonical identity, junction/symlink exclusions, and command hints; record the passing workflow or exact remaining platform blocker. +- [ ] 5.3 Exercise list/view/show/validate/status/instructions/archive/init/update/schema flows on a temporary split repository; verify mutation targets and sibling artifact hashes end to end. +- [ ] 5.4 Capture actual source-built view and read/validation output from fictional fixtures, publish screenshots outside the code diff, and open an implementation draft PR linked to the approved proposal.