diff --git a/.agents/skills/devspec-codebase-structure.md b/.agents/skills/devspec-codebase-structure.md index 785fd7b..19ab054 100644 --- a/.agents/skills/devspec-codebase-structure.md +++ b/.agents/skills/devspec-codebase-structure.md @@ -1,5 +1,5 @@ --- name: devspec-codebase-structure -description: Capture owned source roots, module boundaries, integrations, and repository access. +description: Capture or customize owned source roots, repository layouts, module boundaries, integrations, and repository access. --- Read and execute `devspec/contracts/devspec.codebase-structure.md`. diff --git a/.agents/skills/devspec-coding-standards.md b/.agents/skills/devspec-coding-standards.md index c23ee48..50c5269 100644 --- a/.agents/skills/devspec-coding-standards.md +++ b/.agents/skills/devspec-coding-standards.md @@ -1,5 +1,5 @@ --- name: devspec-coding-standards -description: Capture reusable observed or developer-defined coding standards with numbered examples. +description: Capture concise, reusable coding conventions, followable examples, and anti-patterns from source evidence or developer-defined standards. --- Read and execute `devspec/contracts/devspec.coding-standards.md`. diff --git a/.agents/skills/devspec-extract.md b/.agents/skills/devspec-extract.md index 6552a6a..e2c7fe6 100644 --- a/.agents/skills/devspec-extract.md +++ b/.agents/skills/devspec-extract.md @@ -1,5 +1,5 @@ --- name: devspec-extract -description: Backfill concise foundation evidence from an existing repository. +description: Inspect the approved existing system end-to-end, produce its technical, business, workflow, and rule baseline, and prepare an evidence-backed diagram candidate list for explicit generation approval. --- Read and execute `devspec/contracts/devspec.extract.md`. diff --git a/.agents/skills/devspec-grooming.md b/.agents/skills/devspec-grooming.md index 01194b9..d729cad 100644 --- a/.agents/skills/devspec-grooming.md +++ b/.agents/skills/devspec-grooming.md @@ -1,5 +1,5 @@ --- name: devspec-grooming -description: Make one draft story buildable through scoped review and targeted questions. +description: Make one draft story buildable through scoped review and material questions. --- Read and execute `devspec/contracts/devspec.grooming.md`. diff --git a/.claude/skills/devspec-codebase-structure/SKILL.md b/.claude/skills/devspec-codebase-structure/SKILL.md index 785fd7b..19ab054 100644 --- a/.claude/skills/devspec-codebase-structure/SKILL.md +++ b/.claude/skills/devspec-codebase-structure/SKILL.md @@ -1,5 +1,5 @@ --- name: devspec-codebase-structure -description: Capture owned source roots, module boundaries, integrations, and repository access. +description: Capture or customize owned source roots, repository layouts, module boundaries, integrations, and repository access. --- Read and execute `devspec/contracts/devspec.codebase-structure.md`. diff --git a/.claude/skills/devspec-coding-standards/SKILL.md b/.claude/skills/devspec-coding-standards/SKILL.md index b66bbe2..50c5269 100644 --- a/.claude/skills/devspec-coding-standards/SKILL.md +++ b/.claude/skills/devspec-coding-standards/SKILL.md @@ -1,5 +1,5 @@ --- name: devspec-coding-standards -description: Capture short, evidence-backed conventions and anti-patterns. +description: Capture concise, reusable coding conventions, followable examples, and anti-patterns from source evidence or developer-defined standards. --- Read and execute `devspec/contracts/devspec.coding-standards.md`. diff --git a/.claude/skills/devspec-extract/SKILL.md b/.claude/skills/devspec-extract/SKILL.md index ea65694..e2c7fe6 100644 --- a/.claude/skills/devspec-extract/SKILL.md +++ b/.claude/skills/devspec-extract/SKILL.md @@ -1,5 +1,5 @@ --- name: devspec-extract -description: Inspect the approved existing system end-to-end and produce its technical, business, workflow, rule, and diagram baseline without requiring separate foundation or diagram commands. +description: Inspect the approved existing system end-to-end, produce its technical, business, workflow, and rule baseline, and prepare an evidence-backed diagram candidate list for explicit generation approval. --- Read and execute `devspec/contracts/devspec.extract.md`. diff --git a/.cursor/rules/devspec-workflow.mdc b/.cursor/rules/devspec-workflow.mdc index 68236b8..f0fa80b 100644 --- a/.cursor/rules/devspec-workflow.mdc +++ b/.cursor/rules/devspec-workflow.mdc @@ -2,4 +2,4 @@ description: Devspec Lite workflow alwaysApply: false --- -For `devspec.changerequest`, `devspec.clarify`, `devspec.codebase-structure`, `devspec.coding-standards`, `devspec.diagram`, `devspec.extract`, `devspec.finalize`, `devspec.grooming`, `devspec.implement`, `devspec.projectcontext`, `devspec.quickfix`, `devspec.review`, `devspec.rules`, `devspec.story`, `devspec.tasks`, `devspec.techstack`, read the matching `devspec/contracts/` file and listed protocols. For a clear continuation, resolve per-worktree current context and run only the saved next action; ask before switching stories. +For `devspec.extract`, `devspec.projectcontext`, `devspec.techstack`, `devspec.codebase-structure`, `devspec.coding-standards`, `devspec.rules`, `devspec.story`, `devspec.grooming`, `devspec.clarify`, `devspec.changerequest`, `devspec.finalize`, `devspec.tasks`, `devspec.implement`, `devspec.review`, `devspec.diagram`, `devspec.quickfix`, read the matching `devspec/contracts/` file and listed protocols. For a clear continuation, resolve per-worktree current context and run only the saved next action; ask before switching stories. diff --git a/.gemini/commands/devspec/codebase-structure.toml b/.gemini/commands/devspec/codebase-structure.toml index 6d67d8d..51c6168 100644 --- a/.gemini/commands/devspec/codebase-structure.toml +++ b/.gemini/commands/devspec/codebase-structure.toml @@ -1,2 +1,2 @@ -description = "Capture owned source roots, module boundaries, integrations, and repository access." +description = "Capture or customize owned source roots, repository layouts, module boundaries, integrations, and repository access." prompt = "Read and execute devspec/contracts/devspec.codebase-structure.md" diff --git a/.gemini/commands/devspec/coding-standards.toml b/.gemini/commands/devspec/coding-standards.toml index eb62300..ff86ac3 100644 --- a/.gemini/commands/devspec/coding-standards.toml +++ b/.gemini/commands/devspec/coding-standards.toml @@ -1,2 +1,2 @@ -description = "Capture short, evidence-backed conventions and anti-patterns." +description = "Capture concise, reusable coding conventions, followable examples, and anti-patterns from source evidence or developer-defined standards." prompt = "Read and execute devspec/contracts/devspec.coding-standards.md" diff --git a/.gemini/commands/devspec/extract.toml b/.gemini/commands/devspec/extract.toml index c49329e..b121a71 100644 --- a/.gemini/commands/devspec/extract.toml +++ b/.gemini/commands/devspec/extract.toml @@ -1,2 +1,2 @@ -description = "Inspect the approved existing system end-to-end and produce its technical, business, workflow, rule, and diagram baseline without requiring separate foundation or diagram commands." +description = "Inspect the approved existing system end-to-end, produce its technical, business, workflow, and rule baseline, and prepare an evidence-backed diagram candidate list for explicit generation approval." prompt = "Read and execute devspec/contracts/devspec.extract.md" diff --git a/.github/agents/devspec.codebase-structure.agent.md b/.github/agents/devspec.codebase-structure.agent.md index 043cc53..838c9f0 100644 --- a/.github/agents/devspec.codebase-structure.agent.md +++ b/.github/agents/devspec.codebase-structure.agent.md @@ -1,6 +1,6 @@ --- name: devspec.codebase-structure -description: Capture owned source roots, module boundaries, integrations, and repository access. +description: Capture or customize owned source roots, repository layouts, module boundaries, integrations, and repository access. user-invocable: true --- Execute `devspec/contracts/devspec.codebase-structure.md`. diff --git a/.github/agents/devspec.coding-standards.agent.md b/.github/agents/devspec.coding-standards.agent.md index ee8257b..861a28f 100644 --- a/.github/agents/devspec.coding-standards.agent.md +++ b/.github/agents/devspec.coding-standards.agent.md @@ -1,6 +1,6 @@ --- name: devspec.coding-standards -description: Capture short, evidence-backed conventions and anti-patterns. +description: Capture concise, reusable coding conventions, followable examples, and anti-patterns from source evidence or developer-defined standards. user-invocable: true --- Execute `devspec/contracts/devspec.coding-standards.md`. diff --git a/.github/agents/devspec.extract.agent.md b/.github/agents/devspec.extract.agent.md index d9417d8..6f089c1 100644 --- a/.github/agents/devspec.extract.agent.md +++ b/.github/agents/devspec.extract.agent.md @@ -1,6 +1,6 @@ --- name: devspec.extract -description: Backfill concise foundation evidence from an existing repository. +description: Inspect the approved existing system end-to-end, produce its technical, business, workflow, and rule baseline, and prepare an evidence-backed diagram candidate list for explicit generation approval. user-invocable: true --- Execute `devspec/contracts/devspec.extract.md`. diff --git a/README.md b/README.md index 8b216d1..d979fbd 100644 --- a/README.md +++ b/README.md @@ -12,10 +12,12 @@ Devspec Lite is a compact, resumable spec-driven workflow for AI coding agents. | macOS/Linux package-manager installation | [Homebrew](docs/setup-homebrew.md) | | Already installed the CLI; need init, upgrade, or profile changes | [CLI lifecycle](docs/setup-lifecycle.md) | -Manual copying and CLI installation produce the same canonical `devspec/` content and agent wrappers. In either route, set the target repository's `repository-state.md` to `new` or `existing`. Choose one setup route; the CLI is optional. +Manual copying and CLI installation produce the same canonical `devspec/` content and agent wrappers, once the manual route resets the project records listed in its guide. In either route, set the target repository's `repository-state.md` to `new` or `existing`. Choose one setup route; the CLI is optional. ## CLI quick start +The [CLI quick start](docs/quickstart.md) walks through initializing, validating, and choosing the first command. + After choosing a CLI route, initialize and validate the repository: ```powershell @@ -28,7 +30,7 @@ uvx devspec-lite init --target . --profile all --repo-state new uvx devspec-lite doctor --target . --profile all ``` -`init` copies canonical Markdown + XML contracts, concise templates, and the wrappers for the selected agent profile. Use the `devspec.*` commands exposed by your agent host. Use `devspec-lite diff --target .` to inspect installed-framework drift and `devspec-lite sync --target . --profile all --dry-run` before applying a framework upgrade. +`init` copies canonical Markdown + XML contracts, concise templates, and the wrappers for the selected agent profile. It generates `devspec/foundation/repository-state.md` from `--repo-state` and seeds empty `devspec/architecture/overview.md` and `artifact-queue.md` from their templates. Those two, plus `devspec/constitution.md`, are project-owned: `init` and `sync` never overwrite them, even with `--force`. Use the `devspec.*` commands exposed by your agent host. Use `devspec-lite diff --target .` to inspect installed-framework drift and `devspec-lite sync --target . --profile all --dry-run` before applying a framework upgrade. ## Choose a workflow route diff --git a/devspec/README.md b/devspec/README.md index 17684a7..164485f 100644 --- a/devspec/README.md +++ b/devspec/README.md @@ -1,10 +1,12 @@ # Devspec Lite -New repository foundation: `projectcontext → techstack → codebase-structure → coding-standards → rules`. Existing repository baseline: `extract` completes the foundation, prepares the applicable diagram list, and asks whether to generate all or selected diagrams. Rare durable cross-work-item principles live in `constitution.md`; `projectcontext` promotes or retires them only on explicit input. +New repository foundation: `projectcontext → techstack → codebase-structure → coding-standards → rules`. Existing repository baseline: `extract` completes the foundation, prepares the applicable diagram list, and asks whether to generate all or selected diagrams. Rare durable cross-work-item principles live in `constitution.md` with stable `CP-###` IDs. `extract` records candidates from evidence; `projectcontext` promotes or retires them only on explicit input. Work item: `story → grooming` when needed `→ finalize → tasks → implement → review`. Story intake accepts one manual request or, when an authenticated MCP connector is available, one read-only provider work-item reference. After `story` selects a work item, use the normal work-item commands without repeating its ID. Per-worktree private context resolves the selected story and its recorded `next` action; use an ID only to switch or disambiguate stories. Use `clarify` only for an active blocker and `quickfix` only for localized, low-risk changes. See `lifecycle.md` for all command transitions. +Each contract in `contracts/` states its own intent, scope, rules, and transitions, and loads the shared behavior it needs from `protocols/`: `state` for the run-state and evidence vocabulary, `run` for preflight and checkpoints, `work` for scope and change discipline, `ask` for material questions, `current-work-item` for ID-free continuation, `revision` for scope revisions, `repo-access` for repository boundaries, and `security` for the OWASP baseline. A rule belongs in a protocol when more than one command needs it. + `diagram` creates static SVG by default. Use `motion=explain` only for an evidence-backed sequence, flow, or state transition; animated output must retain complete static and reduced-motion meaning. diff --git a/devspec/architecture/_template/application-landscape-diagram.svg b/devspec/architecture/_template/application-landscape-diagram.svg new file mode 100644 index 0000000..07ee8e0 --- /dev/null +++ b/devspec/architecture/_template/application-landscape-diagram.svg @@ -0,0 +1,196 @@ + + [DIAGRAM_TITLE] - Application Landscape Diagram + [DIAGRAM_DESCRIPTION] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [PROJECT_NAME] + [DIAGRAM_TITLE] + [DIAGRAM_DESCRIPTION] + + + + + REST + + + + Batch + + + + Contract + + + + SaaS + + + + Sync + + + + Publish + + + + Consume + + + + [CAPABILITY_DOMAIN_A] + + + + + [CAPABILITY_DOMAIN_B] + + + + + [SHARED_PLATFORM] + + + + + + [App A1] + customer entry + Owner: [team] + + + + + + [App A2] + order handling + Owner: [team] + + + + + + [App A3] + reporting + Owner: [team] + + + + + + [App B1] + fulfilment + Owner: [team] + + + + + + [Vendor App] + bought capability + Owner: [vendor] + + + + + + [App B2] + settlement + Owner: [team] + + + + + + [Shared Service] + events / identity / integration + + + + + Legend + + Owned application + + Shared platform + + Vendor / SaaS + + Synchronous interface + + Event / async + + + Generated by devspec - [DATE_OR_VERSION] + diff --git a/devspec/architecture/_template/architecture-diagram.svg b/devspec/architecture/_template/architecture-diagram.svg index 5b5ae2a..4293945 100644 --- a/devspec/architecture/_template/architecture-diagram.svg +++ b/devspec/architecture/_template/architecture-diagram.svg @@ -1,5 +1,5 @@ - [DIAGRAM_TITLE] + [DIAGRAM_TITLE] - System Architecture Diagram [DIAGRAM_DESCRIPTION] @@ -84,7 +84,6 @@ - @@ -93,127 +92,129 @@ [DIAGRAM_TITLE] [DIAGRAM_DESCRIPTION] - - - + + + + 1 - - Sign in + + Sign in - - + + 2 - - Request + + Request - - + + 3 - - Calls + + Stores - - + + 4 - - Stores + + Enqueue - - + + 5 - - Events + + Calls - - [CLIENT_BOUNDARY] + + [CLIENT_BOUNDARY] - - [APPLICATION_BOUNDARY] + + [APPLICATION_BOUNDARY] - - [EXTERNAL_BOUNDARY] + + [EXTERNAL_BOUNDARY] - - [SECURITY_BOUNDARY] + + [SECURITY_BOUNDARY] - - - User Client - Actor Entry - Replace me + + + User Client + Actor Entry + Replace me - - - Security - Policy Checks - Replace me + + + Security + Policy Checks + Replace me - - - Core Service - Orchestration - Replace me + + + Core Service + Orchestration + Replace me - - - - Data Store - Owned Data - Replace me + + + + External API + Third Party + Replace me - - - - Worker - Async Flow - Replace me + + + + Data Store + Owned Data + Replace me - - - - External API - Third Party - Replace me + + + + Worker + Async Flow + Replace me - - + + Legend - - 1 - Numbered data or control flow - - Owned service - - Optional or async flow - - Boundary + + 1 + Numbered flow + + Owned service + + Optional or async flow + + Boundary Generated by devspec - [DATE_OR_VERSION] diff --git a/devspec/architecture/_template/artifact-queue.md b/devspec/architecture/_template/artifact-queue.md index 2aee793..b35a7ac 100644 --- a/devspec/architecture/_template/artifact-queue.md +++ b/devspec/architecture/_template/artifact-queue.md @@ -1,4 +1,6 @@ # Architecture Artifact Queue -| ID | Scope | Type | Subject | Output | Evidence | Status | Next | -|---|---|---|---|---|---|---|---| +One row per diagram candidate. `Duplicate check` records what was compared and the result, so a later run does not regenerate an existing diagram. `Next` is the one action left for that row, or `none` when it is complete. + +| ID | Scope | Type | Subject | Output | Evidence | Duplicate check | Status | Next | +|---|---|---|---|---|---|---|---|---| diff --git a/devspec/architecture/_template/diagram-sample.md b/devspec/architecture/_template/diagram-sample.md index 690a0a7..a955009 100644 --- a/devspec/architecture/_template/diagram-sample.md +++ b/devspec/architecture/_template/diagram-sample.md @@ -1,6 +1,8 @@ # Diagram Sample -Use this compact worked example as a pattern. Replace every value with repository evidence; queue state belongs only in artifact-queue.md. +Use this compact worked example as a pattern for the record. Replace every value with repository evidence; queue state belongs only in artifact-queue.md. + +The accompanying `diagram-sample.svg` is a completed worked example on the shared 1600 by 900 canvas, so it shows the visual contract a real diagram must meet. A real diagram still starts from the matching family template in this directory rather than from this sample. ## Brief @@ -19,9 +21,9 @@ A process flow makes the one routing decision, its two outcomes, and the durable ## Queue row -| ID | Scope | Type | Subject | Output | Evidence | Status | Next | -|---|---|---|---|---|---|---|---| -| DIA-001 | workflow | process flow | customer-request-routing | images/dia-001-customer-request-routing.svg | contracts above | complete | index in overview | +| ID | Scope | Type | Subject | Output | Evidence | Duplicate check | Status | Next | +|---|---|---|---|---|---|---|---|---| +| DIA-001 | workflow | Process flow | customer-request-routing | `devspec/architecture/diagrams/dia-001-customer-request-routing.svg` | contracts above | no existing diagram covers this subject | complete | index in overview | ## Completion diff --git a/devspec/architecture/_template/diagram-sample.svg b/devspec/architecture/_template/diagram-sample.svg index 46cea2a..1d5cd3e 100644 --- a/devspec/architecture/_template/diagram-sample.svg +++ b/devspec/architecture/_template/diagram-sample.svg @@ -1 +1,140 @@ -Customer request routing sampleA confirmed request is routed to a localized quickfix or to a traceable work item based on scope and risk.DEVSPEC LITE / PROCESS FLOW SAMPLECustomer request routingUse confirmed scope and risk to select one durable route.Requestconfirmed needLocal +low risk?quickfixfocused validationwork itemstory to reviewRecordevidence + nextYESNO / RISKEVIDENCE: QUICKFIX + STORY CONTRACTS • TYPE: PROCESS FLOW • STATUS: COMPLETE + + Customer request routing - Process Flow Sample + A confirmed request is routed to a localized quickfix or to a traceable work item based on scope and risk, and either route ends in one durable record. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DEVSPEC LITE / PROCESS FLOW SAMPLE + Customer request routing + Use confirmed scope and risk to select one durable route. + + + CONFIRMED ROUTE + + + + + + + YES + + + + NO / RISK + + + + + + + + Request + confirmed need + + + + + + Local + + low risk? + + + + + + quickfix + focused validation + + + + + + work item + story to review + + + + + + Record + evidence + next + + + + + Legend + + Entry + + Decision + + Quickfix route + + Work-item route + + + EVIDENCE: QUICKFIX + STORY CONTRACTS - TYPE: PROCESS FLOW - STATUS: COMPLETE + diff --git a/devspec/architecture/_template/diagram-types.md b/devspec/architecture/_template/diagram-types.md index af033a8..9bd63b8 100644 --- a/devspec/architecture/_template/diagram-types.md +++ b/devspec/architecture/_template/diagram-types.md @@ -30,7 +30,9 @@ Use the smallest diagram that makes a confirmed relationship easier to understan | Diagram type | SVG template | |---|---| -| System architecture, application landscape, infrastructure topology | `architecture-diagram.svg` | +| System architecture | `architecture-diagram.svg` | +| Application landscape | `application-landscape-diagram.svg` | +| Infrastructure topology | `infrastructure-topology-diagram.svg` | | Process flow | `process-flow-diagram.svg` | | Sequence | `sequence-diagram.svg` | | State lifecycle | `state-lifecycle-diagram.svg` | @@ -44,6 +46,10 @@ Use the smallest diagram that makes a confirmed relationship easier to understan Do not infer entities, callers, timelines, ownership, user sentiment, or priorities. Record uncertain information in the work item or decisions file, not as a factual diagram label. Keep a flowchart to one primary concern; split a diagram that cannot remain readable instead of shrinking text or crossing unrelated flows. +The journey template ships a signal row. Keep it only when a measured or user-confirmed signal supports every point; delete the row and its legend entry otherwise, because an unmeasured curve is inferred sentiment. + +Every connector must start on one shape edge and end on another. A line that begins or ends in open space, or whose arrowhead is hidden behind the shape it points at, states a relationship the diagram does not actually show. Keep label backgrounds clear of boundary strokes and other labels, and keep every colour that appears on a shape present in the legend. + ## Opt-in motion Use motion only for `motion=explain`, and only when an evidence-backed order or transition helps the reader understand the diagram. A plain request for an animated diagram selects this mode. Static SVG remains the default. diff --git a/devspec/architecture/_template/diagram.md b/devspec/architecture/_template/diagram.md index b927565..b8be2cc 100644 --- a/devspec/architecture/_template/diagram.md +++ b/devspec/architecture/_template/diagram.md @@ -1,33 +1,15 @@ # Architecture Diagram -Use this optional Markdown artifact for one durable Mermaid architecture, module, feature, workflow, process-flow, user journey, sequence, state, or domain diagram when the selected output set includes `mermaid`. SVG is the default diagram output and lives under `devspec/architecture/images/`; HTML is optional and lives under `devspec/architecture/html/`. Keep diagram status in `devspec/architecture/artifact-queue.md`; keep generated content references, supporting evidence, assumptions, and maintenance notes here when this Markdown artifact is created. +Use this optional Markdown artifact for one durable Mermaid architecture, module, feature, workflow, process-flow, user journey, sequence, state, or domain diagram when the selected output set includes `mermaid`. SVG is the default diagram output and lives under `devspec/architecture/diagrams/`; HTML is optional and lives under `devspec/architecture/diagrams/`. Keep diagram status in `devspec/architecture/artifact-queue.md`; keep generated content references, supporting evidence, assumptions, and maintenance notes here when this Markdown artifact is created. -## Resume State - -| Field | Value | -| --- | --- | -| Current stage | diagram | -| Current command | `/devspec.diagram` | -| Current agent | devspec.diagram | -| Run status | See `devspec/glossary.md#run-status-values` | -| Current item | | -| Last completed step | | -| Next required action | | -| Pending user question | | -| Question options and examples | | -| Custom Answer entry or response | | -| Recommended option and justification | | -| Continuation condition | | -| Resume command | `/devspec.diagram` | -| Resume notes | | -| Updated | | +This record holds evidence and maintenance notes only. Queue status lives in `devspec/architecture/artifact-queue.md`, and any material question belongs in the caller's decision record; a diagram never holds workflow run state. ## Diagram Metadata | Field | Value | | --- | --- | | ID | | -| Display title | `DIA-NNN - ` | +| Display title | `DIA-### - ` | | Scope | architecture, module, feature, workflow, user-journey | | Diagram type | flowchart, sequenceDiagram, journey, stateDiagram, classDiagram, erDiagram, gantt, quadrantChart, mindmap, timeline | | Audience | developers, architects, security reviewers, operators, stakeholders, or user-provided audience | @@ -35,19 +17,19 @@ Use this optional Markdown artifact for one durable Mermaid architecture, module | Architecture style | monolith, microservices, event-driven, serverless, agentic workflow, multi-repo, cloud-native, or user-provided style | | Output format | mermaid, svg+mermaid, html+mermaid, or svg+html+mermaid | | Mermaid declaration | flowchart TD, flowchart LR, flowchart BT, sequenceDiagram, journey, stateDiagram-v2, classDiagram, erDiagram, gantt, quadrantChart, mindmap, timeline | -| SVG target | `devspec/architecture/images/dia-NNN-<diagram-name>.svg` when output format includes svg | -| HTML target | `devspec/architecture/html/dia-NNN-<diagram-name>.html` when output format includes html | -| Subject | `dia-NNN-<diagram-name>` | +| SVG target | `devspec/architecture/diagrams/dia-###-<diagram-name>.svg` when output format includes svg | +| HTML target | `devspec/architecture/diagrams/dia-###-<diagram-name>.html` when output format includes html | +| Subject | `dia-###-<diagram-name>` | | Confidence | observed, high-confidence, low-confidence | | Tags | | -| Queue row | `devspec/architecture/artifact-queue.md#diagram-queue-register` | +| Queue row | `devspec/architecture/artifact-queue.md` | When a request uses the structured architecture-diagram prompt format and the selected output set includes `mermaid`, reflect the provided system name, architecture style, purpose, audience, actors, components, stores, flows, boundaries, design rules, and output format in this metadata, the queue row notes, source evidence and assumptions, and generated diagram content. If the request uses structured non-architecture diagram input, reflect the matching sequence, state/lifecycle, domain model, journey, timeline/gantt, quadrant, or mindmap fields in this metadata, the queue row notes, source evidence and assumptions, generated Mermaid content, and any SVG or HTML companion output. If the request omits output format, use SVG-only output and do not create this Markdown artifact. ## Mermaid Diagram - Include this section only when the selected output set includes `mermaid`. SVG-only and HTML-only output should not create this Markdown artifact. -- Keep durable `DIA-*` IDs and `dia-NNN-*` subjects in metadata and filenames only; Mermaid content uses simple internal naming. +- Keep durable `DIA-*` IDs and `dia-###-*` subjects in metadata and filenames only; Mermaid content uses simple internal naming. - Use short alphanumeric node IDs, double-quoted node labels of 1-4 words, and 2-3 word edge labels. Do not use `\n` or `<br>` inside node labels or edge labels. - Keep architectural flowcharts focused on one primary domain at macro level, structurally unidirectional, and adjacent by layer. Do not include overloaded graphs, cross-layer arrows, decision diamonds, UI micro-interactions, or return/error paths unless the diagram is explicitly an algorithm or activity flowchart. - Use `sequenceDiagram` for exact step-by-step request and response behavior. Sequence diagrams should show happy-path messages between distinct participants, collapse pass-through API client helpers, and use method names for message labels. @@ -101,9 +83,9 @@ flowchart TD ## Companion Outputs - Use this section when `Output format` includes `svg` or `html`. -- Store the durable SVG at `devspec/architecture/images/dia-NNN-<diagram-name>.svg`. -- Store optional standalone HTML at `devspec/architecture/html/dia-NNN-<diagram-name>.html`. -- Select SVG templates from `.github/prompts/PATTERNS.md#svg-output-pattern`: `architecture-diagram.svg`, `process-flow-diagram.svg`, `sequence-diagram.svg`, `state-lifecycle-diagram.svg`, `domain-model-diagram.svg`, `journey-map-diagram.svg`, `timeline-plan-diagram.svg`, `quadrant-analysis-diagram.svg`, or `mindmap-diagram.svg`. Every template must preserve the shared dark architecture-style visual contract unless a documented constraint requires a smaller custom SVG. +- Store the durable SVG at `devspec/architecture/diagrams/dia-###-<diagram-name>.svg`. +- Store optional standalone HTML at `devspec/architecture/diagrams/dia-###-<diagram-name>.html`. +- Select SVG templates from `devspec/architecture/_template/`: `architecture-diagram.svg`, `application-landscape-diagram.svg`, `infrastructure-topology-diagram.svg`, `process-flow-diagram.svg`, `sequence-diagram.svg`, `state-lifecycle-diagram.svg`, `domain-model-diagram.svg`, `journey-map-diagram.svg`, `timeline-plan-diagram.svg`, `quadrant-analysis-diagram.svg`, or `mindmap-diagram.svg`. Every template must preserve the shared dark architecture-style visual contract unless a documented constraint requires a smaller custom SVG. - Generated SVG must be standalone XML with inline styles and no external assets, `<script>`, `<iframe>`, `<foreignObject>`, remote fonts, remote images, secrets, credentials, internal-only URLs, or unresolved placeholders. - Generated HTML must be standalone static HTML with inline styles and no external assets, `<script>`, `<iframe>`, remote fonts, remote images, secrets, credentials, internal-only URLs, or unresolved placeholders. - Validate the SVG as XML before reporting generation complete. diff --git a/devspec/architecture/_template/domain-model-diagram.svg b/devspec/architecture/_template/domain-model-diagram.svg index c7bfa13..86e37aa 100644 --- a/devspec/architecture/_template/domain-model-diagram.svg +++ b/devspec/architecture/_template/domain-model-diagram.svg @@ -85,10 +85,10 @@ <path class="relation" d="M 955 400 C 1060 400, 1140 400, 1245 400" marker-end="url(#arrow)"/> <text class="cardinality" x="982" y="388">1</text> <text class="cardinality" x="1210" y="388">*</text> - <rect class="relation-label-bg" x="1080" y="388" width="84" height="24" rx="7"/> - <text class="relation-label" x="1122" y="405" text-anchor="middle">Uses</text> + <rect class="relation-label-bg" x="1010" y="388" width="84" height="24" rx="7"/> + <text class="relation-label" x="1052" y="405" text-anchor="middle">Uses</text> - <path class="relation relation-secondary" d="M 830 550 C 830 625, 830 655, 830 730" marker-end="url(#arrow-secondary)"/> + <path class="relation relation-secondary" d="M 830 470 C 830 560, 830 640, 830 730" marker-end="url(#arrow-secondary)"/> <rect class="relation-label-bg" x="852" y="632" width="94" height="24" rx="7"/> <text class="relation-label" x="899" y="649" text-anchor="middle">Stores</text> diff --git a/devspec/architecture/_template/infrastructure-topology-diagram.svg b/devspec/architecture/_template/infrastructure-topology-diagram.svg new file mode 100644 index 0000000..24d22c9 --- /dev/null +++ b/devspec/architecture/_template/infrastructure-topology-diagram.svg @@ -0,0 +1,193 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 900" role="img" aria-labelledby="title desc"> + <title id="title">[DIAGRAM_TITLE] - Infrastructure Topology Diagram + [DIAGRAM_DESCRIPTION] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [PROJECT_NAME] + [DIAGRAM_TITLE] + [DIAGRAM_DESCRIPTION] + + + + [ENVIRONMENT_PRIMARY] + + + + + [ENVIRONMENT_SECONDARY] + + + + + [PROVIDER_OR_REGION] + + + + + [EXTERNAL_DEPENDENCY] + + + + + [PROVIDER_OR_REGION] + + + + + + HTTPS + + + + TLS + + + + Egress + + + + Replication + + + + TLS + + + + + Edge + Ingress / DNS + Replace me + + + + + + Runtime Host + Compute + Replace me + + + + + + Managed Data + Primary store + Replace me + + + + + + Third-Party API + Outside control + Replace me + + + + + + Standby Host + Compute + Replace me + + + + + + Replica Data + Read replica + Replace me + + + + + Legend + + Edge + + Compute + + Managed data + + External + + Network path + + Replication + + + Generated by devspec - [DATE_OR_VERSION] + diff --git a/devspec/architecture/_template/journey-map-diagram.svg b/devspec/architecture/_template/journey-map-diagram.svg index cd4473e..e9a7fd6 100644 --- a/devspec/architecture/_template/journey-map-diagram.svg +++ b/devspec/architecture/_template/journey-map-diagram.svg @@ -76,6 +76,7 @@ ACTOR SYSTEM OUTCOME + SIGNAL @@ -105,7 +106,7 @@ - + @@ -160,15 +161,15 @@ - - + + Legend Actor action - - System action - - Experience signal + + System action + + Experience signal Generated by devspec - [DATE_OR_VERSION] diff --git a/devspec/architecture/_template/mindmap-diagram.svg b/devspec/architecture/_template/mindmap-diagram.svg index 78c5f63..4a18c2c 100644 --- a/devspec/architecture/_template/mindmap-diagram.svg +++ b/devspec/architecture/_template/mindmap-diagram.svg @@ -75,21 +75,21 @@ [DIAGRAM_DESCRIPTION] - - - - - - + + + + + + - - [CAPABILITY_GROUP_A] + + [CAPABILITY_GROUP_A] - - [CAPABILITY_GROUP_B] + + [CAPABILITY_GROUP_B] diff --git a/devspec/architecture/_template/process-flow-diagram.svg b/devspec/architecture/_template/process-flow-diagram.svg index f31c0e8..f071db7 100644 --- a/devspec/architecture/_template/process-flow-diagram.svg +++ b/devspec/architecture/_template/process-flow-diagram.svg @@ -198,28 +198,28 @@ validate + process - + Decision? Yes / No - + - 4 + 3 API Integration external handoff - + - 5 + 4 SYSTEM Finalize notify + record diff --git a/devspec/architecture/_template/quadrant-analysis-diagram.svg b/devspec/architecture/_template/quadrant-analysis-diagram.svg index ffc812c..a91a277 100644 --- a/devspec/architecture/_template/quadrant-analysis-diagram.svg +++ b/devspec/architecture/_template/quadrant-analysis-diagram.svg @@ -112,14 +112,16 @@ - + Legend Priority item Risk item - - Exploratory item + + Deferred item + + Exploratory item Generated by devspec - [DATE_OR_VERSION] diff --git a/devspec/architecture/_template/state-lifecycle-diagram.svg b/devspec/architecture/_template/state-lifecycle-diagram.svg index 706e55c..ce5bb59 100644 --- a/devspec/architecture/_template/state-lifecycle-diagram.svg +++ b/devspec/architecture/_template/state-lifecycle-diagram.svg @@ -91,8 +91,8 @@ - - [EXCEPTION_STATE] + + [EXCEPTION_STATE] @@ -109,13 +109,13 @@ Approve - - - Reject + + + Reject - - - Revise + + + Revise @@ -152,23 +152,23 @@ - - - Rework - Resolve issues + + + Rework + Resolve issues - + Legend Normal state - - Exception + + Exception Return or terminal flow - - Rejected transition + + Rejected transition Generated by devspec - [DATE_OR_VERSION] diff --git a/devspec/architecture/_template/timeline-plan-diagram.svg b/devspec/architecture/_template/timeline-plan-diagram.svg index 4923d1f..09caebe 100644 --- a/devspec/architecture/_template/timeline-plan-diagram.svg +++ b/devspec/architecture/_template/timeline-plan-diagram.svg @@ -63,7 +63,6 @@ - @@ -73,84 +72,92 @@ [DIAGRAM_DESCRIPTION] - - PLANNING + + PLANNING - - BUILD + + BUILD - - VALIDATE + + VALIDATE - - RELEASE + + RELEASE - - - + + + [T1] - + [T2] - + [T3] - + [T4] - - - Depends - - - Risk + + + + Depends + + + + Risk - - - Plan Ready - [date / sprint] + + + Plan Ready + [owner / deliverable] - - - Build Done - [date / sprint] + + + Build Done + [owner / deliverable] - - - Validation Gate - [date / sprint] + + + Validation Gate + [owner / deliverable] - - - Release - [date / sprint] + + + Release + [owner / deliverable] - - + + Legend - - Milestone - - Gate / risk - - Dependency + + Planned + + Delivered + + Gate / risk + + Release + + Dependency (source first) + + Risk link Generated by devspec - [DATE_OR_VERSION] diff --git a/devspec/architecture/artifact-queue.md b/devspec/architecture/artifact-queue.md index 76b0da9..cf2cb3d 100644 --- a/devspec/architecture/artifact-queue.md +++ b/devspec/architecture/artifact-queue.md @@ -1,7 +1,9 @@ # Architecture Artifact Queue -| ID | Scope | Type | Subject | Output | Evidence | Status | Next | -|---|---|---|---|---|---|---|---| -| DOC-001 | workflow | flowchart | foundation-route | `docs/assets/foundation-routes.svg` | command registry, repository state | complete | none | -| DOC-002 | workflow | flowchart | delivery-route | `docs/assets/delivery-routes.svg` | command contracts, protocols | complete | none | -| DOC-003 | workflow | flowchart | install-lifecycle | `docs/assets/maintenance-flow.svg` | CLI, Doctor, setup guides | complete | none | +| ID | Scope | Type | Subject | Output | Evidence | Duplicate check | Status | Next | +|---|---|---|---|---|---|---|---|---| +| DIA-001 | workflow | Process flow | foundation-route | `docs/assets/foundation-routes.svg` | command registry, repository state | none | complete | none | +| DIA-002 | workflow | Process flow | delivery-route | `docs/assets/delivery-routes.svg` | command contracts, protocols | none | complete | none | +| DIA-003 | workflow | Process flow | install-lifecycle | `docs/assets/maintenance-flow.svg` | CLI, doctor, setup guides | none | complete | none | +| DIA-004 | workflow | Process flow | manual-copy-route | `docs/assets/manual-copy-flow.svg` | manual copy guide, install manifest | none | complete | none | +| DIA-005 | workflow | Process flow | diagram-route | `docs/assets/diagram-route.svg` | diagram contract, clarify transition | none | complete | none | diff --git a/devspec/architecture/overview.md b/devspec/architecture/overview.md index 32d32b5..3a59efa 100644 --- a/devspec/architecture/overview.md +++ b/devspec/architecture/overview.md @@ -4,11 +4,14 @@ - Scope: developer workflow and setup guidance, not product runtime architecture. - Sources: command contracts, protocols, CLI behavior, and setup documentation. - Constraint: diagrams show confirmed routes only; they do not infer application dependencies. +- Deviation: these four are wide documentation banners sized to the guides that embed them, not the 1600 by 900 canvas `_template/diagram-types.md` requires for a family template. They keep the dark grammar, titles, descriptions, and evidence rules. A diagram generated by `devspec.diagram` uses the family template and its canvas. ## Diagram index | ID | Diagram | Scope | Evidence | Link | |---|---|---|---|---| -| DOC-001 | Foundation route | workflow | command registry, repository state | `docs/assets/foundation-routes.svg` | -| DOC-002 | Delivery route | workflow | command contracts, protocols | `docs/assets/delivery-routes.svg` | -| DOC-003 | Install lifecycle | workflow | CLI, Doctor, setup guides | `docs/assets/maintenance-flow.svg` | +| DIA-001 | Foundation route | workflow | command registry, repository state | `docs/assets/foundation-routes.svg` | +| DIA-002 | Delivery route | workflow | command contracts, protocols | `docs/assets/delivery-routes.svg` | +| DIA-003 | Install lifecycle | workflow | CLI, doctor, setup guides | `docs/assets/maintenance-flow.svg` | +| DIA-004 | Manual copy route | workflow | manual copy guide, install manifest | `docs/assets/manual-copy-flow.svg` | +| DIA-005 | Diagram route | workflow | diagram contract, clarify transition | `docs/assets/diagram-route.svg` | diff --git a/devspec/command-registry.md b/devspec/command-registry.md index 24175a1..e3df55d 100644 --- a/devspec/command-registry.md +++ b/devspec/command-registry.md @@ -1,22 +1,24 @@ # Command Registry +Purpose and next route are the contract's own `` and `` values. Change the contract, not this table. + | Command | Purpose | Next route | |---|---|---| -| `devspec.extract` | Build the complete evidence-backed baseline for an existing scoped system, prepare the applicable diagram list, then obtain explicit all-or-selected generation approval. | `devspec.story` or `devspec.clarify` | -| `devspec.projectcontext` | Capture product purpose, users, outcomes, and scope boundaries. | `techstack` | -| `devspec.techstack` | Capture evidence-backed runtime, frameworks, data, tooling, and delivery constraints. | `codebase-structure` | -| `devspec.codebase-structure` | Capture or customize owned roots, representative repository layout trees, boundaries, integrations, and access. | `coding-standards` | -| `devspec.coding-standards` | Capture or update reusable observed or developer-defined standards with linked numbered code examples and anti-patterns. | `rules` | -| `devspec.rules` | Capture non-negotiable engineering, security, compliance, delivery, and accessibility rules. | `story` | -| `devspec.story` | Create one concise work-item intake from a request or provider reference. | `devspec.grooming` or `devspec.finalize` | -| `devspec.grooming` | Make one draft story buildable through scoped review and material questions. | `devspec.clarify` or `devspec.finalize` | -| `devspec.clarify` | Resolve one active blocker and resume its originating command. | `resume-origin` | -| `devspec.changerequest` | Append one related post-finalization requirement without rewriting history. | `finalize` | -| `devspec.finalize` | Produce a concise readiness brief and validation plan. | `devspec.clarify` or `devspec.tasks` | -| `devspec.tasks` | Create ordered, independently verifiable implementation tasks. | `implement` | -| `devspec.implement` | Implement pending ready tasks with focused checkpoints and validation. | `review` | -| `devspec.review` | Review changed work, record an outcome, and set one next action. | `devspec.implement`, `devspec.clarify`, or terminal | -| `devspec.diagram` | Create one targeted evidence-backed diagram with duplicate checks and durable queue state. | return to caller | -| `devspec.quickfix` | Implement and validate one localized, low-risk enhancement or bug fix. | terminal, `devspec.clarify`, or `devspec.story` | +| `devspec.extract` | Inspect the approved existing system end-to-end, produce its technical, business, workflow, and rule baseline, and prepare an evidence-backed diagram candidate list for explicit generation approval. | `devspec.story`, `devspec.clarify` | +| `devspec.projectcontext` | Capture product purpose, users, outcomes, and scope boundaries. | `devspec.techstack`, `return-to-caller`, `devspec.clarify` | +| `devspec.techstack` | Capture evidence-backed runtime, frameworks, data, tooling, and delivery constraints. | `devspec.codebase-structure`, `return-to-caller`, `devspec.clarify` | +| `devspec.codebase-structure` | Capture or customize owned source roots, repository layouts, module boundaries, integrations, and repository access. | `devspec.coding-standards`, `return-to-caller`, `devspec.clarify` | +| `devspec.coding-standards` | Capture concise, reusable coding conventions, followable examples, and anti-patterns from source evidence or developer-defined standards. | `devspec.rules`, `return-to-caller`, `devspec.clarify` | +| `devspec.rules` | Capture non-negotiable engineering, security, compliance, delivery, and accessibility rules. | `devspec.story`, `return-to-caller`, `devspec.clarify` | +| `devspec.story` | Create one concise work-item intake from a request or provider reference. | `devspec.grooming`, `devspec.finalize`, `devspec.clarify` | +| `devspec.grooming` | Make one draft story buildable through scoped review and material questions. | `devspec.finalize`, `devspec.clarify` | +| `devspec.clarify` | Resolve one active blocker and resume its originating stage. | `resume-origin` | +| `devspec.changerequest` | Append one related post-finalization requirement without rewriting history. | `devspec.finalize`, `devspec.clarify` | +| `devspec.finalize` | Produce a concise readiness brief and validation plan. | `devspec.tasks`, `devspec.clarify` | +| `devspec.tasks` | Create ordered, independently verifiable implementation tasks. | `devspec.implement`, `devspec.clarify` | +| `devspec.implement` | Implement pending ready tasks with focused checkpoints and validation. | `devspec.review`, `devspec.clarify` | +| `devspec.review` | Review changed work against readiness, tasks, and validation evidence. | `none`, `devspec.implement`, `devspec.clarify` | +| `devspec.diagram` | Create one evidence-backed diagram with duplicate checks and durable queue state. | `return-to-caller`, `devspec.clarify` | +| `devspec.quickfix` | Implement and validate one localized, low-risk enhancement or bug fix. | `none`, `devspec.clarify`, `devspec.story` | -Work-item IDs are optional for `grooming`, `finalize`, `tasks`, `implement`, `review`, `clarify`, and `changerequest`. Without an ID, resolve the private per-worktree current context and run only the work item's recorded `next` action. Use an explicit ID to switch stories; when several eligible stories exist, ask the user to choose. +Work-item IDs are optional for `grooming`, `finalize`, `tasks`, `implement`, `review`, `clarify`, and `changerequest`. Without an ID, resolve the private per-worktree current context and run only the work item's recorded `next` action. Use an explicit ID to switch stories; when several eligible work items exist, ask the developer to choose. diff --git a/devspec/contracts/devspec.changerequest.md b/devspec/contracts/devspec.changerequest.md index d45c969..4eaf549 100644 --- a/devspec/contracts/devspec.changerequest.md +++ b/devspec/contracts/devspec.changerequest.md @@ -9,9 +9,12 @@ Invocation: `/devspec.changerequest [work-item-id] Add JSON export` + + + Use only for a requirement related to a work item that is already finalized. Use devspec.story for independent scope, and edit the story directly while it is still before finalization. An optional work-item ID and one related missing requirement. Append the next CR-### entry and CR-scoped criteria; never rewrite baseline evidence. @@ -21,13 +24,11 @@ Invocation: `/devspec.changerequest [work-item-id] Add JSON export` + - Append the CR, increment scope_revision, mark downstream records superseded, and preserve their historical evidence. - Classify scope as related or independent; append the next CR identifier when related. - devspec/work-items/<id>/story.md - finalize + Append the CR and record the classification that justified it. diff --git a/devspec/contracts/devspec.clarify.md b/devspec/contracts/devspec.clarify.md index 93197b7..108489a 100644 --- a/devspec/contracts/devspec.clarify.md +++ b/devspec/contracts/devspec.clarify.md @@ -8,9 +8,13 @@ Invocation: `/devspec.clarify [work-item-id]` Resolve one active blocker and resume its originating stage. - + + + + + Use only to resolve one recorded material blocker and resume the command that recorded it. This command never advances a stage, changes scope, or answers a question its originating command has not recorded. An optional work-item ID, or one foundation or quickfix record, with one active material blocker question. Resolve the one highest-priority material decision in its active queue and append its answer to decisions.md. For a work item, append the origin command, question, resolution, evidence, and exact resume command to clarify.md. @@ -23,12 +27,10 @@ Invocation: `/devspec.clarify [work-item-id]` + Append the resolution, restore the exact saved stage and next command, and do not change scope while resolving a blocker. - Ask the recorded high-priority material question, append the resolution, and return to the saved next action. - devspec/work-items/<id>/decisions.md - resume-origin diff --git a/devspec/contracts/devspec.codebase-structure.md b/devspec/contracts/devspec.codebase-structure.md index 849d8ee..8aeb301 100644 --- a/devspec/contracts/devspec.codebase-structure.md +++ b/devspec/contracts/devspec.codebase-structure.md @@ -9,6 +9,7 @@ Invocation: `/devspec.codebase-structure` + @@ -18,18 +19,17 @@ Invocation: `/devspec.codebase-structure` Map owned source roots, boundaries, integration points, and validation locations. For each repository, maintain a readable `text` layout tree rooted at its recorded local path. Include solution or manifest files, owned roots, meaningful modules, configuration, and integration or migration locations; keep it representative rather than exhaustive and exclude dependencies, caches, generated output, and secrets. For an explicit targeted update, accept a developer-provided layout tree or structure change without rerunning extraction. Mark developer-defined additions or changes as such, retain observed evidence where it remains accurate, and reconcile the repository table, layout tree, and area map. - Use repo-access whenever scope or access evidence is missing and when work crosses repositories. Record one named least-privilege access requirement per repository; never infer access from its path. + Reconcile the repository table with the access requirements repo-access recorded; never infer access from a repository path. Completed technology stack in the new foundation chain, or an explicit targeted update; reject an existing-system baseline request. + + - Record repository access boundaries, representative layout trees, and one registered next command; blocked evidence routes to devspec.clarify. - Map or customize owned areas, then record repository paths, roles, named access requirements, and layout origins before relying on them. - devspec/foundation/codebase-structure.md - coding-standards + Record repository access boundaries, representative layout trees, and one registered next command. diff --git a/devspec/contracts/devspec.coding-standards.md b/devspec/contracts/devspec.coding-standards.md index c3041b5..10f08f9 100644 --- a/devspec/contracts/devspec.coding-standards.md +++ b/devspec/contracts/devspec.coding-standards.md @@ -1,6 +1,6 @@ # devspec.coding-standards -Capture concise, reusable coding conventions, examples, and anti-patterns. +Capture concise, reusable coding conventions, followable examples, and anti-patterns from source evidence or developer-defined standards. Invocation: `/devspec.coding-standards` @@ -9,26 +9,27 @@ Invocation: `/devspec.coding-standards` + + Use for new-repository foundation authoring or an explicitly requested targeted update. Use devspec.extract, not this command, to establish an existing-system baseline. Observed conventions, approved standards, or developer-defined custom standards with followable numbered examples or example updates. Keep only conventions that change implementation or review behavior. For an observed convention, assign a stable `CS-###` ID, cite its local source evidence, and record concise fenced code or test snippets as linked `EX-###` entries under `## Standards Examples`. Record an anti-pattern when repository evidence supports one. - Accept a custom standard explicitly supplied or approved by a developer even when no local source example exists. Mark it developer-defined rather than observed, record its approval or request as evidence, assign or retain a stable `CS-###` ID, and include a concise illustrative `EX-###` entry for future implementations. For a developer-defined example, identify its source as the user or developer directive and date. + Accept a custom standard explicitly supplied or approved by a developer even when no local source example exists. Mark it developer-defined rather than observed, record its approval or request as evidence, assign or retain a stable `CS-###` ID, and include a concise illustrative `EX-###` entry for future implementations. For a developer-defined example, identify its source as the developer directive and date. For an explicit targeted update, accept added, replaced, or retired standards examples without rerunning extraction. Preserve existing `CS-###` and `EX-###` IDs, create new IDs without renumbering historical entries, and reconcile each standard's linked example IDs and origin. Completed codebase structure in the new foundation chain, or an explicit targeted update; reject an existing-system baseline request. + + - Record each retained standard with its stable ID, origin, linked numbered examples, and an anti-pattern when applicable, then register one next command; blocked evidence routes to devspec.clarify. - Record only standards that change a developer action, preserving developer-defined numbered examples as reusable implementation guidance. - devspec/foundation/coding-standards.md - rules + Record each retained standard with its stable ID, origin, linked numbered examples, and an anti-pattern when applicable and register one next command. diff --git a/devspec/contracts/devspec.diagram.md b/devspec/contracts/devspec.diagram.md index 797f956..c18bc49 100644 --- a/devspec/contracts/devspec.diagram.md +++ b/devspec/contracts/devspec.diagram.md @@ -9,22 +9,25 @@ Invocation: `/devspec.diagram runtime architecture format=svg motion=none|explai + Use for one targeted diagram in the current approved context. An explicit process-flow batch request may generate every queued, non-duplicate process-flow candidate; devspec.extract otherwise owns existing-system diagram discovery, candidate listing, and all-or-selected generation approval. Diagram queue ID, subject, work item, explicit process-flow batch request, format request, or optional `motion=none|explain` in the current repository or an explicitly scoped multi-repository system. - Select the diagram type from devspec/architecture/_template/diagram-types.md; load only the needed pattern. - Start each SVG from the matching family-specific template: `architecture-diagram.svg` for system architecture, application landscape, and infrastructure topology; `process-flow-diagram.svg` for process flows; `sequence-diagram.svg` for interactions; `state-lifecycle-diagram.svg` for state behavior; `domain-model-diagram.svg` for domain models; `journey-map-diagram.svg` for journeys; `timeline-plan-diagram.svg` for timelines; `quadrant-analysis-diagram.svg` for quadrants; and `mindmap-diagram.svg` for mind maps. + Read only the evidence the requested subject needs, the one diagram-type pattern selected, and its matching family template. Do not load unrelated templates or explore beyond the subject's confirmed boundary. + Select the diagram type from devspec/architecture/_template/diagram-types.md. + Start each SVG from the matching family-specific template: `architecture-diagram.svg` for system architecture; `application-landscape-diagram.svg` for application landscapes; `infrastructure-topology-diagram.svg` for infrastructure topology; `process-flow-diagram.svg` for process flows; `sequence-diagram.svg` for interactions; `state-lifecycle-diagram.svg` for state behavior; `domain-model-diagram.svg` for domain models; `journey-map-diagram.svg` for journeys; `timeline-plan-diagram.svg` for timelines; `quadrant-analysis-diagram.svg` for quadrants; and `mindmap-diagram.svg` for mind maps. Create only evidence-backed, non-duplicate diagrams and persist queue or overview state for recovery. - For a multi-repository diagram, use repo-access before reading or validating another repository. - Accept a stable queued `DIA-###` ID or diagram subject, record subject, type, evidence, format, status, and next in the queue, and index completed output in the overview. On an explicit process-flow batch request, generate every queued non-duplicate process-flow candidate, validate each output, update each queue row independently, and leave the caller lifecycle state unchanged. - Default to SVG with title and description and validate its XML; write Mermaid or HTML only when explicitly requested. + Record an evidence blocker in the caller's decision record, never in the queue, and leave the caller's saved stage and next action unchanged. + Accept a stable queued `DIA-###` ID or diagram subject, record subject, type, evidence, output format, duplicate-check result, status, and next action in the queue, and index completed output in the overview. On an explicit process-flow batch request, generate every queued non-duplicate process-flow candidate, validate each output, update each queue row independently, and leave the caller lifecycle state unchanged. + Default to SVG with title and description and validate its XML. Write Mermaid or HTML only when explicitly requested, and when you do, record it from `devspec/architecture/_template/diagram.md` or `diagram.html` so its evidence, assumptions, and maintenance notes stay with the output. Default to `motion=none`. Treat an explicit request for an animated diagram without a motion value as `motion=explain`; reject unsupported motion values. For `motion=explain`, animate only an evidence-backed sequence, flow, or state transition and follow the opt-in motion guidance in diagram-types.md. Keep the complete meaning visible in the static final frame, provide a reduced-motion result with no information loss, and do not add decorative motion or imply unsupported behavior. Record animated SVG output in the queue's existing Output field as `svg; motion=explain`. When HTML is also requested, inline the same SVG so its motion and reduced-motion behavior remain intact. Preserve the template's standalone dark visual contract: 1600 by 900 canvas, subtle grid, framed surface, monospace typography, semantic role colors, connectors behind cards, short labels, and a legend only when its notation needs explanation. Replace every placeholder before completion and do not use external assets, scripts, iframes, foreign objects, remote fonts, unresolved placeholders, or unsupported diagram families. + Anchor every connector to a shape edge at both ends, keep each arrowhead visible instead of hidden behind the shape it points at, and remove any shape the evidence leaves unconnected. Keep label backgrounds clear of boundary strokes, other labels, and neighboring shapes, and give every color that appears on a shape a matching legend entry. Keep labels short and place explanations in supporting Markdown rather than the graphic. Keep flowcharts to one primary concern and split an overloaded diagram at a confirmed responsibility boundary; use `sequence` for ordered interactions and the process-flow template for end-to-end operational behavior. For process flows, make the happy path visually obvious; distinguish start or end, manual, automated, integration, decision, exception, and artifact steps; label loop-backs; and draw exception paths as labeled dashed rose arrows that terminate or reconnect to a named step. @@ -32,13 +35,12 @@ Invocation: `/devspec.diagram runtime architecture format=svg motion=none|explai + + Validate the queued output, including finite animation and final-frame and reduced-motion completeness when motion is requested; index only completed diagrams, and leave the caller's saved stage unchanged. - Use static SVG by default; add explanatory motion, Mermaid, or HTML only when requested. - devspec/architecture/artifact-queue.md - return-to-caller diff --git a/devspec/contracts/devspec.extract.md b/devspec/contracts/devspec.extract.md index e4288fc..6dbfc4c 100644 --- a/devspec/contracts/devspec.extract.md +++ b/devspec/contracts/devspec.extract.md @@ -1,6 +1,6 @@ # devspec.extract -Build a complete evidence-backed baseline for one existing repository or an explicitly scoped multi-repository system. +Inspect the approved existing system end-to-end, produce its technical, business, workflow, and rule baseline, and prepare an evidence-backed diagram candidate list for explicit generation approval. Invocation: `/devspec.extract` @@ -9,33 +9,31 @@ Invocation: `/devspec.extract` + + + Use for the existing-system baseline of an approved source scope. This command completes the whole foundation chain in one run; do not also run the individual foundation commands for the same repository. It prepares diagram candidates and offers generation once; devspec.diagram owns every later diagram. Explicitly confirmed source repository scope, or current canonical evidence that names each repository's role, local path, and allowed access. - Treat the agent's current workspace or scaffolding directory as a proposed source target, never proof. Before inspecting source, obtain either an explicit user confirmation that names every source repository, role, path, and read, edit, and validation permission, or current canonical evidence that records those facts. If neither exists, first collect one repository path at a time, then ask one access question after each confirmed path; record the accepted source scope in `devspec/foundation/codebase-structure.md` before reading source. Later commands may use that current record as scope evidence. + Complete repo-access before inspecting source, then record the accepted source scope in `devspec/foundation/codebase-structure.md`. Later commands may use that record as scope evidence. Inspect owned source, tests, manifests, configuration, infrastructure, scripts, and docs; exclude dependencies, caches, generated output, and repositories outside approved scope. - For multi-repository work, record every repository role, path, access boundary, and evidence before reading, editing, or validating it. For every approved repository, record an observed repository layout in `devspec/foundation/codebase-structure.md`: a readable `text` tree rooted at its confirmed local path that includes solution or manifest files, owned source and test roots, meaningful modules, configuration, and integration or migration locations. Keep the tree representative rather than exhaustive; exclude dependencies, caches, generated output, and secrets. - Ask one clarification for every unresolved material question. Label all durable findings confirmed, observed, inferred, or blocked; do not invent roles, workflows, business rules, validation rules, integrations, or diagrams. + Do not invent roles, workflows, business rules, validation rules, integrations, or diagrams; record an absent fact as blocked instead. Initialize and complete every listed foundation artifact from its template when missing: project context, technology stack, codebase structure, coding standards with followable local examples, rules, technical baseline, roles, workflows, workflow rules, extraction state, exploration state, and coverage. Record rare cross-work-item principle candidates in `devspec/constitution.md` with stable `CP-###` IDs, evidence, and candidate state; do not promote inferred candidates. For each observed coding convention that changes implementation or review behavior, assign a stable `CS-###` ID and capture one or more concise, concrete local code or test snippets as `EX-###` entries under `## Standards Examples`. Each entry names the applicable standard IDs, source location, and fenced language-appropriate code; one example may apply to multiple standards. Record a relevant anti-pattern when repository evidence supports one. - Populate the single OWASP Top 10:2025 baseline in rules.md from observed code, dependencies, configuration, deployment, and access evidence. Record controls, gaps, and unknowns; do not infer an internal-only or limited-access boundary without enforceable evidence. + Populate the OWASP baseline in rules.md from observed code, dependency, configuration, deployment, and access evidence. For every confirmed business workflow, record its business area, participating roles, trigger, outcome, business rules, validation rules, evidence, and applicable exceptions. Identify applicable evidence-backed diagram candidates: system architecture, application landscape, infrastructure topology, integration sequence or context, and a journey or process-flow diagram for every confirmed workflow. Add domain-model or state-lifecycle candidates only when evidence supports them. - Record every candidate in the diagram queue with its stable ID, type, subject, evidence, output format, duplicate-check result, status, and next action. Keep the overview limited to completed diagram links; do not generate an SVG or add an overview entry during extraction before the user answers the post-extraction diagram question. - After all foundation extraction outputs are complete, show the user or developer the complete candidate list. When one or more candidates exist, ask exactly one interactive confirmation: "Do you want me generate all the possible diagrams?" Offer: `Yes — generate all listed diagrams`, `No — prepare the list only`, `Choose diagrams — enter the IDs or subjects to generate`, and `Custom Answer`. Recommend `No — prepare the list only` when no generation preference is already confirmed. Each choice must include a concise example. - If the user or developer chooses `Yes`, generate every listed non-duplicate candidate, validate each SVG XML file, update its queue status, and index completed durable output in the overview. If they choose `No`, leave the evidence-backed candidate list prepared in the queue without generating diagrams. If they choose `Choose diagrams`, generate only the entered non-duplicate IDs or subjects and leave the remainder listed in the queue. - Whenever the candidate list is shown, tell the user or developer that any listed diagram can be generated later with `/devspec.diagram <DIA-ID-or-subject>`; include one concrete example such as `/devspec.diagram DIA-002`. + Record every candidate in the diagram queue with its stable ID, type, subject, evidence, output format, duplicate-check result, status, and next action. Keep the overview limited to completed diagram links; do not generate an SVG or add an overview entry during extraction before the developer answers the post-extraction diagram question. + After all foundation extraction outputs are complete, show the developer the complete candidate list. When one or more candidates exist, ask exactly one interactive confirmation: "Do you want me to generate all the possible diagrams?" Offer: `Yes — generate all listed diagrams`, `No — prepare the list only`, `Choose diagrams — enter the IDs or subjects to generate`, and `Custom Answer`. Recommend `No — prepare the list only` when no generation preference is already confirmed. Each choice must include a concise example. + If the developer chooses `Yes`, generate every listed non-duplicate candidate, validate each SVG XML file, update its queue status, and index completed durable output in the overview. If they choose `No`, leave the evidence-backed candidate list prepared in the queue without generating diagrams. If they choose `Choose diagrams`, generate only the entered non-duplicate IDs or subjects and leave the remainder listed in the queue. + Whenever the candidate list is shown, tell the developer that any listed diagram can be generated later with `/devspec.diagram <DIA-ID-or-subject>`; include one concrete example such as `/devspec.diagram DIA-002`. + Record every path deliberately left out of inspection in `devspec/foundation/discovery-exclusions.md` with its reason, so a later run does not re-explore it or mistake the gap for missing evidence. Keep one extraction coverage item active and write discovered facts to their destination artifact, not queue state. Reuse recorded discovery methods and do not repeat a failed method unless its condition changed. Existing system with confirmed source scope and no active incompatible extraction run; reject new-repository foundation authoring or an assumed workspace target. - - - - - Complete the listed baseline outputs and present the diagram candidate list before routing to story. Record every material evidence gap as blocked with a continuation condition, and preserve ungenerated candidates for `/devspec.diagram`. @@ -50,10 +48,14 @@ Invocation: `/devspec.extract` + + - Confirm and record source scope before inspection, then complete the existing-system baseline, prepare and present the applicable diagram list, obtain the one diagram-generation confirmation, and record remaining gaps or blocked evidence. - devspec/foundation/extraction-coverage.md - devspec.story-or-devspec.clarify + + + + + Complete the listed baseline outputs and present the diagram candidate list before routing to story. Record every material evidence gap as blocked with a continuation condition, and preserve ungenerated candidates for `/devspec.diagram`. diff --git a/devspec/contracts/devspec.finalize.md b/devspec/contracts/devspec.finalize.md index 216c36f..6e2c5ef 100644 --- a/devspec/contracts/devspec.finalize.md +++ b/devspec/contracts/devspec.finalize.md @@ -9,29 +9,31 @@ Invocation: `/devspec.finalize [work-item-id]` + + + + Use to decide whether the current scope revision is buildable and to record its brief and validation plan. This command plans readiness only; devspec.tasks sequences the work and devspec.implement changes code. An optional work-item ID or a groomed current draft. + Read only the current-revision story and decisions, the finalization traces' direct sources in coding standards, codebase structure, rules, workflow rules, constitution, and the architecture queue or overview. Do not scan unrelated work items, unrelated code areas, or historical revisions beyond the superseded sections of this work item. Check only material readiness gaps: scope, criteria, behavior, data, integration, security, compliance, validation, and delivery constraints. Mark ready only when remaining gaps cannot materially change implementation or validation; otherwise create one material blocker question. Classify every accepted material decision as work-item-local or reusable. Promote a reusable business or validation decision to devspec/foundation/workflow-rules.md with a stable rule ID and source decision link; promote a reusable engineering constraint to devspec/foundation/rules.md. Record the resulting canonical rule link in decisions.md. - Record one compact foundation trace for the relevant coding conventions, owned areas and boundaries, canonical rules, applicable active `CP-###` principles, and OWASP categories. Record a separate architecture and diagram trace for relevant overview entries, completed diagrams, or queued candidates, including implementation and validation impact; no diagram is required. For every relevant OWASP category, state applicability, required control, and planned project-native evidence. - Do not mark ready while a relevant OWASP category, required control, or security-validation plan is unresolved. + Record one compact foundation trace for the relevant coding conventions, owned areas and boundaries, canonical rules, applicable active `CP-###` principles, and the OWASP categories the change touches. Record a separate architecture and diagram trace for relevant overview entries, completed diagrams, or queued candidates, including implementation and validation impact; no diagram is required. Write a concise implementation brief and validation plan, not implementation code. Active work item at finalization with a complete current-revision story; reject stale finalization, blocked work, or incomplete draft scope. + Stamp the readiness brief with the current scope revision. Preserve earlier revision sections as superseded history. - Scan only material readiness gaps; do not invent implementation detail. - devspec/work-items/<id>/finalize.md - devspec.clarify-or-devspec.tasks diff --git a/devspec/contracts/devspec.grooming.md b/devspec/contracts/devspec.grooming.md index 8519162..091c52b 100644 --- a/devspec/contracts/devspec.grooming.md +++ b/devspec/contracts/devspec.grooming.md @@ -9,9 +9,13 @@ Invocation: `/devspec.grooming [work-item-id]` + + + + Use only when a draft story needs scoped analysis before it can be built. Skip it and run devspec.finalize directly when behavior, acceptance criteria, and the affected code area are already clear. An optional work-item ID or clear current draft. Read only the draft, relevant coding standards, codebase structure, foundation rules and workflow rules, selected code area, and direct dependencies; do not scan unrelated historical work-item decisions. @@ -22,13 +26,11 @@ Invocation: `/devspec.grooming [work-item-id]` + Do not advance while a material question remains unanswered; record the one blocker and resume reference. - Improve draft story and decisions in place; suggest only material questions. - devspec/work-items/<id>/story.md - devspec.clarify-or-devspec.finalize diff --git a/devspec/contracts/devspec.implement.md b/devspec/contracts/devspec.implement.md index e3f7aec..ded72ef 100644 --- a/devspec/contracts/devspec.implement.md +++ b/devspec/contracts/devspec.implement.md @@ -9,31 +9,33 @@ Invocation: `/devspec.implement [work-item-id]` + + + + Use to execute the ordered pending tasks of the current scope revision. This command does not re-plan, widen scope, or review its own output. An optional work-item ID with ready finalization and pending task records. + Read only the tasks being implemented, the finalization traces they cite, and the code area and direct dependencies each task names. Do not scan unrelated work items, unrelated code areas, or historical decision records. Confirm every task is in finalized scope, unblocked, and ordered before editing code. Checkpoint before edits and focused validation; stop for a material ambiguity instead of expanding scope. Before editing, apply the relevant finalization foundation trace: coding standards and their follow examples, owned code areas and boundaries, canonical rules, and applicable OWASP controls. Record changed areas, applied decision or canonical rule IDs, and validation evidence after each meaningful task. Express a business or validation decision through named code and tests. Add a developer comment only when its rationale is not evident from the code or test; reference the canonical rule ID, never an old work-item decision as the sole authority. - Record project-native security evidence for every applicable OWASP control. A suspected false positive or not-applicable finding requires the agent to ask one material confirmation question of the implementing developer, then record the explicit confirmation, rationale, enforceable supporting evidence, and material-change revalidation trigger; it remains proposed until review. - Do not classify a known unresolved vulnerability as not applicable merely because access is limited, authenticated, or internal-only. Active work item at implementation with current-revision ready finalization and ordered pending tasks; reject stale plans, blocked tasks, or changed scope. + + - Record the changed-work baseline and mark a task complete only after its recorded validation passes; preserve superseded revisions. - Stay within finalized scope; checkpoint before edits and validation. - devspec/work-items/<id>/implement.md - review + Record the changed-work baseline and mark a task complete only after its recorded validation passes. diff --git a/devspec/contracts/devspec.projectcontext.md b/devspec/contracts/devspec.projectcontext.md index e0d272e..8b0860e 100644 --- a/devspec/contracts/devspec.projectcontext.md +++ b/devspec/contracts/devspec.projectcontext.md @@ -9,25 +9,24 @@ Invocation: `/devspec.projectcontext` + Use for new-repository foundation authoring or an explicitly requested targeted update. Use devspec.extract, not this command, to establish an existing-system baseline. Product context, a confirmed source, or an explicit durable-principle promotion or retirement. Capture purpose, users, outcomes, boundaries, and delivery context only. When the developer explicitly promotes or retires a rare cross-work-item principle, update `devspec/constitution.md` with its stable `CP-###` ID, evidence, state, and append-only history; do not infer a promotion. - Mark each material statement confirmed, observed, inferred, or blocked. New foundation chain with project context absent, or an explicit targeted update; reject an existing-system baseline request. + + - Record the foundation state and one registered next command; blocked evidence routes to devspec.clarify. - Update product context with clearly labeled confirmed, observed, inferred, or blocked statements. - devspec/foundation/project-context.md - techstack + Record the foundation state and one registered next command. diff --git a/devspec/contracts/devspec.quickfix.md b/devspec/contracts/devspec.quickfix.md index 7b9b526..085a8b8 100644 --- a/devspec/contracts/devspec.quickfix.md +++ b/devspec/contracts/devspec.quickfix.md @@ -9,8 +9,11 @@ Invocation: `/devspec.quickfix Fix Orders empty-state text` + + + Use only for one localized, low-risk change that needs no work item. Route anything outside that boundary to devspec.story before editing code. One localized bug fix or small enhancement. Select one primary scope: UI, internal API, function/job, library, configuration, tests, or a user-defined bounded scope. @@ -18,17 +21,14 @@ Invocation: `/devspec.quickfix Fix Orders empty-state text` Create a QF record, implement, and run focused validation in the same command. Route public API contracts, database schema or migration, authentication or security work, breaking changes, unrelated concerns, and unresolved risk to story and suggested grooming without editing code. - One documented localized low-risk request at triage with one primary scope; reject contracts, migrations, security work, breaking changes, unrelated concerns, and unresolved risk. + One documented localized low-risk request at triage with one primary scope; reject any request this command must route. - + Record the selected route, validation evidence, and terminal next action. Direct implementation is allowed only for the declared low-risk scope. - Select one primary scope, route risky work, then implement and validate directly. - devspec/quickfixes/QF-###-slug.md - none-or-devspec.clarify-or-devspec.story diff --git a/devspec/contracts/devspec.review.md b/devspec/contracts/devspec.review.md index b09d726..6307bc7 100644 --- a/devspec/contracts/devspec.review.md +++ b/devspec/contracts/devspec.review.md @@ -9,19 +9,23 @@ Invocation: `/devspec.review [work-item-id]` + + + + + Use to judge completed implementation against the current scope revision's approved scope and recorded evidence. This command records findings; devspec.implement applies them. An optional work-item ID with finalization, tasks, implementation record, and changed work. + Read only the changed-work baseline's changed paths and their direct callers, the current-revision finalization, tasks, and implementation records, and the canonical rules those records cite. Do not re-review unchanged code or unrelated work items. Compare changed work to approved scope, task source coverage, finalization foundation and architecture traces, validation evidence, and every applicable accepted material decision or canonical rule. + Verify the work against every protocol this work item loaded, and report a violation as a finding: evidence labels and changed-work baseline from state, revision currency from revision, scope and change discipline from work, access boundaries from repo-access, and the security gate from security. Check changed source against the shared work protocol for duplicated capabilities, unjustified dependencies, speculative abstractions, and unused configuration. Evaluate the choices against approved requirements, project conventions, and any recorded justification. Record actionable complexity findings in the existing Findings table with the location, supporting evidence, and a suitable simpler alternative or removal that preserves required behavior and safeguards. Require rework for demonstrated violations of approved scope or the shared implementation rule. Do not block acceptance solely because a different stylistic implementation is shorter. Record each decision or rule verification as implemented-as-decided, intentionally-superseded with a recorded replacement, or not-verified. Treat an unrecorded contradiction as rework-required. - Verify every applicable OWASP control and its project-native evidence. Confirm a proposed false positive or not-applicable finding only when the implementing developer confirmed it, enforceable evidence supports the rationale, and the reviewer records confirmation. - Do not record accepted while an applicable OWASP control lacks evidence or an exception lacks either confirmation. Treat unsupported internal-only, authenticated-only, or limited-access reasoning as an applicable risk with reduced exposure. A known unresolved vulnerability cannot be closed as an exception. - Record a material-change revalidation trigger for every confirmed exception covering related code, access control, deployment, integration, or exposure. Write findings only; do not silently edit implementation code. Record exactly one outcome: accepted, rework-required, or blocked; record exactly one next action. @@ -29,6 +33,7 @@ Invocation: `/devspec.review [work-item-id]` + @@ -36,7 +41,4 @@ Invocation: `/devspec.review [work-item-id]` Verify the recorded changed-work baseline. Accepted is terminal and clears current-work-item context; rework returns only affected tasks to implementation and blocked work preserves context. - Record the review outcome, one next action, and any actionable findings; do not silently change implementation code. - devspec/work-items/<id>/review.md - devspec.implement-or-devspec.clarify-or-none diff --git a/devspec/contracts/devspec.rules.md b/devspec/contracts/devspec.rules.md index 9cd26d3..62389c6 100644 --- a/devspec/contracts/devspec.rules.md +++ b/devspec/contracts/devspec.rules.md @@ -9,26 +9,25 @@ Invocation: `/devspec.rules` + + Use for new-repository foundation authoring or an explicitly requested targeted update. Use devspec.extract, not this command, to establish an existing-system baseline. Hard engineering, compliance, security, delivery, or accessibility constraints. Keep non-negotiable rules separate from ordinary coding conventions and link applicable active `CP-###` constitution principles rather than duplicating them. State enforcement or validation for each rule when known. - Maintain one OWASP Top 10:2025 baseline in rules.md. For every category, record whether it is applicable, limited, out-of-scope, or unknown, plus the required project control and enforcement evidence. - Record limited or internal-only exposure only when enforceable access, deployment, or network evidence supports it; otherwise treat the category as applicable with reduced exposure. Completed coding standards in the new foundation chain, or an explicit targeted update; reject an existing-system baseline request. + + - Record enforceable rules and one registered next command; blocked evidence routes to devspec.clarify. - Keep hard constraints distinct from ordinary coding conventions and establish the project OWASP baseline. - devspec/foundation/rules.md - story + Record enforceable rules and one registered next command. diff --git a/devspec/contracts/devspec.story.md b/devspec/contracts/devspec.story.md index 2b513b9..7e6d12d 100644 --- a/devspec/contracts/devspec.story.md +++ b/devspec/contracts/devspec.story.md @@ -9,9 +9,13 @@ Invocation: `/devspec.story Add customer export` + + + + Use to open one new work item from a manual request or a provider reference. Use devspec.changerequest for related scope on an already-finalized work item, and devspec.quickfix for a localized low-risk change that needs no work item. One manual feature, bug, security issue, or task, or one provider work-item URL or identifier resolvable through an available authenticated MCP tool. Handle exactly one work item; ask a material selection question when input contains independent items. @@ -22,9 +26,9 @@ Invocation: `/devspec.story Add customer export` Allow manual intake as an explicit fallback only when provider resolution is unavailable or the developer intentionally selects it. Record the confirmation result and concise redacted source summary in story.md; keep credentials, tokens, and unnecessary personal data out of all artifacts. If a provider reference is ambiguous, inaccessible, unavailable through MCP, or insufficient to create one work item, ask one material clarification or offer the structured manual fallback. Do not silently fall back to browser search, create an unverified work item, or fabricate provider content. Read only the coding standards, codebase structure, foundation rules, and workflow rules relevant to the requested behavior and code area; do not scan unrelated historical work-item decisions. + Resolve a provider reference against `devspec/foundation/provider-integrations.md`: use its accepted inputs, validation guardrails, and confirmation requirements, and record the resolution outcome there when a new provider, input form, or guardrail is confirmed. Create folders as optional-provider-prefix plus numeric ID plus kebab-case title; do not rename legacy folders automatically. - Before finalization, update the baseline; after finalization, route related scope to changerequest and unrelated scope to a linked item. - Treat an explicit story request as new-work intent unless it is clearly related finalized scope, which routes to changerequest. + Treat an explicit story request as new-work intent. Before finalization, update the baseline in place; after finalization, route related scope to changerequest and unrelated scope to a linked item. When creating a story or accepting a validated explicit ID, set current-work-item context for the current branch; preserve meta.md as the canonical state record. For an ordinary request with current context, resume clearly related pre-finalization work; ask one classification question before switching stories or accepting independent scope. @@ -32,6 +36,8 @@ Invocation: `/devspec.story Add customer export` + + @@ -39,7 +45,4 @@ Invocation: `/devspec.story Add customer export` Record the selected route and normalized provider source when used. Use grooming when code-area evidence, compatibility, risk, or acceptance criteria needs scoped analysis. - Resolve one provider reference read-only when available, require structured confirmation before creating the work item, or record an explicitly chosen manual request; preserve finalized baselines. - devspec/work-items/<id>/story.md - devspec.grooming-or-devspec.finalize diff --git a/devspec/contracts/devspec.tasks.md b/devspec/contracts/devspec.tasks.md index f1d19e5..19269ed 100644 --- a/devspec/contracts/devspec.tasks.md +++ b/devspec/contracts/devspec.tasks.md @@ -9,26 +9,29 @@ Invocation: `/devspec.tasks [work-item-id]` + + + + Use to turn a ready finalization into an ordered, independently verifiable plan. This command plans only; devspec.implement makes the changes. An optional work-item ID with a ready current finalization brief. + Read only the current finalization brief, the story's current-revision criteria, and the foundation or architecture entries that brief already cites. Do not re-derive the traces from source or re-read unrelated foundation artifacts. Each task names scope, dependency, source justification, applicable decision or canonical rule IDs, validation, and done condition. Cite the finalization foundation and architecture traces for coding standards, codebase boundaries, diagrams, and OWASP controls instead of duplicating them per task. Order dependencies before dependents and split only work too broad to validate safely. - Active work item at tasks with a ready finalization matching the current scope revision; reject blocked, stale, or superseded readiness evidence. + Active work item at tasks with a ready finalization matching the current scope revision; reject blocked readiness evidence. + Plan only the active revision. Each task has source justification, validation, done condition, and a controlled initial status. - Trace tasks to readiness items and validation evidence; sequence dependencies first. - devspec/work-items/<id>/tasks.md - implement diff --git a/devspec/contracts/devspec.techstack.md b/devspec/contracts/devspec.techstack.md index 29babc0..e21cd65 100644 --- a/devspec/contracts/devspec.techstack.md +++ b/devspec/contracts/devspec.techstack.md @@ -9,7 +9,9 @@ Invocation: `/devspec.techstack` + + Use for new-repository foundation authoring or an explicitly requested targeted update. Use devspec.extract, not this command, to establish an existing-system baseline. Stack evidence, target stack, or delivery constraint. @@ -20,13 +22,12 @@ Invocation: `/devspec.techstack` Completed project context in the new foundation chain, or an explicit targeted update; reject an existing-system baseline request. + + - Record inspected evidence and one registered next command; blocked evidence routes to devspec.clarify. - Inspect manifests and configuration before asking for missing material facts. - devspec/foundation/tech-stack.md - codebase-structure + Record inspected evidence and one registered next command. diff --git a/devspec/foundation/_template/codebase-structure.md b/devspec/foundation/_template/codebase-structure.md index ccdb4b1..4f8b89a 100644 --- a/devspec/foundation/_template/codebase-structure.md +++ b/devspec/foundation/_template/codebase-structure.md @@ -1,7 +1,7 @@ # Codebase Structure -| Area | Ownership | Boundary | Evidence | -|---|---|---|---| +| Area | Ownership | Boundary | Integration points | Validation location | Evidence | +|---|---|---|---|---|---| ## Repositories @@ -27,4 +27,4 @@ For every repository above, record a representative tree rooted at its confirmed | `-- <meaningful-module>/ |-- <test-root>/ `-- <configuration-or-migration-location>/ -``` \ No newline at end of file +``` diff --git a/devspec/foundation/_template/decisions.md b/devspec/foundation/_template/decisions.md index ae810e6..8908d95 100644 --- a/devspec/foundation/_template/decisions.md +++ b/devspec/foundation/_template/decisions.md @@ -7,5 +7,7 @@ ## Decisions +One row per material question, in the shape `devspec/protocols/ask.xml` requires. Record the row before waiting for an answer. + | ID | Material question | Evidence | Impact | Choices | Recommended | Recommendation justification | Applicability | Canonical rule link | Answer or skip reason | Status | -|---|---|---|---|---|---|---|---|---|---|---| \ No newline at end of file +|---|---|---|---|---|---|---|---|---|---|---| diff --git a/devspec/foundation/_template/extraction-coverage.md b/devspec/foundation/_template/extraction-coverage.md index 68f674c..3996d03 100644 --- a/devspec/foundation/_template/extraction-coverage.md +++ b/devspec/foundation/_template/extraction-coverage.md @@ -1,4 +1,4 @@ # Extraction Coverage | Area | Scope | Destination artifact | Evidence | Status | Gap or next action | -|---|---|---|---|---|---| \ No newline at end of file +|---|---|---|---|---|---| diff --git a/devspec/foundation/_template/project-context.md b/devspec/foundation/_template/project-context.md index dfa89a1..7fbae89 100644 --- a/devspec/foundation/_template/project-context.md +++ b/devspec/foundation/_template/project-context.md @@ -1,7 +1,11 @@ # Project Context -- Purpose: -- Users: -- Outcomes: -- Scope boundaries: -- Delivery context: +Label every statement `confirmed`, `observed`, `inferred`, or `blocked`. + +| Area | Statement | Evidence label | Evidence | +|---|---|---|---| +| Purpose | | | | +| Users | | | | +| Outcomes | | | | +| Scope boundaries | | | | +| Delivery context | | | | diff --git a/devspec/foundation/_template/provider-integrations.md b/devspec/foundation/_template/provider-integrations.md index 786b88d..1a00cab 100644 --- a/devspec/foundation/_template/provider-integrations.md +++ b/devspec/foundation/_template/provider-integrations.md @@ -47,4 +47,4 @@ Show provider, identifier, title, type when available, current external status w | Failure detail | Distinguish not found, unauthorized, malformed input, and transient provider failures. | | Authentication configuration | Keep provider authentication outside prompt artifacts. | | Privilege model | Use least-privilege tokens or service identities. | -| Access mode | Prefer read-only access for intake and review unless write-back is separately required. | \ No newline at end of file +| Access mode | Prefer read-only access for intake and review unless write-back is separately required. | diff --git a/devspec/foundation/_template/roles.md b/devspec/foundation/_template/roles.md index 553e39f..c658559 100644 --- a/devspec/foundation/_template/roles.md +++ b/devspec/foundation/_template/roles.md @@ -1,4 +1,4 @@ # Roles | Role | Responsibilities | Permission boundary | Workflows | Evidence | -|---|---|---|---|---| \ No newline at end of file +|---|---|---|---|---| diff --git a/devspec/foundation/_template/rules.md b/devspec/foundation/_template/rules.md index ca53ddf..f115272 100644 --- a/devspec/foundation/_template/rules.md +++ b/devspec/foundation/_template/rules.md @@ -2,8 +2,8 @@ ## Project Rules -| Rule ID | Rule | Why | Enforcement | Source decision | -|---|---|---|---|---| +| Rule ID | Rule | Why | Enforcement | Constitution principles | Source decision | +|---|---|---|---|---|---| ## OWASP Top 10:2025 Baseline @@ -22,4 +22,4 @@ Record the project applicability, required control, and enforcement evidence for | A07:2025 Authentication Failures | | | | | | A08:2025 Software or Data Integrity Failures | | | | | | A09:2025 Security Logging and Alerting Failures | | | | | -| A10:2025 Mishandling of Exceptional Conditions | | | | | \ No newline at end of file +| A10:2025 Mishandling of Exceptional Conditions | | | | | diff --git a/devspec/foundation/_template/tech-stack.md b/devspec/foundation/_template/tech-stack.md index cdc4140..8bcd60b 100644 --- a/devspec/foundation/_template/tech-stack.md +++ b/devspec/foundation/_template/tech-stack.md @@ -1,4 +1,4 @@ # Technology Stack -| Area | Confirmed stack | Evidence | Constraint | -|---|---|---|---| +| Area | Confirmed stack | Supported versions | Evidence | Constraint | +|---|---|---|---|---| diff --git a/devspec/foundation/_template/technical-baseline.md b/devspec/foundation/_template/technical-baseline.md index f62eb47..2f3f500 100644 --- a/devspec/foundation/_template/technical-baseline.md +++ b/devspec/foundation/_template/technical-baseline.md @@ -13,4 +13,4 @@ ## Integrations | Integration | Direction | Contract or protocol | Failure or security concern | Evidence | -|---|---|---|---|---| \ No newline at end of file +|---|---|---|---|---| diff --git a/devspec/foundation/_template/workflow-rules.md b/devspec/foundation/_template/workflow-rules.md index ea38b76..5fbd477 100644 --- a/devspec/foundation/_template/workflow-rules.md +++ b/devspec/foundation/_template/workflow-rules.md @@ -1,4 +1,4 @@ # Workflow Rules | Rule ID | Workflow ID | Applicability | Rule | Validation or enforcement | Exception | Source decision | Evidence | -|---|---|---|---|---|---|---|---| \ No newline at end of file +|---|---|---|---|---|---|---|---| diff --git a/devspec/foundation/_template/workflows.md b/devspec/foundation/_template/workflows.md index a293692..d4caedc 100644 --- a/devspec/foundation/_template/workflows.md +++ b/devspec/foundation/_template/workflows.md @@ -8,4 +8,4 @@ ## Role Workflow Matrix | Role | Workflow ID | Responsibility | Entry or exit | Evidence | -|---|---|---|---|---| \ No newline at end of file +|---|---|---|---|---| diff --git a/devspec/foundation/template-map.md b/devspec/foundation/template-map.md index 042e303..492a2b7 100644 --- a/devspec/foundation/template-map.md +++ b/devspec/foundation/template-map.md @@ -18,4 +18,4 @@ Create a missing canonical artifact from its matching template before editing it | `_template/exploration-state.md` | `exploration-state.md` | `devspec.extract` | | `_template/extraction-coverage.md` | `extraction-coverage.md` | `devspec.extract` | | `_template/discovery-exclusions.md` | `discovery-exclusions.md` | `devspec.extract` | -| `_template/provider-integrations.md` | `provider-integrations.md` | provider-backed work | \ No newline at end of file +| `_template/provider-integrations.md` | `provider-integrations.md` | provider-backed work | diff --git a/devspec/glossary.md b/devspec/glossary.md index 7956616..6af9ba2 100644 --- a/devspec/glossary.md +++ b/devspec/glossary.md @@ -1,13 +1,15 @@ # Glossary -- Work-item stages: intake, grooming, finalization, tasks, implementation, review, complete. -- Quickfix stages: triage, implementation, validation, complete, routed. -- Run states: active (eligible to continue), paused (user-paused), blocked (one active material decision), stopped (requires new direction), complete (terminal with `next: none`). -- Task statuses: pending, in-progress, blocked, complete, superseded. -- Scope revision: a monotonic work-item number. Finalization, tasks, implementation, and review operate only on the current revision; older records are retained as superseded history. +Run states, work-item and quickfix stages, task statuses, evidence labels, the changed-work baseline, and resume semantics are defined once in `devspec/protocols/state.xml`. `devspec/lifecycle.md` owns the route graph. This file covers the remaining terms. + +- Scope revision: a monotonic work-item number identifying which generation of approved scope a record belongs to. `devspec/protocols/revision.xml` owns its rules. - Current work-item context: a private, per-worktree Git-metadata selection used to resolve an omitted work-item ID. It is never a Git-tracked artifact and never replaces `meta.md` as canonical state. -- Evidence: confirmed, observed, inferred, blocked. -- OWASP exception: a reviewer-confirmed false-positive or not-applicable finding supported by enforceable evidence; it is distinct from an unresolved vulnerability. +- Material question: a question whose answer can change implementation, validation, or scope. Only material questions enter the ask queue; anything else is decided without asking. +- Material decision: the recorded answer to a material question, held in the command's decision record. +- Material blocker: a material question that must be answered before the command can continue. It sets run state `blocked` and makes `devspec.clarify` the next command. Exactly one may be active at a time. +- Developer: the person the agent asks. Every interactive question in this framework is addressed to the developer; the agent never answers its own material question. +- Registered next action: the single next command recorded in the state record. A command reports exactly one, and `none` is a valid registered next action for terminal work. +- OWASP exception: a reviewer-confirmed false-positive or not-applicable finding supported by enforceable evidence; it is distinct from an unresolved vulnerability. `devspec/protocols/security.xml` owns its confirmation rules. ## Repository access requirements @@ -20,4 +22,4 @@ | `release-coordination` | Coordinate release information only; do not inspect, edit, or validate repository contents. | | `unavailable` | The repository cannot currently be accessed; record the impact as a blocker. | -Use these values in `foundation/codebase-structure.md`. Select the least privilege that satisfies the current command; the repository location alone never grants access. \ No newline at end of file +These lowercase values are the recorded form. `devspec/protocols/repo-access.xml` owns how they are collected, recommended, recorded, and enforced. diff --git a/devspec/install-manifest.txt b/devspec/install-manifest.txt index 211b2cf..1e3c40b 100644 --- a/devspec/install-manifest.txt +++ b/devspec/install-manifest.txt @@ -1,4 +1,7 @@ -# Canonical Devspec Lite artifacts installed by automated and manual setup. +# Glob patterns for the canonical artifacts copied by automated and manual setup. +# Not the full install list: repository-state.md is generated from the chosen repository +# state, and architecture/overview.md and architecture/artifact-queue.md are seeded from +# architecture/_template/ so a target repository starts with empty records. README.md constitution.md command-registry.md @@ -13,5 +16,3 @@ work-items/_template/*.md quickfixes/README.md quickfixes/_template.md architecture/_template/* -architecture/overview.md -architecture/artifact-queue.md diff --git a/devspec/lifecycle.md b/devspec/lifecycle.md index 5abdac1..e4ffdea 100644 --- a/devspec/lifecycle.md +++ b/devspec/lifecycle.md @@ -1,35 +1,32 @@ # Devspec Lifecycle -Canonical contracts in `devspec/contracts/` own command behavior. This document defines the shared state vocabulary and the legal route graph those contracts use. +Canonical contracts in `devspec/contracts/` own command behavior. This document owns the state-record locations and the legal route graph those contracts use. The shared state vocabulary — run states, stages, task statuses, evidence labels, the changed-work baseline, and resume semantics — lives in `devspec/protocols/state.xml`. ## State records - A foundation command records its command, stage, run state, last action, resume reference, next action, and update date in `devspec/foundation/decisions.md`. -- A work item records the same state in `meta.md`. Its `scope_revision` starts at `1` and increases only when `devspec.changerequest` accepts a related requirement. -- The selected current work item is private convenience state, not workflow evidence. Store it only at the per-worktree path returned by `git rev-parse --git-path devspec/current-work-item.json`; it identifies the work item, branch, selection source, and timestamp. Never commit a current-story file. +- A work item records the same state in `meta.md`, together with its scope revision. - A quickfix records its state in front matter. A diagram records queue status and returns to its invoking workflow without changing that workflow's state. -- `active` means the registered next command may run. `blocked` means exactly one active material decision is recorded and the next command is `devspec.clarify`. `paused` is an explicit user pause. `stopped` requires a new user direction before resuming. `complete` is terminal and must use `next: none`. +- The selected current work item is private convenience state, never workflow evidence and never committed. `devspec/protocols/current-work-item.xml` owns where it is stored and how it is selected, validated, and cleared. -## Work-item states and revisions +## Work-item stages | Stage | Required next command or terminal outcome | |---|---| -| `intake` | `devspec.story` | +| `intake` | `devspec.story` or `devspec.clarify` | | `grooming` | `devspec.grooming` or `devspec.clarify` | | `finalization` | `devspec.finalize` or `devspec.clarify` | -| `tasks` | `devspec.tasks` | +| `tasks` | `devspec.tasks` or `devspec.clarify` | | `implementation` | `devspec.implement` or `devspec.clarify` | | `review` | `devspec.review` or `devspec.clarify` | | `complete` | terminal (`next: none`) | -Task status is one of `pending`, `in-progress`, `blocked`, `complete`, or `superseded`. A task becomes `complete` only after its recorded validation passes. Finalization, task, implementation, and review records carry the active scope revision. A change request increments that revision, preserves earlier revision sections as `superseded`, and requires fresh finalization before planning or implementation continues. - -Before an ID-free work-item command, resolve current context in this order: a validated supplied ID, a valid branch-matched local selection, then exactly one eligible non-terminal work item on the current branch. Clear a selection that has a changed branch, a missing work-item folder or `meta.md`, terminal work, or a stage/next-action mismatch. If several items remain, ask the user to choose. A clear continuation request dispatches only the selected `next` action; blocked work goes through `devspec.clarify`, and terminal work does not resume. +A work-item stage that records a material blocker routes to `devspec.clarify` and nowhere else. The foundation, caller, and quickfix triage stages do the same; the quickfix `routed` stage is non-terminal and routes only to `devspec.story`. `devspec/protocols/revision.xml` owns which revision each stage may read and write. ## Route graph -- Existing repository: `devspec.extract → devspec.story`; an evidence gap that can materially affect later work is `blocked → devspec.clarify`. +- Existing repository: `devspec.extract → devspec.story`. - New repository: `devspec.projectcontext → devspec.techstack → devspec.codebase-structure → devspec.coding-standards → devspec.rules → devspec.story`. A targeted foundation update returns to its caller after completing its declared artifact. - Work item: `devspec.story → devspec.grooming|devspec.finalize → devspec.tasks → devspec.implement → devspec.review`. Review results are `accepted → complete`, `rework-required → devspec.implement`, or `blocked → devspec.clarify`. -- Work-item IDs are optional selectors for switching or resolving ambiguity. After a story is selected, normal commands and `continue` use its per-worktree context and never skip the recorded `next` command. -- `devspec.clarify` resolves one decision and resumes its saved originating command. `devspec.changerequest` is allowed only after finalization and always returns to `devspec.finalize` with a new revision. `devspec.quickfix` is `complete`, `blocked`, or `routed -> devspec.story`. `devspec.diagram` returns to its caller. +- Work-item IDs are optional selectors for switching or resolving ambiguity. Without one, the current-work-item protocol resolves which work item a command acts on. +- `devspec.clarify` resolves one decision and resumes its saved originating command. `devspec.changerequest` is allowed only after finalization and always returns to `devspec.finalize` with a new revision. `devspec.quickfix` ends complete, blocks to `devspec.clarify`, or routes to `devspec.story`. `devspec.diagram` returns to its caller, or blocks to `devspec.clarify`. diff --git a/devspec/protocols/ask.xml b/devspec/protocols/ask.xml index e3d5b9b..c9d4e88 100644 --- a/devspec/protocols/ask.xml +++ b/devspec/protocols/ask.xml @@ -1,11 +1,12 @@ + Load with every command. It governs how any material question is asked and recorded. Maintain one active material-question queue for the invoking command. A command may deliberately scope its queue to one recorded material blocker. Ask one clarification for every unresolved material question in the active command queue. Ask exactly one unanswered material question at a time. Record and resolve it before asking the next material question. Maintain the active material-question queue until every material question is answered or skipped. After each answer, re-evaluate every remaining material question against current decisions; skip an invalid or inapplicable material question with its reason, then ask the next valid unanswered material question. Resume the workflow only when no applicable unanswered material questions remain. Persist material-question ID, evidence, impact, choices, recommendation, recommendation justification, applicability, canonical rule link when promoted, resume action, and answer-or-skip status in the command's decision record before waiting. - Offer two to five meaningful exclusive choices, each with a short example. + Offer two to five meaningful exclusive choices, each with a short example. A protocol that defines a fixed named value set offers that whole set instead. Custom Answer is always additional and never counts toward the limit. Render identical text choices only when the host lacks interactive controls. diff --git a/devspec/protocols/current-work-item.xml b/devspec/protocols/current-work-item.xml index 40984f1..d4d875e 100644 --- a/devspec/protocols/current-work-item.xml +++ b/devspec/protocols/current-work-item.xml @@ -2,9 +2,9 @@ Use before a work-item command with an omitted ID and for a clear continuation request such as continue or where were we. Use `git rev-parse --git-path devspec/current-work-item.json` for per-worktree local context. Never create or commit a tracked current-work-item artifact. Store work-item ID, current branch, selection source, and timestamp only in that local JSON record; it is never committed or pushed. - Prefer a validated explicit ID, then a valid local selection for the current branch, then exactly one eligible non-terminal work item. Ask the user to choose whenever multiple items remain. + Prefer a validated explicit ID, then a valid local selection for the current branch, then exactly one non-terminal work item on the current branch. Ask the developer to choose whenever multiple items remain. Clear a selection when its branch changed, its folder or meta record is missing, it is complete, or its saved stage and next action do not permit the requested command. - When no valid selection exists, recover only one eligible work item; otherwise ask the user to select or start a story. + When no valid selection exists, recover only one eligible work item; otherwise ask the developer to select one or start a work item. For a clear continuation request, dispatch only the selected saved meta.md next action. A blocked item uses devspec.clarify; a terminal item is not resumed. Set local context after story creation, validated explicit selection, or unique recovery. Preserve it while clarify restores the saved command. Clear local context after accepted review. Context is convenience state; meta.md remains canonical workflow truth. diff --git a/devspec/protocols/repo-access.xml b/devspec/protocols/repo-access.xml index ba2ee12..59df176 100644 --- a/devspec/protocols/repo-access.xml +++ b/devspec/protocols/repo-access.xml @@ -1,6 +1,8 @@ - Load before accessing a repository outside the scaffolding root, whenever source scope is not already confirmed, and whenever a task depends on more than one repository. - When a repository path is not already evidenced, first ask for one repository name or local path in a free-form text input. Show at least two examples such as `D:\Code\orders-api` and `D:\Code\orders-web`; allow the developer to type another path. Confirm the path before asking about access, and repeat for each additional repository. - After each path is confirmed, ask one interactive question: “What access requirement applies to <repository>?” Always offer these five exclusive choices plus Custom Answer: Reference-only (example: inspect source, configuration, and tests as evidence; do not edit or run validations), Edit (example: update approved repository files; do not run validations), Edit-and-test (Recommended; example: make approved changes and run focused validations, including tests), Validation-only (example: run approved validations without editing), and Unavailable (example: record a blocker because the repository cannot be accessed). Include Custom Answer (example: a different boundary such as edit only one approved folder). Recommend Edit-and-test with the justification that it permits normal delivery work and focused evidence; it grants capability, not authorization to change source outside the active command scope. Record each repository's role, local path, workspace availability, named access requirement, and evidence. Treat the current workspace as a proposed target until an explicit user confirmation or current canonical evidence names that repository and boundary. - Never edit a reference-only, validation-only, release-coordination, or unavailable repository. Never validate a reference-only, release-coordination, or unavailable repository. Validate a validation-only repository only when its recorded validation permission allows it. - \ No newline at end of file + Load before reading, editing, or validating any repository other than the one holding the devspec scaffold, whenever source scope is not already confirmed by current canonical evidence, and whenever the work depends on more than one repository. + When a repository path is not already evidenced, ask for one repository name or local path at a time in a free-form text input. Show at least two examples such as `D:\Code\orders-api` and `D:\Code\orders-web`, and allow the developer to type another path. Confirm the path before asking about access, then repeat for each additional repository. + After each path is confirmed, ask one interactive question: “What access requirement applies to <repository>?” Offer every named access requirement from devspec/glossary.md as an exclusive choice with a short example — reference-only (inspect source, configuration, and tests as evidence), edit (update approved files without running validations), edit-and-test (make approved changes and run focused validations), validation-only (run approved validations without editing), release-coordination (coordinate release information without inspecting the repository), and unavailable (the repository cannot be reached) — plus Custom Answer for a narrower boundary such as editing one approved folder. + Mark exactly one choice recommended and justify it. Recommend the least-privilege requirement that satisfies the current command; where normal delivery work applies that is edit-and-test, because it permits focused change and evidence. A granted requirement is capability, not authorization to change source outside the active command scope. + Record each repository's role, local path, workspace availability, named access requirement in the lowercase form devspec/glossary.md uses, and the evidence for it, in devspec/foundation/codebase-structure.md. + Honor exactly the recorded requirement and nothing wider. Never inspect a release-coordination or unavailable repository. Never edit a reference-only, validation-only, release-coordination, or unavailable repository. Never validate a reference-only, edit, release-coordination, or unavailable repository. + diff --git a/devspec/protocols/revision.xml b/devspec/protocols/revision.xml new file mode 100644 index 0000000..2539980 --- /dev/null +++ b/devspec/protocols/revision.xml @@ -0,0 +1,6 @@ + + Load for every work-item command. The scope revision decides which records are current and which are history. + meta.md `scope_revision` starts at 1 and increases only when devspec.changerequest accepts a related requirement. Finalization, task, implementation, and review records each carry the revision they belong to. Read and write only the current revision. Each command stamps its own key in meta.md as it completes: devspec.finalize sets `finalized_revision`, devspec.tasks `planned_revision`, devspec.implement `implemented_revision`, and devspec.review `reviewed_revision`. A key behind `scope_revision` means that stage must run again. + An accepted change request increments the revision, marks the earlier finalization, task, implementation, and review sections superseded, and preserves their evidence unchanged. Fresh finalization is required before planning or implementation continues. + Reject stale or superseded readiness, task, or implementation evidence instead of updating it in place, and record the mismatch as the reason. + diff --git a/devspec/protocols/run.xml b/devspec/protocols/run.xml index 631c540..a7cae43 100644 --- a/devspec/protocols/run.xml +++ b/devspec/protocols/run.xml @@ -1,6 +1,7 @@ - Before every command, confirm single-repository or multi-repository scope from either explicit developer confirmation or current canonical evidence. Treat the current workspace as proposed, never proof. When repository evidence is absent, collect one repository name or local path at a time through a free-form text input with two path examples and a custom typed value; do not present access choices until that path is confirmed. After each path is confirmed, ask exactly one interactive named access-requirement question with two to five exclusive choices, an example for each, Custom Answer, and exactly one recommended least-privilege choice with justification. Record that repository's role and named access requirement; repeat path collection then access confirmation for each additional repository. A new repository may explicitly confirm that no source exists yet. Do not inspect or change source until this sequence is complete. Then validate required input, target artifact, stage, and access before output. - Before material questions, edits, validation, retries, or handoff, save stage, run state, last action, resume reference, and exactly one next action in the command's state record. + Load with every command. It governs preflight, checkpoints, resumption, and closing report. + Before every command, confirm single-repository or multi-repository scope from either explicit developer confirmation or current canonical evidence. Treat the current workspace as proposed, never proof. When repository evidence is absent, complete the repo-access protocol before reading, editing, or validating source; a new repository may explicitly confirm that no source exists yet. Do not inspect or change source until that sequence is complete. Then validate required input, target artifact, stage, and access before output. + Before material questions, edits, validation, retries, or handoff, save stage, run state, last action, resume reference, and exactly one next action in the command's state record. For foundation work the state record and the decision record are the same file, holding both a Run State row and a Decisions row. devspec/work-items/<id>/meta.md devspec/foundation/decisions.md @@ -8,6 +9,6 @@ For a work-item continuation, use current-work-item before validating stage. Dispatch only the saved next action; do not skip a stage. Resume paused work when prerequisites hold. Clear or recover stale local context, and ask one interactive selection question when multiple work items or a stopped state make continuation ambiguous. - Record the material blocker and continuation condition; retry only when that condition changes or the user directs it. + Record the material blocker and continuation condition; retry only when that condition changes or the developer directs it. Report artifact, outcome, blocker if any, and exactly one registered next action. \ No newline at end of file diff --git a/devspec/protocols/security.xml b/devspec/protocols/security.xml new file mode 100644 index 0000000..fc2becc --- /dev/null +++ b/devspec/protocols/security.xml @@ -0,0 +1,8 @@ + + Load whenever a command establishes, applies, or verifies the project security baseline. + Maintain exactly one OWASP Top 10:2025 baseline, in devspec/foundation/rules.md. For every category record its applicability (applicable, limited, out-of-scope, or unknown), the required project control, and the enforcement or evidence that backs it. Record gaps and unknowns rather than omitting a category. + Record limited or internal-only exposure only when enforceable access, deployment, or network evidence supports it; otherwise record the category as applicable and note the reduced exposure in its evidence. A known unresolved vulnerability is never closed as not applicable because access is limited, authenticated, or internal-only. + Record project-native evidence for every applicable control, expressed through the project's own code, tests, configuration, or pipeline rather than a claim in an artifact. + A suspected false positive or not-applicable finding requires ask the developer one material confirmation question, then a record of the explicit confirmation, its rationale, the enforceable supporting evidence, and a material-change revalidation trigger covering related code, access control, deployment, integration, and exposure. It remains proposed until a reviewer confirms it. + Do not mark a work item ready, and do not record an accepted review, while an applicable category, its required control, its planned validation, or an exception confirmation is unresolved. + diff --git a/devspec/protocols/state.xml b/devspec/protocols/state.xml new file mode 100644 index 0000000..5fdb941 --- /dev/null +++ b/devspec/protocols/state.xml @@ -0,0 +1,10 @@ + + Load with every command. This is the shared vocabulary that every state record, transition, and closing report uses. devspec/lifecycle.md holds the legal route graph and devspec/glossary.md the full term list. + Read devspec/foundation/repository-state.md before the first foundation command. State `existing` starts at devspec.extract; state `new` starts at devspec.projectcontext. Do not infer the state from the presence of source. + `active` means the registered next command may run. `paused` is an explicit user pause. `blocked` means exactly one active material decision is recorded and the next command is devspec.clarify. `stopped` requires a new user direction before resuming. `complete` is terminal and must record `next: none`, which is itself the one reported next action. + Work-item stages are intake, grooming, finalization, tasks, implementation, review, and complete. A quickfix advances through triage, implementation, and validation inside its single run, then ends at complete or routed; only complete, triage, and routed appear as transition stages. Foundation and extraction work uses the foundation stage. A command that returns to its caller reports the caller's stage. + A task is pending, in-progress, blocked, complete, or superseded. A task becomes complete only after its recorded validation passes. + Label every durable fact confirmed, observed, inferred, or blocked. Never record an inferred fact as confirmed. + The changed-work baseline is what an implementation is measured from: the base revision, the comparison revision or an explicit working-tree marker, and the list of changed paths. devspec.implement records it; devspec.review verifies the recorded baseline before judging the work. + `return-to-caller` and `resume-origin` both mean: continue the command named in this record's saved resume reference, at its saved stage and next action. Never infer a caller. When no resume reference is saved, report the outcome and stop instead of guessing a next command. + diff --git a/devspec/protocols/work.xml b/devspec/protocols/work.xml index 46b9c9d..f27001f 100644 --- a/devspec/protocols/work.xml +++ b/devspec/protocols/work.xml @@ -1,7 +1,8 @@ + Load with every command. It governs what may be touched and how a change is made. Select the smallest affected area and direct dependencies; exclude generated application outputs, dependency directories, caches, and unrelated source. Canonical `devspec/` artifacts remain in scope when the command owns them. When a target artifact, required state record, or its parent folder is missing, create it from the matching _template artifact before editing. Resolve foundation artifacts through devspec/foundation/template-map.md. For a new work item, initialize every file from devspec/work-items/_template, including meta.md and decisions.md. For a new quickfix, initialize devspec/quickfixes/QF-###-slug.md from devspec/quickfixes/_template.md. Never overwrite an existing artifact. - Label durable facts as confirmed, observed, inferred, or blocked. + Apply the evidence labels defined in the state protocol to every durable fact this command records. For source changes only, inspect the affected behavior and relevant callers before editing; for defects, identify the underlying cause within approved scope. These checks do not require source exploration for unrelated artifact work. Choose the smallest safe change that satisfies approved requirements and project conventions. Prefer suitable existing project code, standard-library or platform capabilities, and installed dependencies before introducing custom code. New dependencies or abstractions require a concrete present need; do not add speculative ones. diff --git a/devspec/quickfixes/_template.md b/devspec/quickfixes/_template.md index 7e7173d..de1b7ef 100644 --- a/devspec/quickfixes/_template.md +++ b/devspec/quickfixes/_template.md @@ -4,6 +4,7 @@ type: bug stage: triage run: active scope: [] +last: none resume: none next: select scope updated: @@ -17,8 +18,11 @@ updated: - Validation: - Outcome: -- Route: complete | devspec.clarify | devspec.story +- Route: complete | blocked (`devspec.clarify`) | routed (`devspec.story`) + ## Decisions +One row per material question, in the shape `devspec/protocols/ask.xml` requires. + | ID | Material question | Evidence | Impact | Choices | Recommended | Recommendation justification | Applicability | Canonical rule link | Answer or skip reason | Status | -|---|---|---|---|---|---|---|---|---|---|---| \ No newline at end of file +|---|---|---|---|---|---|---|---|---|---|---| diff --git a/devspec/work-items/_template/decisions.md b/devspec/work-items/_template/decisions.md index c1911d4..96dfd36 100644 --- a/devspec/work-items/_template/decisions.md +++ b/devspec/work-items/_template/decisions.md @@ -1,4 +1,6 @@ # Decisions +One row per material question, in the shape `devspec/protocols/ask.xml` requires. Record the row before waiting for an answer. + | ID | Material question | Evidence | Impact | Choices | Recommended | Recommendation justification | Applicability | Canonical rule link | Answer or skip reason | Status | -|---|---|---|---|---|---|---|---|---|---|---| \ No newline at end of file +|---|---|---|---|---|---|---|---|---|---|---| diff --git a/devspec/work-items/_template/finalize.md b/devspec/work-items/_template/finalize.md index 46a01ba..87e23bc 100644 --- a/devspec/work-items/_template/finalize.md +++ b/devspec/work-items/_template/finalize.md @@ -7,7 +7,7 @@ ## Foundation Traceability -| Foundation artifact | Relevant convention, area, boundary, or rule | Applicability or boundary | Evidence | +| Foundation artifact or `CP-###` principle | Relevant convention, area, boundary, or rule | Applicability or boundary | Evidence | |---|---|---|---| ## Architecture and Diagram Trace diff --git a/devspec/work-items/_template/implement.md b/devspec/work-items/_template/implement.md index a2911cd..d83665c 100644 --- a/devspec/work-items/_template/implement.md +++ b/devspec/work-items/_template/implement.md @@ -12,4 +12,4 @@ | Finding ID | OWASP category | Disposition | Developer confirmation | Rationale and enforceable evidence | Validation evidence | Revalidate when | |---|---|---|---|---|---|---| -Use `proposed-not-applicable` or `proposed-false-positive` only for a suspected finding. A real unresolved vulnerability remains `unresolved`; do not relabel it as an exception. \ No newline at end of file +Use `proposed-not-applicable` or `proposed-false-positive` only for a suspected finding. A real unresolved vulnerability remains `unresolved`; do not relabel it as an exception. diff --git a/devspec/work-items/_template/review.md b/devspec/work-items/_template/review.md index 28adaaa..2b084a0 100644 --- a/devspec/work-items/_template/review.md +++ b/devspec/work-items/_template/review.md @@ -15,6 +15,8 @@ | Architecture or diagram reference | Expected implementation or validation impact | Evidence | Status | Finding or action | |---|---|---|---|---| +Use `implemented-as-decided`, `intentionally-superseded` with a recorded replacement, or `not-verified`. Treat an unrecorded contradiction as rework-required. + ## Security Verification | Finding ID | OWASP category | Disposition | Developer confirmation | Rationale and enforceable evidence | Reviewer confirmation | Revalidate when | Status or action | @@ -24,5 +26,5 @@ Use `remediated`, `confirmed-not-applicable`, `confirmed-false-positive`, or `un ## Findings -| Finding | Severity | Evidence | Required action | -|---|---|---|---| \ No newline at end of file +| Finding | Location | Severity | Evidence | Required action | +|---|---|---|---|---| diff --git a/devspec/work-items/_template/story.md b/devspec/work-items/_template/story.md index 0390d86..fba7218 100644 --- a/devspec/work-items/_template/story.md +++ b/devspec/work-items/_template/story.md @@ -32,4 +32,4 @@ Record a concise, redacted summary of the provider title, description, acceptanc ## Change Requests | ID | Request | Status | -|---|---|---| \ No newline at end of file +|---|---|---| diff --git a/devspec/work-items/_template/tasks.md b/devspec/work-items/_template/tasks.md index 1b608ee..ff89c4a 100644 --- a/devspec/work-items/_template/tasks.md +++ b/devspec/work-items/_template/tasks.md @@ -4,4 +4,4 @@ - Status: active | superseded | ID | Task | Scope | Depends on | Source justification and foundation or architecture trace | Decision or rule IDs | Validation | Done condition | Status | -|---|---|---|---|---|---|---| \ No newline at end of file +|---|---|---|---|---|---|---|---|---| diff --git a/docs/assets/delivery-routes.svg b/docs/assets/delivery-routes.svg index 76f656d..ecde7ea 100644 --- a/docs/assets/delivery-routes.svg +++ b/docs/assets/delivery-routes.svg @@ -1 +1 @@ -Delivery routes for quick fixes and work itemsA localized low-risk request uses Quickfix, focused validation, and a recorded outcome. Broader or higher-risk work follows Story, optional Grooming, Finalize, Tasks, Implement, and Review. Clarify resumes the blocked stage.DEVSPEC LITE / DELIVERYTake the smallest safe routeQuickfix handles one localized, low-risk concern. Scope, risk, or durable design needs a traceable work item.LOCAL / LOW-RISK CHANGEPLANNED WORK ITEMRequestone stated needLocal +low risk?quickfixtargeted discoveryfocused validationdirect evidenceQF record + outcomeresume state includedstorygrooming*finalizetasksimplementreviewYESNO / RISKblocker: clarify, then resume the originating stage* SUGGEST GROOMING ONLY WHEN AMBIGUITY, RISK, OR ACCEPTANCE CRITERIA ARE MATERIALLY INCOMPLETE +Delivery routes for quick fixes and work itemsA localized low-risk request uses Quickfix, focused validation, and a recorded outcome. Broader or higher-risk work follows Story, optional Grooming, Finalize, Tasks, Implement, and Review. Clarify resumes the blocked stage.DEVSPEC LITE / DELIVERYTake the smallest safe routeQuickfix handles one localized, low-risk concern. Scope, risk, or durable design needs a traceable work item.LOCAL / LOW-RISK CHANGEPLANNED WORK ITEMRequestone stated needLocal +low risk?quickfixtargeted discoveryfocused validationdirect evidenceQF record + outcomeresume state includedstorygrooming*finalizetasksimplementreviewYESNO / RISKblocker: clarify, then resume the originating stage* SUGGEST GROOMING ONLY WHEN AMBIGUITY, RISK, OR ACCEPTANCE CRITERIA ARE MATERIALLY INCOMPLETE diff --git a/docs/assets/diagram-route.svg b/docs/assets/diagram-route.svg new file mode 100644 index 0000000..f1f53fb --- /dev/null +++ b/docs/assets/diagram-route.svg @@ -0,0 +1 @@ +Diagram command route for Devspec LiteA queued candidate or subject is duplicate-checked, matched to a diagram type and family template, generated as SVG, validated, then indexed in the queue and overview before control returns to the caller. Missing evidence records a blocker and routes to devspec.clarify, which resumes the queued subject.DEVSPEC LITE / DIAGRAMGenerate one diagram, onceA queued candidate becomes one validated, indexed diagram. Anything unproven becomes a clarify blocker instead.GENERATEBLOCKEDNO EVIDENCEclarify, then resume the queued subjectQueue rowDIA-### or subjectDuplicate checkcompare subjectsSelect typefamily templateGenerate SVGmotion optionalValidate XMLstandalone checkIndex outputqueue + overviewCallerEvidence blockerdevspec.clarifyONE DIAGRAM PER RUN - QUEUE STATE IS DURABLE - CALLER LIFECYCLE STAGE IS NEVER CHANGED diff --git a/docs/assets/foundation-routes.svg b/docs/assets/foundation-routes.svg index c7e4d4f..4db8b4d 100644 --- a/docs/assets/foundation-routes.svg +++ b/docs/assets/foundation-routes.svg @@ -1 +1 @@ -Foundation routes for new and existing repositoriesNew repositories begin with project context. Existing repositories use Extract to create the complete evidence-backed baseline.DEVSPEC LITE / FOUNDATIONChoose the correct repository routeNew projects are documented intentionally. Existing systems are documented end-to-end from observed evidence.NEW REPOSITORYEXISTING REPOSITORYNew repositoryno source to inspectExisting repositorysource already presentextractcomplete baselineprojectcontextpurpose + boundariestechstackobserved toolingcodebase-structureroots + boundariesstandards + rulesconstraintsNEW: AUTHOR FOUNDATION COMMANDS • EXISTING: EXTRACT CREATES THE COMPLETE BASELINE +Foundation routes for new and existing repositoriesNew repositories begin with project context. Existing repositories use Extract to create the complete evidence-backed baseline.DEVSPEC LITE / FOUNDATIONChoose the correct repository routeNew projects are documented intentionally. Existing systems are documented end-to-end from observed evidence.NEW REPOSITORYEXISTING REPOSITORYNew repositoryno source to inspectExisting repositorysource already presentextractcomplete baselineprojectcontextpurpose + boundariestechstackobserved toolingcodebase-structureroots + boundariescoding-standardsconventionsrulesconstraintsNEW: AUTHOR FOUNDATION COMMANDS • EXISTING: EXTRACT CREATES THE COMPLETE BASELINE diff --git a/docs/assets/manual-copy-flow.svg b/docs/assets/manual-copy-flow.svg index 359ff0d..f245271 100644 --- a/docs/assets/manual-copy-flow.svg +++ b/docs/assets/manual-copy-flow.svg @@ -1,14 +1,15 @@ Manual copy flow for Devspec Lite - A developer checks out the latest main branch, chooses one agent profile, copies the canonical artifacts into a target repository, verifies the files, and commits them. Updates repeat the comparison and copy steps without requiring the CLI. - + A developer checks out the latest main branch, chooses one agent profile, copies the canonical artifacts into a target repository, resets the project records that the checkout carries, sets the target repository state, then verifies and commits. Updates repeat the comparison and copy steps without requiring the CLI. + DEVSPEC LITE / MANUAL COPYCopy the latest main profile without an installerMain-branch files are canonical. Python and the CLI are optional, not required. - Check out mainlatest canonical files - Choose profileone agent host - Copy required filesdevspec + wrapper - Verify pathsmanifest + wrapper - Commit target filesstart the workflow - latest main → compare, copy approved changes, commitNO PYTHON • NO CLI • NO PACKAGE MANAGER • PRESERVE LOCAL CUSTOMIZATIONS - \ No newline at end of file + Check out mainlatest canonical files + Choose profileone agent host + Copy required filesdevspec + wrapper + Reset project dataqueue, overview, QF + Set repository statenew or existing + Verify and commitmanifest + reset table + latest main → compare, copy approved changes, reset project data, commitNO PYTHON • NO CLI • NO PACKAGE MANAGER • PRESERVE LOCAL CUSTOMIZATIONS + diff --git a/docs/command-examples.md b/docs/command-examples.md index e85522b..6f15de3 100644 --- a/docs/command-examples.md +++ b/docs/command-examples.md @@ -9,7 +9,7 @@ No `devspec.*` command treats the agent's current workspace as proof of its repo When evidence is absent, collect scope in this order for every command: 1. Ask one free-form repository path question. The text input should say, “Which repository is in scope? Enter its local path or name.” Show examples such as `D:\Code\orders-api` and `D:\Code\orders-web`, and let the developer type another value. Do not ask about access yet. -2. After the path is confirmed, ask: **What access requirement applies to `D:\Code\orders-api`?** Always show these choices: **Reference-only** — inspect source, configuration, and tests as evidence; do not edit or run validations. **Edit** — update approved repository files; do not run validations. **Edit-and-test (Recommended)** — make approved changes and run focused validations, including tests. **Validation-only** — run approved validations without editing. **Unavailable** — record a blocker because the repository cannot be accessed. **Custom Answer** — describe another boundary, for example edit only one approved folder. `Edit-and-test` grants normal delivery capability; the active command still controls whether source is changed. +2. After the path is confirmed, ask: **What access requirement applies to `D:\Code\orders-api`?** Always show these choices: **Reference-only** — inspect source, configuration, and tests as evidence; do not edit or run validations. **Edit** — update approved repository files; do not run validations. **Edit-and-test** — make approved changes and run focused validations, including tests. Recommended for ordinary delivery work; for a repository outside the change, recommend the least privilege that still satisfies the command. **Validation-only** — run approved validations without editing. **Release-coordination** — coordinate release information without inspecting the repository. **Unavailable** — record a blocker because the repository cannot be accessed. **Custom Answer** — describe another boundary, for example edit only one approved folder. `Edit-and-test` grants normal delivery capability; the active command still controls whether source is changed. 3. Repeat the path question and then the access question for each additional repository. Record the scaffold path, repository role, and the separate read, edit, and validation permissions before continuing. For a new project, the path answer may say `D:\Code\inventory — no source exists yet`; access is still confirmed after the path. @@ -27,7 +27,7 @@ The scaffold location is not a source-access grant. When it is outside the code ## Work with multiple repositories -Name a primary repository that owns the change record, then list every dependent repository. For each one, state a local path plus one named access requirement (`reference-only`, `edit`, `edit-and-test`, `validation-only`, `release-coordination`, or `unavailable`). For example, a documentation repository might be `read/edit/validate`; a production-infrastructure repository may be `read` only. The agent must not infer missing permissions, edit a reference-only repository, or validate it. +Name a primary repository that owns the change record, then list every dependent repository. For each one, state a local path plus one named access requirement (`reference-only`, `edit`, `edit-and-test`, `validation-only`, `release-coordination`, or `unavailable`). For example, a documentation repository might be `edit-and-test`; a production-infrastructure repository may be `reference-only`. The agent must not infer missing permissions. It honors exactly the recorded requirement, as `devspec/protocols/repo-access.xml` defines: an `edit` repository is never validated, and a `release-coordination` one is never even inspected. ## Intake from MCP providers diff --git a/docs/how-to.md b/docs/how-to.md index 2655834..0272eab 100644 --- a/docs/how-to.md +++ b/docs/how-to.md @@ -1,6 +1,6 @@ # How to use Devspec Lite -This guide uses real developer situations to show which agent command to run, when to run it, and what happens next. Run `devspec-lite init` and `devspec-lite doctor` first; then invoke the listed `devspec.*` command from your configured agent host. +This guide uses real developer situations to show which agent command to run, when to run it, and what happens next. Install the framework by either setup route, then invoke the listed `devspec.*` command from your configured agent host. The CLI is one route, not a prerequisite. Git-tracked `devspec/` artifacts are the project record. Do not skip a command because the answer is present in chat: record the evidence or decision in the matching artifact. @@ -8,7 +8,7 @@ Git-tracked `devspec/` artifacts are the project record. Do not skip a command b ## Choose the scaffold and confirm source scope -The `devspec/` scaffold may live in the code repository or in a separate Git repository that records a multi-repository change. The directory open in the agent host is the scaffold location, not automatic permission to inspect source. Before every `devspec.*` command, confirm single-repository or multi-repository scope in two steps when current evidence is absent: first ask for one repository name or local path in a free-form text input with examples; after that path is confirmed, ask one interactive named access-requirement question with examples, Custom Answer, and one least-privilege recommendation. Repeat the two questions for each repository, recording its role and access requirement. A new repository may explicitly confirm that no source exists yet. Current canonical evidence may replace a repeated confirmation only when it records the same facts. +The `devspec/` scaffold may live in the code repository or in a separate Git repository that records a multi-repository change. The directory open in the agent host is the scaffold location, not automatic permission to inspect source. Before every `devspec.*` command, confirm single-repository or multi-repository scope when current evidence is absent. The agent collects each repository path, then asks one access-requirement question per repository, as `devspec/protocols/repo-access.xml` defines. A new repository may explicitly confirm that no source exists yet. Current canonical evidence may replace a repeated confirmation only when it records the same facts. Use the [beginner command examples](command-examples.md) to choose a scaffold layout, confirm one or more repository boundaries, and copy a safe first prompt for every command. @@ -18,21 +18,19 @@ For provider-backed story intake, pass one GitHub, Azure DevOps, Jira, GitLab, o | Developer situation | Run | Then | |---|---|---| -| Existing codebase with no trusted Devspec baseline | `devspec.extract` | Start a story after the baseline is ready. | -| Brand-new repository | `devspec.projectcontext` | Continue the new-foundation route. | +| `devspec/foundation/repository-state.md` says `existing` | `devspec.extract` | Start a work item after the baseline is ready. | +| `devspec/foundation/repository-state.md` says `new` | `devspec.projectcontext` | Continue the new-foundation route. | | New feature, API contract, migration, security change, or multiple concerns | `devspec.story` | Groom when needed, then finalize, plan, implement, and review. | -| One local, low-risk correction | `devspec.quickfix` | Complete directly or route to a story. | +| One local, low-risk correction | `devspec.quickfix` | Complete directly, clarify a blocker, or route to a story. | | A recorded material decision blocks current work | `devspec.clarify` | Resume the exact saved command. | | A related requirement arrives after finalization | `devspec.changerequest` | Re-finalize the new scope revision. | -| One evidence-backed architecture or workflow visual is needed | `devspec.diagram` | Return to the caller's workflow. | -| A known foundation artifact needs a narrow update | Its matching foundation command | Return to the caller after the update. | +| One evidence-backed architecture or workflow visual is needed | `devspec.diagram` | Return to the caller's workflow, or clarify an evidence blocker. | +| A known foundation artifact needs a narrow update | Its matching foundation command | Return to the caller, or clarify an evidence blocker. | ## Continue current work without an ID Say `continue` or run the next work-item command without an ID. Devspec resolves private per-worktree context, reads the selected `meta.md` next action, and resumes only that action. If context is missing or multiple active stories exist, it asks you to select one; use an ID only to switch stories explicitly. - - ## 1. Map an existing service before changing it **Scenario.** You inherit an orders API and need to add an export, but its integrations, conventions, and security controls are not documented. @@ -44,10 +42,10 @@ uvx devspec-lite init --target . --profile all --repo-state existing uvx devspec-lite doctor --target . --profile all ``` -2. Confirm source scope in order: first enter the repository path or name in the free-form prompt, then choose a named access requirement after the path is confirmed. Show all standard access choices and recommend `edit-and-test`; that grants normal delivery capability, while the active command still prevents unnecessary source changes. If a team needs a narrow exception—such as “edit but run only lint”—use **Custom Answer**. The current workspace is only a proposed target; current canonical evidence may replace these questions only when it records the same path, role, and permissions. -3. In your agent host, run a scoped request such as `/devspec.extract Source scope confirmed: orders API at D:\Code\orders-api (primary, read/edit/validate).` +2. Confirm source scope in order: first enter the repository path or name in the free-form prompt, then choose a named access requirement after the path is confirmed. Show all six named access choices. Exactly one is recommended, with a justification, and it is the least privilege that satisfies the command: for ordinary delivery work that is `edit-and-test`, but a repository you only read as evidence should be recommended `reference-only`. If a team needs a narrow exception—such as “edit but run only lint”—use **Custom Answer**. The current workspace is only a proposed target; current canonical evidence may replace these questions only when it records the same path, role, and permissions. +3. In your agent host, run a scoped request such as `/devspec.extract Source scope confirmed: orders API at D:\Code\orders-api (primary, `edit-and-test`).` 4. It inspects only the confirmed source, tests, configuration, and documentation, then creates the evidence-backed foundation and prepares a list of applicable diagrams. -5. At extraction closure, it shows the list and asks: **“Do you want me generate all the possible diagrams?”** Choose **Yes** to generate every listed diagram, **No** to leave the list prepared, or enter selected IDs or subjects. For example, enter `DIA-001, DIA-004` to generate only those two. +5. At extraction closure, it shows the list and asks: **“Do you want me to generate all the possible diagrams?”** Choose **Yes** to generate every listed diagram, **No** to leave the list prepared, or enter selected IDs or subjects. For example, enter `DIA-001, DIA-004` to generate only those two. 6. Any prepared diagram can be generated later with `/devspec.diagram `, for example `/devspec.diagram DIA-002`. Static SVG is the default. Use `/devspec.diagram DIA-002 motion=explain` only when the confirmed sequence, flow, or state transition benefits from explanatory motion. 7. If material evidence or source scope is unavailable, answer the recorded question through `/devspec.clarify`. Otherwise, begin the requested change with `/devspec.story Add customer export`. @@ -69,7 +67,7 @@ uvx devspec-lite doctor --target . --profile all **Scenario.** Your team has created an empty service repository and wants a durable engineering baseline before accepting feature work. 1. Initialize it with `--repo-state new`. -2. Confirm the repository scope before the first command, for example: `Scope confirmed: scaffold and planned source at D:\Code\inventory; no source exists yet; read/edit/validate.` +2. Confirm the repository scope before the first command, for example: `Scope confirmed: scaffold and planned source at D:\Code\inventory; no source exists yet; `edit-and-test`.` 3. Run these agent commands in order: ```text @@ -83,7 +81,7 @@ uvx devspec-lite doctor --target . --profile all 4. Use `/devspec.coding-standards` to add a team-defined standard at any time as a targeted update. Include a concise example that future implementations should follow; the artifact distinguishes it from an observed source convention. 5. Use `/devspec.diagram ` only when a specific evidence-backed visual is needed during this route. Add `motion=explain` only for a confirmed sequence, flow, or state transition; otherwise keep the static default. -**What to expect.** Each command records its artifact and advances to the next command. After `rules`, the foundation is ready for `/devspec.story`. +**What to expect.** Each command records its artifact and advances to the next command, or records an evidence blocker and routes to `/devspec.clarify`. After `devspec.rules`, the foundation is ready for `/devspec.story`. ## 3. Deliver a feature from request to accepted review @@ -116,13 +114,13 @@ uvx devspec-lite doctor --target . --profile all 3. Start the story from the primary repository and state the repository roles, local paths, and read, edit, and validation permissions in the request. For example: ```text -/devspec.story Add checkout address validation. Primary: orders-api at D:\Code\orders-api (read/edit/validate). Dependent UI: orders-web at D:\Code\orders-web (read/edit/validate). +/devspec.story Add checkout address validation. Primary: orders-api at D:\Code\orders-api (`edit-and-test`). Dependent UI: orders-web at D:\Code\orders-web (`edit-and-test`). ``` 4. When a command needs the second repository, it uses the `repo-access` protocol before reading, editing, or validating it. Record a repository as reference-only or validation-only when that is its real boundary. 5. Run `/devspec.extract` instead of the individual foundation commands when you need an evidence-backed baseline for an explicitly scoped multi-repository existing system. -**What to expect.** There is no separate multi-repository configuration command. The approved roles, paths, and access permissions are the configuration, recorded in canonical Devspec artifacts. Never infer edit access, and never validate a reference-only or unavailable repository. +**What to expect.** There is no separate multi-repository configuration command. The approved roles, paths, and access permissions are the configuration, recorded in canonical Devspec artifacts. Never infer access from a path. Honor exactly the recorded requirement: never inspect a `release-coordination` or `unavailable` repository; never edit a `reference-only`, `validation-only`, `release-coordination`, or `unavailable` one; and never validate a `reference-only`, `edit`, `release-coordination`, or `unavailable` one. `devspec/protocols/repo-access.xml` is the authority. - Next command for a new change: `/devspec.story `. @@ -150,7 +148,6 @@ uvx devspec-lite doctor --target . --profile all **Scenario.** Finalization is blocked because the required data-retention period is unknown. - 1. Run `/devspec.clarify` and answer the one recorded decision. **What to expect.** Clarification resumes the exact saved stage and next command. It does not add new scope or bypass a required review. diff --git a/docs/manual-copy.md b/docs/manual-copy.md index f192780..d0fd34d 100644 --- a/docs/manual-copy.md +++ b/docs/manual-copy.md @@ -14,11 +14,11 @@ The `main` checkout supplies the canonical `devspec/` directory and prebuilt age ## 2. Copy one profile -Copy `devspec/` and the folder or file for the agent host into the target repository. +Copy `devspec/` and the folder or file for the agent host into the target repository. Copy only the listed paths. In particular do not copy `.github/workflows/` — those are Devspec Lite's own release pipelines, and one of them requests publishing credentials. | Profile | Copy from the `main` checkout | Copy into the target repository | |---|---|---| -| Copilot | `devspec/`, `.github/` | `devspec/`, `.github/` | +| Copilot | `devspec/`, `.github/prompts/`, `.github/agents/` | `devspec/`, `.github/prompts/`, `.github/agents/` | | Codex | `devspec/`, `AGENTS.md` | `devspec/`, `AGENTS.md` | | Claude | `devspec/`, `.claude/` | `devspec/`, `.claude/` | | Cursor | `devspec/`, `.cursor/` | `devspec/`, `.cursor/` | @@ -27,6 +27,15 @@ Copy `devspec/` and the folder or file for the agent host into the target reposi Do not pre-copy individual foundation or work-item templates. When an agent needs a missing target artifact, the shared `work` protocol creates it from the matching `_template`; creating a work item initializes every file in `devspec/work-items/_template`, including `meta.md`. +The `main` checkout also carries Devspec Lite's own project records, which the CLI never installs. After copying, reset these in the target so it starts empty: + +| Path | Action in the target repository | +|---|---| +| `devspec/architecture/artifact-queue.md` | Replace with `devspec/architecture/_template/artifact-queue.md` | +| `devspec/architecture/overview.md` | Replace with `devspec/architecture/_template/overview.md` | +| `devspec/quickfixes/QF-*.md` | Delete; keep `README.md` and `_template.md` | +| `devspec/foundation/repository-state.md` | Replace as described in step 3 | + ## 3. Set the target repository state After copying `devspec/`, replace `devspec/foundation/repository-state.md` with the state that matches the target repository. Do not retain the state from the `main` checkout. @@ -51,7 +60,7 @@ Use this exact Markdown structure: ## 4. Verify and commit -Verify that every path listed in `devspec/install-manifest.txt` exists, that the selected agent wrapper is present, and that `devspec/foundation/repository-state.md` has the target's intended state and start command. Compare any same-named target wrapper before replacing it, then commit the copied files with the target repository. +Verify that every glob pattern in `devspec/install-manifest.txt` resolves to at least one copied file, that the selected agent wrapper is present, that `devspec/foundation/repository-state.md` has the target's intended state and start command, and that every row in step 2's reset table has been applied. Compare any same-named target wrapper before replacing it, then commit the copied files with the target repository. ## 5. Update manually diff --git a/docs/quickstart.md b/docs/quickstart.md index 9f3dd0a..b92a3cd 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -20,11 +20,15 @@ Use a narrower profile such as `copilot`, `codex`, `claude`, `cursor`, `gemini`, ## 2. Start the right workflow +Every `devspec.*` command begins by confirming repository scope: it asks for each repository path, then one named access requirement per repository. Answer those before the command inspects any source. The route itself comes from `devspec/foundation/repository-state.md`, which `init` writes from `--repo-state`. + - New repository: author the foundation intentionally with `devspec.projectcontext → devspec.techstack → devspec.codebase-structure → devspec.coding-standards → devspec.rules`. -- Existing repository: run `devspec.extract` once. It creates the evidence-backed technical, workflow, and rules baseline, prepares the possible-diagram list, and asks whether to generate all or selected diagrams. Select **No** to keep only the list; later generate a static SVG with `/devspec.diagram DIA-002`, or request an evidence-backed animated explanation with `/devspec.diagram DIA-002 motion=explain`. +- Existing repository: run `devspec.extract` once. It creates the evidence-backed technical, business, workflow, and rule baseline, prepares the possible-diagram list, then asks one question with four answers: generate all, prepare the list only, choose specific diagrams, or a custom answer. Choosing to prepare the list only keeps the candidates without generating them; later generate a static SVG with `/devspec.diagram DIA-002`, or request an evidence-backed animated explanation with `/devspec.diagram DIA-002 motion=explain`. Work route: `devspec.story → devspec.grooming` when needed `→ devspec.finalize → devspec.tasks → devspec.implement → devspec.review`. +When a command reports a blocker, run `devspec.clarify`: it resolves the one recorded decision and resumes the exact saved command. When a related requirement arrives after finalization, run `devspec.changerequest` to append it and re-finalize the new scope revision. + Use `devspec.quickfix` only for one localized, low-risk change. It routes API contracts, migrations, authentication/security, and breaking changes to the full route. ## Workflow routes diff --git a/docs/setup-homebrew.md b/docs/setup-homebrew.md index 630b30e..f9db12f 100644 --- a/docs/setup-homebrew.md +++ b/docs/setup-homebrew.md @@ -1,6 +1,6 @@ # Homebrew setup -Use this route on macOS or Linux only after the Devspec Lite formula is published to a Homebrew tap. If the tap or formula is unavailable, choose [Python and uvx](setup-python.md) or [manual copy from `main`](manual-copy.md). +Use this route on macOS or Linux only after the Devspec Lite formula is published to a Homebrew tap. If the tap or formula is unavailable, use [manual copy from `main`](manual-copy.md); the [Python route](setup-python.md) needs the same release. ## Install @@ -22,7 +22,7 @@ devspec-lite init --target . --profile all --repo-state new devspec-lite doctor --target . --profile all ``` -Use a single-agent profile when the repository does not need every adapter wrapper. +Use a single-agent profile when the repository does not need every adapter wrapper: `copilot`, `codex`, `claude`, `cursor`, `gemini`, or `antigravity`. ## Next steps diff --git a/docs/setup-lifecycle.md b/docs/setup-lifecycle.md index ebe2dfa..0f23712 100644 --- a/docs/setup-lifecycle.md +++ b/docs/setup-lifecycle.md @@ -14,7 +14,7 @@ The terminal CLI is `devspec-lite`. After initialization, the installed agent wr |---|---|---| | Install the CLI | `uvx`, `pipx`, WinGet, or Homebrew | Choose one package-manager route below. | | Check version | `devspec-lite --version` | Confirms the installed CLI. | -| Initialize | `devspec-lite init --target --profile --repo-state ` | Copies canonical artifacts and selected wrappers. | +| Initialize | `devspec-lite init --target --profile --repo-state ` | Copies canonical artifacts and selected wrappers. | | Validate | `devspec-lite doctor --target --profile ` | Read-only check of contracts, protocols, templates, and wrappers. | | Compare installed framework files | `devspec-lite diff --target ` | Read-only drift report. | | Synchronize canonical artifacts | `devspec-lite sync --target --profile --dry-run` | Preview, then run without `--dry-run`; use `--force` only for reviewed framework-owned edits. | diff --git a/docs/setup-python.md b/docs/setup-python.md index adae95c..51f356e 100644 --- a/docs/setup-python.md +++ b/docs/setup-python.md @@ -1,6 +1,8 @@ # Python and uvx setup -Use this route on Windows, macOS, or Linux when Python 3.10 or newer is available. Choose `uvx` for one-off use, or `pipx` for a persistent CLI installation. To avoid installing Python or any CLI, use [manual copy from `main`](manual-copy.md). +Use this route on Windows, macOS, or Linux when Python 3.10 or newer is available. Choose `uvx` for one-off use, or `pipx` for a persistent CLI installation. + +The commands below need a published package. Until the first `v*` release is tagged, no CLI route resolves; use [manual copy from `main`](manual-copy.md), which never requires Python or a package manager. ## One-off use with uvx diff --git a/docs/setup-winget.md b/docs/setup-winget.md index 8e1eb8a..b75342b 100644 --- a/docs/setup-winget.md +++ b/docs/setup-winget.md @@ -1,6 +1,6 @@ # WinGet setup -Use this route on Windows only after the Devspec Lite package is published to WinGet. If the package is unavailable, choose [Python and uvx](setup-python.md) or [manual copy from `main`](manual-copy.md). +Use this route on Windows only after the Devspec Lite package is published to WinGet. If the package is unavailable, use [manual copy from `main`](manual-copy.md); the [Python route](setup-python.md) needs the same release. ## Install diff --git a/docs/upstream-command-parity.md b/docs/upstream-command-parity.md deleted file mode 100644 index cfe036b..0000000 --- a/docs/upstream-command-parity.md +++ /dev/null @@ -1,12 +0,0 @@ -# Upstream Command Parity - -Comparison baseline: [`speclabs/devspec` commit `b93275bb4cef4645bbeef72cb8357aa7a6f8adb7`](https://github.com/speclabs/devspec/blob/b93275bb4cef4645bbeef72cb8357aa7a6f8adb7/devspec/adapters/command-registry.md). - -| Upstream command | Devspec Lite | Status | -|---|---|---| -| extract, projectcontext, techstack, codebase-structure, coding-standards, rules | Same name | Supported | -| story, clarify, changerequest, finalize, tasks, implement, review, diagram | Same name | Supported | - -Lite additionally provides `devspec.grooming` and `devspec.quickfix`. Existing-system extraction remains deliberately comprehensive and routes directly to `devspec.story`; it does not repeat the upstream's five foundation commands. - -This release adds constitution candidates and explicit promotion, work-item clarification ledgers, finalization architecture traces, explicit process-flow batch diagrams, and the `diff`/`sync` installer lifecycle. `sync` never deletes retained obsolete files. diff --git a/docs/workflows.md b/docs/workflows.md index a13e83f..06b9af3 100644 --- a/docs/workflows.md +++ b/docs/workflows.md @@ -9,7 +9,7 @@ Use the smallest route that preserves a durable, reviewable record. Git-tracked - New repository: start with `devspec.projectcontext`. - Before every command, confirm the single-repository or multi-repository scope, including the scaffold location and each source repository's role, path, and permissions, unless current canonical evidence records it. The current workspace alone is not proof of scope. - Existing repository: run `devspec.extract` once with confirmed scope. It completes the evidence-backed technical, workflow, and rule baseline, prepares the applicable diagram list, and asks whether to generate all, selected, or no diagrams. A prepared item can later be generated with `/devspec.diagram DIA-###`; do not rerun individual foundation commands afterward. -- New repository: use `projectcontext`, `techstack`, `codebase-structure`, `coding-standards`, `rules`, and `diagram` as input-driven authoring commands. +- New repository: run `devspec.projectcontext`, `devspec.techstack`, `devspec.codebase-structure`, `devspec.coding-standards`, and `devspec.rules` in order. `devspec.techstack`, `devspec.codebase-structure`, and `devspec.coding-standards` inspect source for evidence, so they confirm repository access first; the other two are input-driven. `devspec.diagram` is not part of the chain; call it separately and it returns to its caller. ## 2. Deliver a change @@ -19,7 +19,6 @@ Use `devspec.quickfix` only when the request is one localized enhancement or bug Use the work-item route for public contracts, data migrations, authentication/security work, breaking changes, unresolved risk, or multiple concerns. Grooming is optional; use it when the story has material ambiguity, risk, or incomplete acceptance criteria. `clarify` asks one interactive material blocker question, records the decision, and resumes the originating stage. - Every command validates its declared entry state and records one explicit transition in the canonical artifact. Work items use a monotonic `scope_revision`; a related change request increments it, retains older finalization, task, implementation, and review evidence as superseded history, and requires a new finalization. Review accepts only a matching revision and changed-work baseline; accepted work is terminal, rework returns affected tasks to implementation, and blocked work routes through `clarify`. After `devspec.story` selects a work item, continue with `devspec.grooming`, `devspec.finalize`, `devspec.tasks`, `devspec.implement`, `devspec.review`, `devspec.clarify`, or `devspec.changerequest` without an ID. The private per-worktree selection resolves the current story only when it matches the branch and `meta.md`; `continue` dispatches only its recorded `next` action. Provide an ID to switch stories. If several active stories are eligible, Devspec asks you to choose rather than inferring. A material decision is work-item-local unless it applies beyond that story. At finalization, promote a reusable business or validation decision to `foundation/workflow-rules.md` with a stable rule ID; promote a reusable engineering constraint to `foundation/rules.md`. New stories read only relevant foundation rules and the affected code area, not every historic decision file. Code and tests are the primary enforcement; add a developer comment only for non-obvious rationale and cite the canonical rule ID. @@ -30,24 +29,41 @@ Every project maintains one OWASP Top 10:2025 baseline in `foundation/rules.md`. ![Install and maintenance flow](assets/maintenance-flow.svg) -## Diagram sample +## 4. Generate one diagram + +![Diagram route](assets/diagram-route.svg) -For an evidence-backed architecture or workflow visual, choose a pattern from the [diagram type guide](../devspec/architecture/_template/diagram-types.md), then use the compact [diagram record sample](../devspec/architecture/_template/diagram-sample.md), its standalone [SVG sample](../devspec/architecture/_template/diagram-sample.svg), the opt-in [motion sample](../devspec/architecture/_template/diagram-motion-sample.svg), or its optional [HTML presentation sample](../devspec/architecture/_template/diagram-sample.html). +For an evidence-backed architecture or workflow visual, choose a pattern from the [diagram type guide](../devspec/architecture/_template/diagram-types.md), then start the SVG from the family template that guide selects. Each diagram type has its own template in `devspec/architecture/_template/`: + +| Diagram type | SVG template | +|---|---| +| System architecture | [`architecture-diagram.svg`](../devspec/architecture/_template/architecture-diagram.svg) | +| Application landscape | [`application-landscape-diagram.svg`](../devspec/architecture/_template/application-landscape-diagram.svg) | +| Infrastructure topology | [`infrastructure-topology-diagram.svg`](../devspec/architecture/_template/infrastructure-topology-diagram.svg) | +| Process flow | [`process-flow-diagram.svg`](../devspec/architecture/_template/process-flow-diagram.svg) | +| Sequence | [`sequence-diagram.svg`](../devspec/architecture/_template/sequence-diagram.svg) | +| State lifecycle | [`state-lifecycle-diagram.svg`](../devspec/architecture/_template/state-lifecycle-diagram.svg) | +| Domain model | [`domain-model-diagram.svg`](../devspec/architecture/_template/domain-model-diagram.svg) | +| Journey map | [`journey-map-diagram.svg`](../devspec/architecture/_template/journey-map-diagram.svg) | +| Timeline | [`timeline-plan-diagram.svg`](../devspec/architecture/_template/timeline-plan-diagram.svg) | +| Quadrant | [`quadrant-analysis-diagram.svg`](../devspec/architecture/_template/quadrant-analysis-diagram.svg) | +| Mind map | [`mindmap-diagram.svg`](../devspec/architecture/_template/mindmap-diagram.svg) | + +For the record that accompanies a diagram, use the compact [diagram record sample](../devspec/architecture/_template/diagram-sample.md) and its worked [SVG sample](../devspec/architecture/_template/diagram-sample.svg). The opt-in [motion sample](../devspec/architecture/_template/diagram-motion-sample.svg) shows the animation pattern, and the [HTML presentation sample](../devspec/architecture/_template/diagram-sample.html) shows the optional presentation shell. Assign a stable `DIA-###` ID, keep status in the queue, and add only completed diagram links to the overview index. Diagram output defaults to static SVG with `motion=none`. Use `/devspec.diagram DIA-### motion=explain` when a confirmed sequence, flow, or state transition benefits from motion. The queue records `svg; motion=explain`; the animation must be finite, preserve a complete static final frame, and expose the same information when reduced motion is enabled. Request HTML separately when its presentation shell is needed. - `init` is idempotent for unchanged managed files. It will not overwrite a changed contract or wrapper. For CLI-managed repositories, use `diff`, then `sync --dry-run`, followed by `sync` and `doctor` after an upgrade or profile addition. Manual-copy updates follow the [manual-copy guide](manual-copy.md). `sync` never deletes retained obsolete files. ## Examples | Situation | Route | |---|---| -| New service repository | `projectcontext → techstack → codebase-structure → coding-standards → rules` | -| Existing service with unknown conventions | `extract` — complete baseline extraction | -| Correct a known empty-state label | `quickfix` with `UI` scope | -| Add a customer-export API and authorization | `story → grooming → finalize → tasks → implement → review` | -| A requirement is blocked by a data-retention decision | `clarify`, then resume the saved stage | -| Add a related requirement after finalization | `changerequest → finalize → tasks → implement → review` | +| New service repository | `devspec.projectcontext → devspec.techstack → devspec.codebase-structure → devspec.coding-standards → devspec.rules` | +| Existing service with unknown conventions | `devspec.extract` — complete baseline extraction | +| Correct a known empty-state label | `devspec.quickfix` with `UI` scope | +| Add a customer-export API and authorization | `devspec.story → devspec.grooming → devspec.finalize → devspec.tasks → devspec.implement → devspec.review` | +| A requirement is blocked by a data-retention decision | `devspec.clarify`, then resume the saved stage | +| Add a related requirement after finalization | `devspec.changerequest → devspec.finalize → devspec.tasks → devspec.implement → devspec.review` | diff --git a/src/devspec_lite/definitions.py b/src/devspec_lite/definitions.py index dce0ce7..02cf877 100644 --- a/src/devspec_lite/definitions.py +++ b/src/devspec_lite/definitions.py @@ -52,3 +52,32 @@ def install_files() -> tuple[Path, ...]: COMMANDS = load_commands() PROTOCOLS = tuple(path.stem for path in sorted((canonical_root() / "protocols").glob("*.xml"))) + +# Reading order for human-facing command lists. COMMANDS is sorted by filename, which would +# open every listing with changerequest and hide the route the commands actually follow. +LIFECYCLE_ORDER = ( + "extract", + "projectcontext", + "techstack", + "codebase-structure", + "coding-standards", + "rules", + "story", + "grooming", + "clarify", + "changerequest", + "finalize", + "tasks", + "implement", + "review", + "diagram", + "quickfix", +) + + +def lifecycle_commands() -> tuple[Command, ...]: + remaining = {command.name: command for command in COMMANDS} + ordered = [remaining.pop(name) for name in LIFECYCLE_ORDER if name in remaining] + # A new contract that is not yet placed in the route still has to reach every listing. + ordered.extend(remaining[name] for name in sorted(remaining)) + return tuple(ordered) diff --git a/src/devspec_lite/framework.py b/src/devspec_lite/framework.py index cd50d94..4b8b9bc 100644 --- a/src/devspec_lite/framework.py +++ b/src/devspec_lite/framework.py @@ -10,7 +10,7 @@ from xml.etree import ElementTree from . import __version__ -from .definitions import COMMANDS, PROTOCOLS, canonical_root, install_files +from .definitions import COMMANDS, PROTOCOLS, canonical_root, install_files, lifecycle_commands, workflow_block PROFILES = ("all", "copilot", "codex", "claude", "cursor", "gemini", "antigravity") ADAPTERS = PROFILES[1:] @@ -53,10 +53,8 @@ def wrapper_text(adapter: str, command) -> tuple[str, str]: raise ValueError(adapter) -def xml_block(text: str) -> str: - start = text.index("") + len("") - return text[start:end] +# Re-exported so existing callers keep importing it from here. +xml_block = workflow_block def expected_paths(profile: str) -> list[Path]: @@ -65,11 +63,16 @@ def expected_paths(profile: str) -> list[Path]: def doctor(root: Path, profile: str) -> list[str]: - issues = [f"missing: {path}" for path in expected_paths(profile) if not (root / path).is_file()] - if (root / "devspec/work-items/current.md").exists(): - issues.append("tracked current-story artifact is not allowed: devspec/work-items/current.md") - valid_stages = {"foundation", "intake", "grooming", "finalization", "tasks", "implementation", "review", "complete", "triage", "routed", "caller", "origin"} - valid_runs = {"active", "blocked", "complete"} + try: + expected = expected_paths(profile) + except OSError as exc: + return [f"cannot read the canonical framework: {exc}"] + issues = [f"missing: {path}" for path in expected if not (root / path).is_file()] + for forbidden in ("devspec/work-items/current.md", "devspec/current-work-item.json"): + if (root / forbidden).exists(): + issues.append(f"tracked current-work-item artifact is not allowed: {forbidden}") + valid_stages = {"foundation", "intake", "grooming", "finalization", "tasks", "implementation", "review", "complete", "triage", "validation", "routed", "caller", "origin"} + valid_runs = {"active", "paused", "blocked", "stopped", "complete"} valid_next = {f"devspec.{command.name}" for command in COMMANDS} | {"none", "return-to-caller", "resume-origin"} lifecycle_templates = { "devspec/work-items/_template/meta.md": ("scope_revision:", "finalized_revision:", "planned_revision:", "implemented_revision:", "reviewed_revision:"), @@ -77,11 +80,16 @@ def doctor(root: Path, profile: str) -> list[str]: } current_context_commands = {"story", "grooming", "finalize", "tasks", "implement", "review", "clarify", "changerequest"} protocol_text_requirements = { - "run": {"preflight": ("Before every command", "single-repository or multi-repository scope", "current workspace as proposed", "free-form text input", "After each path is confirmed", "interactive named access-requirement question", "Do not inspect or change source")}, + "run": {"preflight": ("Before every command", "single-repository or multi-repository scope", "current workspace as proposed", "repo-access protocol", "Do not inspect or change source")}, + "repo-access": { + "collect": ("free-form text input", "Confirm the path before asking about access"), + "question": ("After each path is confirmed", "Custom Answer"), + "recommend": ("exactly one choice recommended", "least-privilege"), + }, "current-work-item": { "location": ("git rev-parse --git-path devspec/current-work-item.json", "Never create or commit"), "record": ("work-item ID", "current branch", "selection source", "timestamp", "never committed or pushed"), - "selection": ("validated explicit ID", "exactly one eligible non-terminal"), + "selection": ("validated explicit ID", "exactly one non-terminal work item on the current branch"), "validation": ("branch changed", "stage and next action"), "continuation": ("saved meta.md next action", "devspec.clarify", "terminal item is not resumed"), "clear": ("accepted review",), @@ -91,36 +99,36 @@ def doctor(root: Path, profile: str) -> list[str]: path = root / f"devspec/protocols/{name}.xml" if path.is_file(): try: - ElementTree.fromstring(path.read_text(encoding="utf-8")) - except ElementTree.ParseError as exc: + protocol = ElementTree.fromstring(path.read_text(encoding="utf-8")) + except (ElementTree.ParseError, OSError, UnicodeDecodeError) as exc: issues.append(f"invalid XML: {path}: {exc}") else: required = { "ask": ("trigger", "checkpoint", "interaction", "resolution"), "run": ("preflight", "checkpoint", "context", "resume", "blocked", "closure"), "work": ("scope", "evidence", "change", "artifacts"), - "repo-access": ("when", "validate", "respect"), + "repo-access": ("when", "collect", "question", "recommend", "record", "respect"), "current-work-item": ("when", "location", "record", "selection", "validation", "recovery", "continuation", "update", "clear"), - }[name] - present = {child.tag for child in ElementTree.fromstring(path.read_text(encoding="utf-8"))} + "state": ("when", "run-states", "stages", "task-statuses", "evidence-labels", "resume"), + }.get(name, ()) + present = {child.tag for child in protocol} missing = sorted(set(required) - present) if missing: issues.append(f"missing protocol tags: {path}: {', '.join(missing)}") - protocol = ElementTree.fromstring(path.read_text(encoding="utf-8")) for tag, phrases in protocol_text_requirements.get(name, {}).items(): value = protocol.findtext(tag, default="") for phrase in phrases: if phrase not in value: - issues.append(f"missing current-story resolver requirement: {path}: {tag}: {phrase}") + issues.append(f"missing protocol requirement: {path}: {tag}: {phrase}") for command in COMMANDS: path = root / f"devspec/contracts/devspec.{command.name}.md" if path.is_file(): - text = path.read_text(encoding="utf-8") try: + text = path.read_text(encoding="utf-8") workflow = ElementTree.fromstring(xml_block(text)) if workflow.tag != "workflow" or workflow.attrib.get("command") != f"devspec.{command.name}": issues.append(f"invalid contract identity: {path}") - required = {"purpose", "protocols", "input", "rules", "entry", "outputs", "transitions", "closure", "actions", "artifact", "handoff"} + required = {"purpose", "protocols", "scope", "input", "rules", "entry", "outputs", "transitions", "closure"} present = {child.tag for child in workflow} missing = sorted(required - present) if missing: @@ -131,9 +139,7 @@ def doctor(root: Path, profile: str) -> list[str]: issues.append(f"missing current-story protocol: {path}") if command.name != "story" and command.name in current_context_commands and "[work-item-id]" not in text: issues.append(f"work-item ID is not optional: {path}") - if command.name == "story" and "current-work-item" not in protocol_refs: - issues.append(f"missing current-story classification protocol: {path}") - except (ValueError, ElementTree.ParseError) as exc: + except (ValueError, ElementTree.ParseError, OSError, UnicodeDecodeError) as exc: issues.append(f"invalid contract XML: {path}: {exc}") continue outputs = workflow.find("outputs") @@ -142,7 +148,7 @@ def doctor(root: Path, profile: str) -> list[str]: transitions = workflow.find("transitions") if transitions is None or not list(transitions): issues.append(f"missing contract transitions: {path}") - elif transitions is not None: + else: for transition in transitions: stage = transition.attrib.get("stage") run = transition.attrib.get("run") @@ -153,6 +159,8 @@ def doctor(root: Path, profile: str) -> list[str]: issues.append(f"blocked transition must clarify: {path}") if next_command == "none" and run != "complete": issues.append(f"terminal transition must be complete: {path}") + if run == "complete" and next_command != "none": + issues.append(f"complete transition must be terminal: {path}") registry = root / "devspec/command-registry.md" registry_text = registry.read_text(encoding="utf-8") if registry.is_file() else "" for command in COMMANDS: @@ -200,7 +208,8 @@ def doctor(root: Path, profile: str) -> list[str]: # Upgrade lifecycle. These definitions intentionally follow the compact installer # above so existing callers retain their public import locations. def _sha256(path: Path) -> str: - return hashlib.sha256(path.read_bytes()).hexdigest() + # Hash normalized text so a CRLF checkout does not read as local drift. + return hashlib.sha256(path.read_text(encoding="utf-8").encode("utf-8")).hexdigest() def _state_from_target(root: Path) -> str: @@ -212,11 +221,16 @@ def _state_from_target(root: Path) -> str: return "existing" +# Live project state seeded once from a template, then never overwritten by sync. +SEEDED_FROM_TEMPLATE = ( + (Path("devspec/architecture/overview.md"), "architecture/_template/overview.md"), + (Path("devspec/architecture/artifact-queue.md"), "architecture/_template/artifact-queue.md"), +) + + def _ownership(relative: Path) -> str: if relative == Path("constitution.md"): return PROJECT_OWNED - if relative in {Path("architecture/overview.md"), Path("architecture/artifact-queue.md")}: - return PROJECT_OWNED if relative == Path("foundation/repository-state.md"): return PROJECT_OWNED return FRAMEWORK_OWNED @@ -230,13 +244,17 @@ def managed_payload(profile: str, repo_state: str) -> tuple[ManagedFile, ...]: files.append(ManagedFile(Path("devspec") / relative, source.read_text(encoding="utf-8"), _ownership(relative))) route = "devspec.extract" if repo_state == "existing" else "devspec.projectcontext" files.append(ManagedFile(Path("devspec/foundation/repository-state.md"), f"# Repository State\n\n- State: {repo_state}\n- Start with: `{route}`\n", PROJECT_OWNED)) + # Seed the live architecture records from their templates. Installing the canonical copies + # would hand every target repository devspec-lite's own diagram rows. + for target, template in SEEDED_FROM_TEMPLATE: + files.append(ManagedFile(target, (source_root / template).read_text(encoding="utf-8"), PROJECT_OWNED)) adapters = ADAPTERS if profile == "all" else (profile,) for adapter in adapters: if adapter == "codex": - command_lines = "\n".join(f"- `devspec.{c.name}`: read `devspec/contracts/devspec.{c.name}.md`." for c in COMMANDS) + command_lines = "\n".join(f"- `devspec.{c.name}`: read `devspec/contracts/devspec.{c.name}.md`." for c in lifecycle_commands()) files.append(ManagedFile(Path("AGENTS.md"), "# Devspec Lite\n\nUse Git-tracked `devspec/` artifacts as canonical state. For a clear work-item continuation, resolve the per-worktree current context and run only its saved next action; ask before switching among multiple stories.\n\n" + command_lines + "\n", FRAMEWORK_OWNED)) elif adapter == "cursor": - commands = ", ".join(f"`devspec.{c.name}`" for c in COMMANDS) + commands = ", ".join(f"`devspec.{c.name}`" for c in lifecycle_commands()) files.append(ManagedFile(Path(".cursor/rules/devspec-workflow.mdc"), f"---\ndescription: Devspec Lite workflow\nalwaysApply: false\n---\nFor {commands}, read the matching `devspec/contracts/` file and listed protocols. For a clear continuation, resolve per-worktree current context and run only the saved next action; ask before switching stories.\n", FRAMEWORK_OWNED)) elif adapter == "copilot": for command in COMMANDS: @@ -308,10 +326,10 @@ def _copy_plan(root: Path, files: tuple[ManagedFile, ...], previous: dict | None skipped.append(name) continue if item.ownership == PROJECT_OWNED: - if mode == "sync": - skipped.append(f"{name} (project-owned)") - else: - conflicts.append(f"{name} already exists and differs") + # A project-owned file that already exists is the developer's own work, and its + # presence is expected when re-running init to add a profile. Never overwrite it, + # and never fail on it: the only escape would be --force, which would destroy it. + skipped.append(f"{name} (project-owned)") continue if mode == "sync" and old.get(name, {}).get("sha256") == digest: writable.append(item) diff --git a/tests/test_contract_consistency.py b/tests/test_contract_consistency.py new file mode 100644 index 0000000..6181b28 --- /dev/null +++ b/tests/test_contract_consistency.py @@ -0,0 +1,261 @@ +"""Cross-check the contracts against every surface that restates them. + +The other suites install into a temporary directory and validate that, so drift between +this repository's own checked-in wrappers and its contracts stayed invisible. These tests +validate the repository itself. +""" + +from __future__ import annotations + +import re +import sys +import unittest +from pathlib import Path +from xml.etree import ElementTree + +REPO = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(REPO / "src")) + +from devspec_lite.definitions import COMMANDS, LIFECYCLE_ORDER, PROTOCOLS, lifecycle_commands # noqa: E402 +from devspec_lite.framework import FRAMEWORK_OWNED, doctor, managed_payload # noqa: E402 + +CONTRACTS = REPO / "devspec/contracts" +# Live project state and this project's own work products are deliberately not installed. +UNINSTALLED = ("foundation/repository-state.md", "architecture/overview.md", "architecture/artifact-queue.md") + + +def contract_text(name: str) -> str: + return (CONTRACTS / f"devspec.{name}.md").read_text(encoding="utf-8") + + +def workflow(name: str) -> ElementTree.Element: + text = contract_text(name) + return ElementTree.fromstring(text[text.index("") + len("")]) + + +def table_rows(text: str, header_starts: str) -> list[list[str]]: + rows = [] + seen_header = False + for line in text.splitlines(): + line = line.strip() + if not line.startswith("|"): + seen_header = False + continue + cells = [c.strip() for c in line.strip("|").split("|")] + if cells[0].startswith(header_starts): + seen_header = True + continue + if seen_header and not set("".join(cells)) <= set("-: "): + rows.append(cells) + return rows + + +class RepositoryIsCurrentTests(unittest.TestCase): + def test_checked_in_wrappers_match_the_contracts(self) -> None: + drift, checked = [], 0 + for item in managed_payload("all", "existing"): + if item.ownership != FRAMEWORK_OWNED: + continue + target = REPO / item.path + if not target.is_file(): + drift.append(f"{item.path.as_posix()} (missing)") + elif target.read_text(encoding="utf-8") != item.content: + drift.append(item.path.as_posix()) + else: + checked += 1 + self.assertEqual([], drift, "run the installer to regenerate these from devspec/contracts") + self.assertGreater(checked, len(COMMANDS), "expected at least one wrapper per command") + + def test_doctor_passes_against_this_repository(self) -> None: + self.assertEqual([], doctor(REPO, "all")) + + def test_install_manifest_covers_every_canonical_file(self) -> None: + from devspec_lite.definitions import canonical_root, install_files + + root = canonical_root() + installed = {p.relative_to(root).as_posix() for p in install_files()} + for path in sorted(root.rglob("*")): + if not path.is_file(): + continue + relative = path.relative_to(root).as_posix() + if relative in UNINSTALLED or relative.startswith("quickfixes/QF-") or relative.startswith("work-items/") and "_template" not in relative: + continue + self.assertIn(relative, installed, f"{relative} is not covered by install-manifest.txt") + + +class ContractSchemaTests(unittest.TestCase): + def test_every_command_has_a_lifecycle_position(self) -> None: + self.assertEqual(sorted(LIFECYCLE_ORDER), sorted(c.name for c in COMMANDS)) + + def test_heading_summary_matches_purpose(self) -> None: + for command in COMMANDS: + with self.subTest(command.name): + body = contract_text(command.name) + summary = body[body.index("\n\n") + 2:body.index("\n\nInvocation:")].strip() + self.assertEqual(command.purpose, summary) + + def test_derivable_elements_are_not_restated(self) -> None: + # A workflow-level restated , restated , and + # restated . The child inside is unaffected. + for command in COMMANDS: + with self.subTest(command.name): + present = {child.tag for child in workflow(command.name)} + self.assertEqual(set(), present & {"artifact", "handoff", "actions"}) + + def test_every_contract_scopes_itself(self) -> None: + for command in COMMANDS: + with self.subTest(command.name): + scope = workflow(command.name).findtext("scope", default="").strip() + self.assertTrue(scope, "contract must state when to use it and what to use instead") + + def test_protocol_refs_resolve(self) -> None: + for command in COMMANDS: + refs = list(workflow(command.name).find("protocols")) + self.assertTrue(refs, f"{command.name} loads no protocol") + for ref in refs: + with self.subTest(command=command.name, ref=ref.attrib.get("ref")): + self.assertIn(ref.attrib.get("ref"), PROTOCOLS) + + def test_every_protocol_is_loaded_by_a_contract(self) -> None: + used = {ref.attrib.get("ref") for c in COMMANDS for ref in workflow(c.name).find("protocols")} + self.assertEqual(set(PROTOCOLS), used, "an unreferenced protocol never reaches the agent") + + def test_shared_vocabulary_reaches_every_command(self) -> None: + for command in COMMANDS: + with self.subTest(command.name): + refs = {ref.attrib.get("ref") for ref in workflow(command.name).find("protocols")} + self.assertIn("state", refs) + self.assertIn("run", refs) + + +class RouteGraphTests(unittest.TestCase): + def transitions(self, name: str) -> list[dict]: + return [t.attrib for t in workflow(name).find("transitions")] + + def test_blocked_and_terminal_transitions_agree_with_lifecycle(self) -> None: + for command in COMMANDS: + for attrib in self.transitions(command.name): + with self.subTest(command=command.name, outcome=attrib.get("outcome")): + if attrib["run"] == "blocked": + self.assertEqual("devspec.clarify", attrib["next"]) + if attrib["run"] == "complete": + self.assertEqual("none", attrib["next"]) + if attrib["next"] == "none": + self.assertEqual("complete", attrib["run"]) + + def test_work_item_stages_match_the_lifecycle_table(self) -> None: + text = (REPO / "devspec/lifecycle.md").read_text(encoding="utf-8") + documented = {row[0].strip("`"): row[1] for row in table_rows(text, "Stage")} + stages = {"intake", "grooming", "finalization", "tasks", "implementation", "review", "complete"} + self.assertEqual(stages, set(documented)) + for command in COMMANDS: + for attrib in self.transitions(command.name): + stage, nxt = attrib["stage"], attrib["next"] + if stage in documented and nxt.startswith("devspec."): + with self.subTest(command=command.name, stage=stage): + self.assertIn(nxt, documented[stage], f"lifecycle.md does not allow {stage} -> {nxt}") + + def test_a_command_declares_the_records_it_writes(self) -> None: + # ask.xml routes a blocker to a decision record; run.xml checkpoints the state record. + for command in COMMANDS: + outputs = [a.attrib["path"] for a in workflow(command.name).find("outputs")] + stages = {t["stage"] for t in self.transitions(command.name)} + runs = {t["run"] for t in self.transitions(command.name)} + work_item = any(p.startswith("devspec/work-items/") for p in outputs) + with self.subTest(command.name): + if "blocked" in runs: + self.assertTrue( + any("decisions.md" in p for p in outputs) or any("QF-###" in p for p in outputs), + f"{command.name} can block but declares no decision record", + ) + if work_item and stages - {"caller", "origin"}: + self.assertTrue( + any(p.endswith("meta.md") for p in outputs), + f"{command.name} moves a work item but declares no meta.md", + ) + + def test_registry_restates_the_contracts_exactly(self) -> None: + text = (REPO / "devspec/command-registry.md").read_text(encoding="utf-8") + rows = table_rows(text, "Command") + self.assertEqual([f"`devspec.{c.name}`" for c in lifecycle_commands()], [r[0] for r in rows]) + for command, row in zip(lifecycle_commands(), rows): + with self.subTest(command.name): + self.assertEqual(command.purpose, row[1]) + expected = [] + for attrib in self.transitions(command.name): + if attrib["next"] not in expected: + expected.append(attrib["next"]) + self.assertEqual(", ".join(f"`{v}`" for v in expected), row[2]) + + +class DocumentationTests(unittest.TestCase): + # A command a guide never names is a command a reader never finds. + COVERING_DOCS = ("how-to.md", "command-examples.md", "quickstart.md", "workflows.md") + + def test_every_command_appears_in_the_command_guides(self) -> None: + for doc in self.COVERING_DOCS: + text = (REPO / "docs" / doc).read_text(encoding="utf-8") + for command in COMMANDS: + with self.subTest(doc=doc, command=command.name): + self.assertIn(f"devspec.{command.name}", text) + + +class ArtifactShapeTests(unittest.TestCase): + def test_markdown_tables_are_well_formed(self) -> None: + separator = re.compile(r"\|(\s*:?-+:?\s*\|)+$") + broken, seen = [], 0 + roots = sorted((REPO / "devspec").rglob("*.md")) + sorted((REPO / "docs").rglob("*.md")) + roots += [REPO / "README.md", REPO / "AGENTS.md"] + for path in roots: + lines = path.read_text(encoding="utf-8").split("\n") + for index, line in enumerate(lines[:-1]): + nxt = lines[index + 1].strip() + if line.strip().startswith("|") and separator.fullmatch(nxt): + seen += 1 + header = line.strip().strip("|").split("|") + if len(header) != len(nxt.strip("|").split("|")): + broken.append(f"{path.relative_to(REPO).as_posix()}:{index + 1}") + self.assertEqual([], broken) + self.assertGreater(seen, 30, "table scan found almost nothing; the walk is probably wrong") + + # Each entry is a field some contract or protocol names, and the template that must offer it. + REQUIRED_FIELDS = { + "devspec/foundation/_template/rules.md": ("Constitution principles",), + "devspec/foundation/_template/tech-stack.md": ("Supported versions",), + "devspec/foundation/_template/project-context.md": ("Evidence label",), + "devspec/foundation/_template/codebase-structure.md": ("Integration points", "Validation location"), + "devspec/architecture/_template/artifact-queue.md": ("Duplicate check",), + "devspec/work-items/_template/finalize.md": ("CP-###", "Scope revision:"), + "devspec/work-items/_template/tasks.md": ("Done condition", "Scope revision:"), + "devspec/work-items/_template/implement.md": ("Changed-work baseline:",), + "devspec/work-items/_template/review.md": ("Location", "implemented-as-decided", "Changed-work baseline:"), + "devspec/quickfixes/_template.md": ("last:", "resume:", "next:"), + } + + def test_templates_carry_the_fields_contracts_require(self) -> None: + for template, fields in self.REQUIRED_FIELDS.items(): + text = (REPO / template).read_text(encoding="utf-8") + for field in fields: + with self.subTest(template=template, field=field): + self.assertIn(field, text) + + def test_contract_outputs_have_a_template(self) -> None: + template_map = (REPO / "devspec/foundation/template-map.md").read_text(encoding="utf-8") + work_item_templates = {p.name for p in (REPO / "devspec/work-items/_template").glob("*.md")} + for command in COMMANDS: + artifacts = list(workflow(command.name).find("outputs")) + self.assertTrue(artifacts, f"{command.name} declares no output") + for artifact in artifacts: + path = artifact.attrib["path"] + with self.subTest(command=command.name, path=path): + name = path.rsplit("/", 1)[-1] + if path.startswith("devspec/work-items/"): + self.assertIn(name, work_item_templates) + elif path.startswith("devspec/foundation/"): + self.assertIn(f"`{name}`", template_map) + else: + self.assertTrue((REPO / path).is_file() or "###" in name, f"no home for {path}") + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_framework.py b/tests/test_framework.py index b2e425c..5ad906c 100644 --- a/tests/test_framework.py +++ b/tests/test_framework.py @@ -67,7 +67,7 @@ def test_ask_protocol_requires_interactive_choices(self) -> None: run = ElementTree.fromstring((target / "devspec/protocols/run.xml").read_text(encoding="utf-8")) self.assertEqual("devspec/foundation/decisions.md", run.findtext("state-records/foundation")) repo_access = ElementTree.fromstring((target / "devspec/protocols/repo-access.xml").read_text(encoding="utf-8")) - self.assertIn("Validate a validation-only repository only", repo_access.findtext("respect")) + self.assertIn("Never validate a reference-only, edit, release-coordination, or unavailable repository", repo_access.findtext("respect")) self.assertTrue((target / "devspec/foundation/template-map.md").is_file()) self.assertTrue((target / "devspec/foundation/_template/decisions.md").is_file()) self.assertTrue((target / "AGENTS.md").is_file()) @@ -112,6 +112,7 @@ def test_security_foundation_and_confirmed_exception_path_are_installed(self) -> finalize_contract = (target / "devspec/contracts/devspec.finalize.md").read_text(encoding="utf-8") implement_contract = (target / "devspec/contracts/devspec.implement.md").read_text(encoding="utf-8") review_contract = (target / "devspec/contracts/devspec.review.md").read_text(encoding="utf-8") + security_protocol = (target / "devspec/protocols/security.xml").read_text(encoding="utf-8") self.assertEqual(1, rules.count("OWASP Top 10:2025 Baseline")) self.assertIn("A01:2025 Broken Access Control", rules) self.assertIn("A10:2025 Mishandling of Exceptional Conditions", rules) @@ -121,18 +122,20 @@ def test_security_foundation_and_confirmed_exception_path_are_installed(self) -> self.assertIn("Developer confirmation", implementation_template) self.assertIn("Security Verification", review_template) self.assertIn("Reviewer confirmation", review_template) - self.assertIn("OWASP Top 10:2025", rules_contract) - self.assertIn("do not infer an internal-only", extract_contract) + # The security protocol owns the baseline, exception, and gate; the contracts load it. + self.assertIn("OWASP Top 10:2025", security_protocol) + self.assertIn("one material confirmation question", security_protocol) + self.assertIn("known unresolved vulnerability", security_protocol) + for contract in (rules_contract, extract_contract, finalize_contract, implement_contract, review_contract): + self.assertIn('', contract) + self.assertIn("internal-only", security_protocol) self.assertIn("foundation trace", finalize_contract) - self.assertIn("ask one material confirmation question", implement_contract) - self.assertIn("reviewer records confirmation", review_contract) - self.assertIn("known unresolved vulnerability", review_contract) def test_contract_xml_and_quickfix_routing_are_present(self) -> None: with tempfile.TemporaryDirectory() as raw: target = Path(raw) main(["init", "--target", str(target), "--profile", "copilot", "--repo-state", "existing"]) quickfix = (target / "devspec/contracts/devspec.quickfix.md").read_text(encoding="utf-8") - self.assertIn("route risky work", quickfix) + self.assertIn("Route public API contracts", quickfix) self.assertIn("database schema or migration", quickfix) self.assertIn("", quickfix) self.assertIn('', quickfix) @@ -169,7 +172,7 @@ def test_extract_prepares_diagrams_and_requests_generation_confirmation(self) -> extract = (target / "devspec/contracts/devspec.extract.md").read_text(encoding="utf-8") diagram = (target / "devspec/contracts/devspec.diagram.md").read_text(encoding="utf-8") how_to = (Path(__file__).resolve().parents[1] / "docs/how-to.md").read_text(encoding="utf-8") - self.assertIn("Do you want me generate all the possible diagrams?", extract) + self.assertIn("Do you want me to generate all the possible diagrams?", extract) self.assertIn("Yes — generate all listed diagrams", extract) self.assertIn("No — prepare the list only", extract) self.assertIn("Choose diagrams — enter the IDs or subjects to generate", extract) @@ -299,6 +302,8 @@ def test_family_specific_diagram_templates_are_installed_and_well_formed(self) - template_root = target / "devspec/architecture/_template" expected = ( "architecture-diagram.svg", + "application-landscape-diagram.svg", + "infrastructure-topology-diagram.svg", "process-flow-diagram.svg", "sequence-diagram.svg", "state-lifecycle-diagram.svg", @@ -317,6 +322,34 @@ def test_family_specific_diagram_templates_are_installed_and_well_formed(self) - diagram = (target / "devspec/contracts/devspec.diagram.md").read_text(encoding="utf-8") self.assertIn("Start each SVG from the matching family-specific template", diagram) self.assertIn("connectors behind cards", diagram) + self.assertIn("Anchor every connector to a shape edge at both ends", diagram) + types = (target / "devspec/architecture/_template/diagram-types.md").read_text(encoding="utf-8") + for name in expected: + with self.subTest(mapped=name): + self.assertIn(f"`{name}`", types) + + def test_diagram_templates_have_no_dangling_marker_references(self) -> None: + """A marker-end pointing at a missing id renders a connector with no arrowhead.""" + with tempfile.TemporaryDirectory() as raw: + target = Path(raw) + main(["init", "--target", str(target), "--profile", "all", "--repo-state", "existing"]) + namespace = "{http://www.w3.org/2000/svg}" + for path in sorted((target / "devspec/architecture/_template").glob("*.svg")): + with self.subTest(template=path.name): + root = ElementTree.parse(path).getroot() + defined = {marker.attrib.get("id") for marker in root.iter(f"{namespace}marker")} + referenced = set() + for element in root.iter(): + for attribute in ("marker-end", "marker-start", "filter", "fill", "stroke"): + value = element.attrib.get(attribute, "") + if value.startswith("url(#"): + referenced.add(value[5:-1]) + self.assertTrue(referenced <= defined | {node.attrib.get("id") for node in root.iter()}, + f"{path.name} references an undefined id") + serialized = ElementTree.tostring(root, encoding="unicode") + self.assertNotIn(" None: with tempfile.TemporaryDirectory() as raw: @@ -393,11 +426,14 @@ def test_current_work_item_protocol_and_optional_ids_are_installed(self) -> None self.assertIn("Continue current work without an ID", how_to) self.assertIn("selected `meta.md` next action", how_to) self.assertIn("post-finalization route", how_to) - tracked_context = target / "devspec/work-items/current.md" - tracked_context.parent.mkdir(parents=True, exist_ok=True) - tracked_context.write_text("current: STORY-001\n", encoding="utf-8") - issues = doctor(target, "all") - self.assertTrue(any("tracked current-story artifact" in issue for issue in issues)) + # Both the legacy path and the path a real violation takes today. + for forbidden in ("devspec/work-items/current.md", "devspec/current-work-item.json"): + tracked_context = target / forbidden + tracked_context.parent.mkdir(parents=True, exist_ok=True) + tracked_context.write_text("current: STORY-001\n", encoding="utf-8") + issues = doctor(target, "all") + self.assertTrue(any(f"tracked current-work-item artifact is not allowed: {forbidden}" in issue for issue in issues)) + tracked_context.unlink() if __name__ == "__main__": unittest.main() diff --git a/tests/test_parity_contracts.py b/tests/test_installed_contracts.py similarity index 97% rename from tests/test_parity_contracts.py rename to tests/test_installed_contracts.py index 5eb09f7..8659598 100644 --- a/tests/test_parity_contracts.py +++ b/tests/test_installed_contracts.py @@ -7,7 +7,7 @@ from devspec_lite.framework import doctor, install_framework -class ParityContractTests(unittest.TestCase): +class InstalledContractTests(unittest.TestCase): def test_constitution_clarification_architecture_and_batch_contracts_are_installed(self) -> None: with tempfile.TemporaryDirectory() as raw: target = Path(raw) diff --git a/tests/test_upgrade.py b/tests/test_upgrade.py index a566ea4..a6aa9aa 100644 --- a/tests/test_upgrade.py +++ b/tests/test_upgrade.py @@ -11,6 +11,26 @@ class UpgradeLifecycleTests(unittest.TestCase): + def test_adding_a_profile_preserves_project_work(self) -> None: + # Re-running init to add a profile must not fail on, or overwrite, the developer's own + # constitution, architecture queue, or overview. The only escape used to be --force, + # which would have destroyed exactly those files. + with tempfile.TemporaryDirectory() as raw: + target = Path(raw) + main(["init", "--target", str(target), "--profile", "codex", "--repo-state", "existing"]) + owned = { + "devspec/constitution.md": "# Constitution\n\n| CP-001 | keep me |\n", + "devspec/architecture/artifact-queue.md": "# Architecture Artifact Queue\n\n| DIA-001 | keep me |\n", + "devspec/architecture/overview.md": "# Architecture Overview\n\nkeep me\n", + } + for path, content in owned.items(): + (target / path).write_text(content, encoding="utf-8") + self.assertEqual(0, main(["init", "--target", str(target), "--profile", "claude", "--repo-state", "existing"])) + for path, content in owned.items(): + self.assertEqual(content, (target / path).read_text(encoding="utf-8"), path) + self.assertTrue((target / ".claude/skills/devspec-story/SKILL.md").is_file()) + self.assertTrue((target / "AGENTS.md").is_file()) + def run_cli(self, arguments: list[str]) -> tuple[int, str]: output = io.StringIO() with contextlib.redirect_stdout(output): @@ -51,8 +71,11 @@ def test_diff_reports_missing_files_and_init_force_preserves_project_owned_files self.assertIn("AGENTS.md", diff_framework(target, "codex")["missing"]) constitution = target / "devspec/constitution.md" constitution.write_text("# Constitution\n\nCP-001: protected\n", encoding="utf-8") - self.assertEqual(2, main(["init", "--target", str(target), "--profile", "codex", "--repo-state", "new", "--force"])) + # init now restores the missing wrapper instead of failing, and --force still + # cannot reach a project-owned file. + self.assertEqual(0, main(["init", "--target", str(target), "--profile", "codex", "--repo-state", "new", "--force"])) self.assertIn("CP-001: protected", constitution.read_text(encoding="utf-8")) + self.assertTrue((target / "AGENTS.md").is_file()) def test_sync_preserves_project_owned_constitution(self) -> None: with tempfile.TemporaryDirectory() as raw: