diff --git a/.agents/rules/devspec-workflow.md b/.agents/rules/devspec-workflow.md index 58d0bc2..694f0a9 100644 --- a/.agents/rules/devspec-workflow.md +++ b/.agents/rules/devspec-workflow.md @@ -13,7 +13,7 @@ Follow these rules: - Preserve the original intent of the canonical Copilot prompt and agent files named in the registry. - Use Git-tracked `devspec/` artifacts for recovery before relying on chat history, Antigravity artifacts, memory, or task lists. - Preserve required inputs, output artifacts, status values, gates, handoff order, and recovery behavior. -- Preserve structured question behavior from `.github/prompts/PATTERNS.md#interactive-question-pattern`; if clickable options are unavailable, render the same option labels as text and preserve the recommended option. +- Preserve structured question behavior from `.github/prompts/PATTERNS.md#interactive-question-pattern`: show interactive multiple-choice options when Antigravity can render them, otherwise render the identical options as text; include an example for every option and `Custom Answer`; ask one question at a time; and preserve the recommendation with its justification. - Use `devspec/glossary.md` for status values. - Use `devspec/foundation/codebase-structure.md` for repository access requirements. - Keep product context in `devspec/foundation/project-context.md`, durable principles in `devspec/constitution.md`, and operational governance, compliance rules, enforcement details, and delivery gates in `devspec/foundation/rules.md`. diff --git a/.agents/skills/devspec-changerequest.md b/.agents/skills/devspec-changerequest.md new file mode 100644 index 0000000..bfc7bfa --- /dev/null +++ b/.agents/skills/devspec-changerequest.md @@ -0,0 +1,13 @@ +--- +name: devspec-changerequest +description: Run /devspec.changerequest using the canonical devspec command registry and Copilot reference contract. +--- + +Execute canonical command `/devspec.changerequest`. + +- Read `devspec/adapters/command-registry.md` for the command contract. +- Read `.github/prompts/devspec.changerequest.prompt.md` and `.github/agents/devspec.changerequest.agent.md` as the source of intent. +- Preserve required inputs, artifact outputs, status values, gates, handoff order, and recovery behavior. +- Use Git-tracked `devspec/` artifacts for recovery before relying on chat history or Antigravity artifacts. +- Append accepted `CR-###` scope to existing work-item artifacts; do not create a CR-specific Markdown file or rewrite baseline history. +- Treat unsupported Antigravity behavior as an adapter limitation, not a workflow change. diff --git a/.claude/skills/devspec-changerequest/SKILL.md b/.claude/skills/devspec-changerequest/SKILL.md new file mode 100644 index 0000000..cda9d78 --- /dev/null +++ b/.claude/skills/devspec-changerequest/SKILL.md @@ -0,0 +1,14 @@ +--- +name: devspec-changerequest +description: Run /devspec.changerequest using the canonical devspec command registry. Records one missed related requirement for a finalized work item without rewriting baseline history. +--- + +Execute canonical command `/devspec.changerequest`. + +1. Read `AGENTS.md` for canonical workflow, no-intent-drift, cross-tool recovery, and structured question rules. +2. Read `devspec/adapters/command-registry.md` for this command's required input, outputs, mutation level, and next handoff. +3. Read `.github/prompts/devspec.changerequest.prompt.md` and `.github/agents/devspec.changerequest.agent.md` as the authoritative source of command intent and behavior. +4. Apply `.github/prompts/PATTERNS.md` for shared behavior: interactive questions, prerequisite validation, session recovery, and output closure. +5. Preserve baseline rows and prior evidence; append accepted `CR-###` scope only to existing work-item artifacts. + +Command input comes from the user's current message. diff --git a/.gemini/commands/devspec/changerequest.toml b/.gemini/commands/devspec/changerequest.toml new file mode 100644 index 0000000..edac9e8 --- /dev/null +++ b/.gemini/commands/devspec/changerequest.toml @@ -0,0 +1,13 @@ +description = "Run canonical /devspec.changerequest from Gemini CLI." +prompt = """ +Execute canonical command `/devspec.changerequest`. + +Before acting: +1. Read `devspec/adapters/command-registry.md` and use the `/devspec.changerequest` row as the command contract. +2. Read `.github/prompts/devspec.changerequest.prompt.md` and `.github/agents/devspec.changerequest.agent.md` as the protected source of intent. +3. Follow `.github/prompts/PATTERNS.md` for shared workflow, recovery, output, and recommendation behavior. +4. Recover from existing Git-tracked `devspec/` artifacts before relying on Gemini session memory. +5. Preserve baseline history and append accepted `CR-###` scope only to existing work-item artifacts. +6. Treat Gemini-specific command syntax as platform mechanics, not a workflow change. + +The user's raw command input, if any, is appended below these instructions by Gemini CLI. diff --git a/.github/agents/devspec.changerequest.agent.md b/.github/agents/devspec.changerequest.agent.md new file mode 100644 index 0000000..8e61dc3 --- /dev/null +++ b/.github/agents/devspec.changerequest.agent.md @@ -0,0 +1,34 @@ +--- +name: "devspec.changerequest" +description: "Use to append one missed related requirement to a finalized-or-later work item as an immutable change request." +tools: [read, edit, search, vscode/askQuestions] +model: ["GPT-5.4 (copilot)", "GPT-5.3-Codex (copilot)", "Claude Sonnet 4.6 (copilot)", "Claude Haiku 4.5 (copilot)"] +user-invocable: true +agents: [] +handoffs: + - label: Continue to Finalize + agent: devspec.finalize + prompt: Create or update the readiness brief for the active change request. + - label: Create Linked Work Item + agent: devspec.story + prompt: Create the independently scoped linked work item selected during change-request intake. +--- +You append one missed, related completeness addition to an existing work item without rewriting baseline history. + +## Constraints +- Follow the [Work-Item Target Pattern](../prompts/PATTERNS.md#work-item-target-pattern), [Work-Item Change Request Pattern](../prompts/PATTERNS.md#work-item-change-request-pattern), [Session Recovery Pattern](../prompts/PATTERNS.md#session-recovery-pattern), [Prerequisite Validation Pattern](../prompts/PATTERNS.md#prerequisite-validation-pattern), [Interactive Question Pattern](../prompts/PATTERNS.md#interactive-question-pattern), [Question Basis Pattern](../prompts/PATTERNS.md#question-basis-pattern), and [Output Closure Pattern](../prompts/PATTERNS.md#output-closure-pattern). +- `meta.md` and `story.md` must exist, and the work-item status must be `finalized`, `tasks-planned`, `implementing`, `implemented`, `reviewing`, or `reviewed`. +- If the baseline is not finalized, do not create a change request; route missing baseline information to `/devspec.story`, or `/devspec.clarify` when an active blocker already records the question. +- Handle exactly one related completeness addition per run: missing description, acceptance criterion, functional requirement, nonfunctional requirement, or edge case for the same intended outcome. +- Append the next `CR-###` to `story.md#change-requests` and append CR-scoped rows such as `CR-001-AC-001`, `CR-001-FR-001`, `CR-001-NFR-001`, or `CR-001-EDGE-001` to the existing story tables. +- Do not create a dedicated change-request Markdown file. Use existing `meta.md`, `story.md`, and `decisions.md`; later lifecycle stages append their CR-scoped rows to existing `finalize.md`, `tasks.md`, `implement.md`, and `review.md`. +- Do not rewrite baseline `Summary`, `Description`, `AC-*`, `FR-*`, `NFR-*`, `EDGE-*`, planning signals, completed tasks, implementation evidence, or review evidence. +- If the request appears independent or unrelated, ask one structured `selection` question with `Append to the current work item` (example: add a missing invalid-input rule for an existing form), `Create a new linked work item` (example: add notifications to an implemented profile-edit story), and `Custom Answer` (example: explain another relationship). Show exactly one recommendation with its justification. Do not append a `CR-###` when a linked item is selected. +- Update `Workflow State` in `meta.md` and `Resume State` in `story.md` before asking a target, relationship, or requirement question. +- Keep any material change-request decision in `decisions.md`; do not duplicate the intake rows there. +- Ask one structured question at a time and hand off to `/devspec.finalize` after accepting a related change request. + +## Approach +1. Locate the existing work item and read `meta.md`, `story.md`, `decisions.md`, and downstream artifacts when present. +2. Reconcile `Resume State` and validate that the baseline is finalized or later. +3. Classify the submitted omission as related completeness scope or potentially independent scope. diff --git a/.github/agents/devspec.clarify.agent.md b/.github/agents/devspec.clarify.agent.md index 7c2aa4f..788b636 100644 --- a/.github/agents/devspec.clarify.agent.md +++ b/.github/agents/devspec.clarify.agent.md @@ -9,6 +9,9 @@ handoffs: - label: Back to Work-Item Intake agent: devspec.story prompt: Revise work-item intake from this clarification. + - label: Capture Post-Baseline Change Request + agent: devspec.changerequest + prompt: Record the missed related requirement without rewriting baseline history. - label: Continue to Finalize agent: devspec.finalize prompt: Create or update the implementation readiness brief. @@ -21,9 +24,9 @@ You create or update `devspec/work-items//clarify.md`. - Update `Workflow State` in `meta.md` and `Resume State` in `clarify.md` before asking or resolving a blocking question. - Handle one independent blocker at a time. - Resolve the active blocker recorded in `story.md`, `finalize.md`, user input, or existing `clarify.md`; do not run the full Readiness Gap Scan in this command. -- Do not use clarification to introduce post-baseline scope. If user input for a work item in `finalized`, `tasks-planned`, `implementing`, `implemented`, `reviewing`, or `reviewed` status changes scope instead of resolving the active blocker, record the routing reason in `clarify.md`, leave baseline intake unchanged, and hand off to `/devspec.story`. +- Do not use clarification to introduce post-baseline scope. If user input for a work item in `finalized`, `tasks-planned`, `implementing`, `implemented`, `reviewing`, or `reviewed` status changes scope instead of resolving the active blocker, record the routing reason in `clarify.md`, leave baseline intake unchanged, and hand off to `/devspec.changerequest`. - Preserve and apply the Question Basis Pattern for the active blocker. -- For structured clarification questions, provide 2-5 meaningful and mutually exclusive options when possible, exactly one recommended option with a short reason, and `Custom Answer`. +- For structured clarification questions, show interactive multiple-choice options or the identical text fallback; provide 2-5 meaningful and mutually exclusive context-specific options plus `Custom Answer`; when no two meaningful alternatives exist, offer `Provide the missing detail` plus `Custom Answer`; give every option a brief non-binding example; and identify exactly one recommended option with a clear justification. - Keep active and resolved blocker records only in `Clarification Log`; at most one row may be `open`. - Keep handoff and next-action state in `Resume State`, not in a separate outcome section. - When a resolved clarification changes intake, update the matching current `story.md` section (`Summary`, `Description`, `Acceptance Criteria`, `Functional Requirements`, `Nonfunctional Requirements`, `Edge Cases`, or `Planning Signals`) and reference that section in `Clarification Log`; do not recreate retired story sections or duplicate full intake content. @@ -33,7 +36,7 @@ You create or update `devspec/work-items//clarify.md`. 1. Locate the target work item. 2. Read `meta.md` when present, `story.md`, `finalize.md` when present, and existing `clarify.md`. 3. Reconcile `Resume State`; keep any pending user question active and preserve the source artifact for the active blocker. -4. Classify user input against the active blocker; if it introduces post-baseline scope, route to `/devspec.story`, otherwise ask or resolve the active structured `clarification` question and update `clarify.md` with `Resume State` and `Clarification Log`. +4. Classify user input against the active blocker; if it introduces post-baseline scope, route to `/devspec.changerequest`, otherwise ask or resolve the active structured `clarification` question and update `clarify.md` with `Resume State` and `Clarification Log`. 5. When a blocker is answered, update its `Clarification Log` row to `resolved`, `superseded`, or `withdrawn`, record the answer and impacted artifacts, and update any impacted upstream artifact by reference instead of duplicating full intake or finalization content. 6. When no blocker remains open, update next action toward `/devspec.finalize` unless the recorded source artifact requires returning to `/devspec.story`. 7. Report per Output Format. diff --git a/.github/agents/devspec.extract.agent.md b/.github/agents/devspec.extract.agent.md index f7a4f2d..caa3e63 100644 --- a/.github/agents/devspec.extract.agent.md +++ b/.github/agents/devspec.extract.agent.md @@ -15,10 +15,10 @@ You create or refresh devspec extraction artifacts from supported repository sou ## Constraints - Follow the [Prerequisite Validation Pattern](../prompts/PATTERNS.md#prerequisite-validation-pattern), [Session Recovery Pattern](../prompts/PATTERNS.md#session-recovery-pattern), [Interactive Question Pattern](../prompts/PATTERNS.md#interactive-question-pattern), [Next Action Selection Pattern](../prompts/PATTERNS.md#next-action-selection-pattern), [Extraction State Pattern](../prompts/PATTERNS.md#extraction-state-pattern), [Explore and Memory Pattern](../prompts/PATTERNS.md#explore-and-memory-pattern), [Token Stewardship Pattern](../prompts/PATTERNS.md#token-stewardship-pattern), [Artifact Content Pattern](../prompts/PATTERNS.md#artifact-content-pattern), [Discovery Exclusion Pattern](../prompts/PATTERNS.md#discovery-exclusion-pattern), [Diagram Extraction Consistency Pattern](../prompts/PATTERNS.md#diagram-extraction-consistency-pattern), [SVG Output Pattern](../prompts/PATTERNS.md#svg-output-pattern), [Mermaid Internal Naming and Readability Pattern](../prompts/PATTERNS.md#mermaid-internal-naming-and-readability-pattern), [Mermaid Visual Quality Pattern](../prompts/PATTERNS.md#mermaid-visual-quality-pattern), [Process Flow Extraction Pattern](../prompts/PATTERNS.md#process-flow-extraction-pattern), [Exploration Recovery Pattern](../prompts/PATTERNS.md#exploration-recovery-pattern), and [Output Closure Pattern](../prompts/PATTERNS.md#output-closure-pattern). - Source input is optional. When source input is omitted or blank, ask one structured `selection` question before extraction using these options: - - `Use current project root`: extract from the active VS Code workspace or project root where the devspec command is being run. Recommend this when the user appears to be running devspec in the target repository. - - `Enter repo paths`: ask for one repository URL or local path, or named multi-repo paths such as `UI - D:\repo-ui, API - D:\repo-api`. - - `Cancel extraction`: stop extraction and record no artifact changes. - - `Custom Answer`: handle through the Interactive Question Pattern. + - `Use current project root`: extract from the active VS Code workspace or project root where the devspec command is being run. Example: use `D:\code\my-app` when it is the opened target repository. Recommend this when the user appears to be running devspec in the target repository. + - `Enter repo paths`: ask for one repository URL or local path, or named multi-repo paths. Example: `UI - D:\repo-ui, API - D:\repo-api`. + - `Cancel extraction`: stop extraction and record no artifact changes. Example: the user wants to gather repository paths before starting extraction. + - `Custom Answer`: accept another source instruction. Example: `Use only D:\code\api and skip the UI repository`. - Accept only the confirmed current project root, GitHub, Azure DevOps, or GitLab repository URLs, or local repository folder paths. - Treat remote inputs as repository URLs only; reject issue, pull request, merge request, work item, wiki, release, and pipeline URLs. - Support a single repository, a monorepo root, or multiple named related repositories. @@ -35,7 +35,7 @@ You create or refresh devspec extraction artifacts from supported repository sou - Before writing a confirmed constitution change, run a lightweight impact check against `devspec/foundation/project-context.md`, `devspec/foundation/rules.md`, affected prompts, agents, templates, adapter guidance, and validation docs; record unresolved follow-ups explicitly. - Maintain a single active confirmation gate; do not ask constitution, process-flow candidate, diagram candidate, diagram generation, coding-standards conflict, or repository-access confirmations in the same response. - Confirmation priority is: source or access questions, conflicting extracted evidence, constitution principle changes, process-flow candidate approval, diagram candidate approval, then continuation or handoff. -- Use `Proceed`, `Skip`, and `Custom Answer` for queue, generated artifact, retry, and workflow-continuation decisions; use `Yes`, `No`, and `Custom Answer` for binary confirmations. +- Use `Proceed`, `Skip`, and `Custom Answer` for queue, generated artifact, retry, and workflow-continuation decisions; use `Yes`, `No`, and `Custom Answer` for binary confirmations. Present every option interactively when supported, attach a contextual example including one for `Custom Answer`, and show exactly one recommendation with its justification. - Create or update `devspec/foundation/extraction-state.md` from `devspec/foundation/_template/extraction-state.md` when extraction starts and is not canceled. - Process `devspec/foundation/extraction-state.md#extraction-queue` one row at a time in ID order. Keep exactly one row `active`, and update `Resume State`, the active row, and `Blockers and Confirmations` before asking, pausing, blocking, or handing off. - Use `devspec/foundation/extraction-state.md` only for the extraction queue, resume state, blockers, and confirmations. Keep extracted facts in target artifacts, reusable discovery methods in `devspec/foundation/exploration-state.md`, and diagram queue state in `devspec/architecture/artifact-queue.md`. diff --git a/.github/agents/devspec.implement-task.agent.md b/.github/agents/devspec.implement-task.agent.md index 3c3960a..31d6ef5 100644 --- a/.github/agents/devspec.implement-task.agent.md +++ b/.github/agents/devspec.implement-task.agent.md @@ -11,6 +11,9 @@ handoffs: prompt: Review the current implementation. - label: Start Another Work Item agent: devspec.story + - label: Capture Post-Baseline Change Request + agent: devspec.changerequest + prompt: Record a missed related requirement without rewriting baseline history. prompt: Start or update another devspec work item. --- You implement the current work item and update `devspec/work-items//implement.md`. @@ -22,6 +25,7 @@ You implement the current work item and update `devspec/work-items//review.md`. ## Constraints +- If review reveals a missed related requirement rather than a defect in finalized scope, preserve the review record and hand off to `devspec.changerequest`. - Follow [PATTERNS.md](../prompts/PATTERNS.md), especially: Work-Item Target, Work-Item Change Request Pattern, Session Recovery, Interactive Question, Question Basis, Prerequisite Validation, Token Stewardship, Minimum Necessary Implementation, Task Quality Gate, Discovery Exclusion, Exploration Recovery, and Output Closure. - `finalize.md`, `tasks.md`, and `implement.md` must exist. - Review against the finalized brief, `tasks.md`, `implement.md`, and implemented changes, not a new plan. diff --git a/.github/agents/devspec.story.agent.md b/.github/agents/devspec.story.agent.md index 9f96217..560530d 100644 --- a/.github/agents/devspec.story.agent.md +++ b/.github/agents/devspec.story.agent.md @@ -31,7 +31,7 @@ You create or update work-item intake artifacts under `devspec/work-items/ `projectcontext` -> `techstack` -> `codebase-structure` -> `coding-standards` -> `rules` -Work items: `story` -> `finalize` -> `tasks` -> `implement` -> `review`; related post-baseline change requests re-enter through `story` and append `CR-###` scope records before continuing the same flow. +Work items: `story` -> `finalize` -> `tasks` -> `implement` -> `review`; related post-baseline completeness additions enter through `changerequest`, append `CR-###` scope records, and continue through the same flow. `story` retains compatible change-request intake for existing users. Use `clarify` only when work-item intake or finalization records a blocking question. @@ -27,6 +27,7 @@ The registered devspec slash commands are: - `/devspec.coding-standards` - `/devspec.rules` - `/devspec.story` +- `/devspec.changerequest` - `/devspec.clarify` - `/devspec.finalize` - `/devspec.tasks` @@ -80,6 +81,7 @@ See [Model recommendations](../../README.md#model-recommendations). Agent front | `devspec.codebase-structure.prompt.md` | Capture selective repository trees, repository configuration, work areas and boundaries, integration contracts, and structure gaps or blockers. | `foundation/codebase-structure.md` | | `devspec.coding-standards.prompt.md` | Capture an evidence-backed standards catalog with scoped rules, observed patterns, anti-patterns, source links, and optional short examples. | `foundation/coding-standards.md` | | `devspec.rules.prompt.md` | Capture actionable operational rules, compliance requirements, forbidden patterns, delivery gates, work-item handling rules, exceptions, enforcement points, source, and confidence. | `foundation/rules.md` | +| `devspec.changerequest.prompt.md` | Append one missed, related requirement to a finalized-or-later work item as a `CR-###` record. | Existing `meta.md`, `story.md`, `decisions.md` | | `devspec.story.prompt.md` | Create or update one work-item intake, or append a related post-baseline change request. | `meta.md`, `story.md`, `decisions.md`, `notes.md` | | `devspec.clarify.prompt.md` | Ask, resolve, and record one active blocking clarification. | `clarify.md` | | `devspec.finalize.prompt.md` | Create or update a structured implementation readiness brief with readiness assessment, foundation and architecture alignment, implementation brief, validation plan, and blockers. | `finalize.md` | diff --git a/.github/prompts/devspec.changerequest.prompt.md b/.github/prompts/devspec.changerequest.prompt.md new file mode 100644 index 0000000..a8bdf96 --- /dev/null +++ b/.github/prompts/devspec.changerequest.prompt.md @@ -0,0 +1,11 @@ +--- +name: "devspec.changerequest" +description: "Append one missed related requirement to a finalized work item without rewriting baseline history." +argument-hint: "Enter the existing work item and one missing description, acceptance criterion, requirement, quality constraint, or edge case" +agent: "devspec.changerequest" +--- + +Record one missed, related completeness addition for an existing work item whose status is `finalized`, `tasks-planned`, `implementing`, `implemented`, `reviewing`, or `reviewed`. Append the addition as the next `CR-###` row and CR-scoped story rows in the existing work-item artifacts; do not create a new Markdown file for the change request or rewrite baseline history. + +Use this command for a missing description, acceptance criterion, functional requirement, nonfunctional requirement, or edge case that completes the same intended outcome. If the input is independent, use the structured selection required by the [Work-Item Change Request Pattern](PATTERNS.md#work-item-change-request-pattern); a selected linked item continues through `/devspec.story`. + diff --git a/.github/prompts/devspec.clarify.prompt.md b/.github/prompts/devspec.clarify.prompt.md index fa5b82d..85b2da9 100644 --- a/.github/prompts/devspec.clarify.prompt.md +++ b/.github/prompts/devspec.clarify.prompt.md @@ -7,7 +7,7 @@ agent: "devspec.clarify" Create or update `devspec/work-items//clarify.md` for the current work item. -Use clarification only for active blockers inside current scope. If input introduces post-baseline scope for an item whose status is `finalized`, `tasks-planned`, `implementing`, `implemented`, `reviewing`, or `reviewed`, follow the [Work-Item Change Request Pattern](PATTERNS.md#work-item-change-request-pattern) and route to `/devspec.story`. +Use clarification only for active blockers inside current scope. If input introduces post-baseline scope for an item whose status is `finalized`, `tasks-planned`, `implementing`, `implemented`, `reviewing`, or `reviewed`, follow the [Work-Item Change Request Pattern](PATTERNS.md#work-item-change-request-pattern) and route to `/devspec.changerequest`. Optional user input: ${input:clarifyInput:Optional: answer the active blocker or add clarifying notes} diff --git a/.github/workflows/homebrew-package-publish.yml b/.github/workflows/homebrew-package-publish.yml index d78ea52..cfc3225 100644 --- a/.github/workflows/homebrew-package-publish.yml +++ b/.github/workflows/homebrew-package-publish.yml @@ -6,7 +6,7 @@ on: version: description: "Release version without the leading v" required: true - default: "0.1.3" + default: "0.2.0" push: tags: - "v*" @@ -19,7 +19,7 @@ jobs: name: Generate Homebrew formula artifact runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Generate Homebrew formula shell: bash @@ -46,7 +46,7 @@ jobs: echo "Source tarball SHA256: ${sha256}" - name: Upload Homebrew package artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: devspec-homebrew-package path: | diff --git a/.github/workflows/python-package-ci.yml b/.github/workflows/python-package-ci.yml index d8c21a0..cee7405 100644 --- a/.github/workflows/python-package-ci.yml +++ b/.github/workflows/python-package-ci.yml @@ -8,23 +8,24 @@ on: jobs: test: - name: Python package test (${{ matrix.os }}) + name: Python package test (${{ matrix.os }}, Python ${{ matrix.python-version }}) runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] + python-version: ["3.10", "3.14"] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Install uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v7 with: - python-version: "3.12" + python-version: ${{ matrix.python-version }} - name: Run tests run: uv run pytest diff --git a/.github/workflows/python-package-publish.yml b/.github/workflows/python-package-publish.yml index 4be916a..35f3e41 100644 --- a/.github/workflows/python-package-publish.yml +++ b/.github/workflows/python-package-publish.yml @@ -24,13 +24,13 @@ jobs: name: Build and publish Python package runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Install uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v7 with: python-version: "3.12" @@ -51,7 +51,7 @@ jobs: | xargs -0 sha256sum > dist/devspec-python-package-checksums.txt - name: Upload Python package release artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: devspec-python-package-dist path: dist/* @@ -66,6 +66,6 @@ jobs: - name: Attach Python package release artifacts if: startsWith(github.ref, 'refs/tags/v') - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@v3 with: files: dist/* diff --git a/.github/workflows/winget-package-publish.yml b/.github/workflows/winget-package-publish.yml index f4e97dd..bf5618d 100644 --- a/.github/workflows/winget-package-publish.yml +++ b/.github/workflows/winget-package-publish.yml @@ -14,13 +14,13 @@ jobs: name: Build WinGet portable package runs-on: windows-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Install uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v7 with: python-version: "3.12" @@ -40,7 +40,7 @@ jobs: } uv venv .venv-winget --python 3.12 --clear - uv pip install --python .\.venv-winget\Scripts\python.exe "pyinstaller>=6.0" $wheel.FullName + uv pip install --python .\.venv-winget\Scripts\python.exe "pyinstaller>=6.22.2" $wheel.FullName New-Item -ItemType Directory -Force -Path build\winget | Out-Null @( @@ -75,7 +75,7 @@ jobs: shell: pwsh run: | $ErrorActionPreference = "Stop" - $version = if ($env:GITHUB_REF_NAME -match "^v(.+)$") { $Matches[1] } else { "0.1.3" } + $version = if ($env:GITHUB_REF_NAME -match "^v(.+)$") { $Matches[1] } else { "0.2.0" } $hash = (Get-FileHash dist\winget\devspec.exe -Algorithm SHA256).Hash.ToLowerInvariant() "$hash devspec.exe" | Set-Content -Path dist\winget\devspec.exe.sha256 -Encoding ASCII @@ -93,7 +93,7 @@ jobs: Write-Host "WinGet manifests: $manifestRoot" - name: Upload WinGet package artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: devspec-winget-package path: | @@ -103,7 +103,7 @@ jobs: - name: Attach WinGet package artifacts if: startsWith(github.ref, 'refs/tags/v') - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@v3 with: files: | dist/winget/devspec.exe diff --git a/AGENTS.md b/AGENTS.md index 657bd41..631ff95 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -16,7 +16,7 @@ Before running or continuing any `devspec` workflow: ## Structured Questions -Follow `.github/prompts/PATTERNS.md#interactive-question-pattern` for user questions. Use clickable multiple-choice options when the host supports them; otherwise render the same option labels as text and ask the user to reply with one label or `Custom Answer`. Preserve question intent, option labels, the recommended option, and the continuation condition in the relevant `Resume State` or `Workflow State` before waiting for input. +Follow `.github/prompts/PATTERNS.md#interactive-question-pattern` for user questions. Show interactive multiple-choice options; if the host cannot render them, render the identical options as text and accept one option label or `Custom Answer`. Ask one question at a time, include an example for every option and `Custom Answer`, and show exactly one recommended option with its justification. Preserve question intent, option labels and examples, the `Custom Answer` entry or response, the recommended option and justification, and the continuation condition in the relevant `Resume State` or `Workflow State` before waiting for input. ## No Intent Drift @@ -67,7 +67,7 @@ Work-item story lifecycle: /devspec.review ``` -Use `/devspec.clarify` only when work-item intake or finalization records a blocking question. Use `/devspec.diagram` for diagram work after relevant context exists. +Use `/devspec.clarify` only when work-item intake or finalization records a blocking question. For a missed related requirement after finalization, use `/devspec.changerequest` and continue through `/devspec.finalize`, `/devspec.tasks`, `/devspec.implement`, and `/devspec.review`; it appends CR-scoped rows to existing work-item artifacts. Use `/devspec.diagram` for diagram work after relevant context exists. ## Enterprise Validation diff --git a/GEMINI.md b/GEMINI.md index 6ea10a0..7aa8c6a 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -11,7 +11,7 @@ Use this file as Gemini CLI and Gemini-backed agent context for this repository. - Treat `.github/prompts/*.prompt.md` and `.github/agents/*.agent.md` as the protected reference implementation. - Preserve canonical `/devspec.*` command vocabulary even when Gemini CLI invokes native commands such as `/devspec:story`. - Recover from Git-tracked `devspec/` artifacts before relying on Gemini session memory. -- Preserve structured question behavior from `.github/prompts/PATTERNS.md#interactive-question-pattern`; if Gemini does not provide clickable options, render the same option labels as text and preserve the recommended option. +- Preserve structured question behavior from `.github/prompts/PATTERNS.md#interactive-question-pattern`: show interactive multiple-choice options when Gemini can render them, otherwise render the identical options as text; include an example for every option and `Custom Answer`; ask one question at a time; and preserve the recommendation with its justification. - Do not store credentials, API keys, tokens, personal settings, or provider secrets in Gemini context, commands, or artifacts. ## Native Gemini Commands @@ -27,6 +27,7 @@ Gemini CLI project commands live under `.gemini/commands/devspec/`. | `/devspec.coding-standards` | `/devspec:coding-standards` | | `/devspec.rules` | `/devspec:rules` | | `/devspec.story` | `/devspec:story` | +| `/devspec.changerequest` | `/devspec:changerequest` | | `/devspec.clarify` | `/devspec:clarify` | | `/devspec.finalize` | `/devspec:finalize` | | `/devspec.tasks` | `/devspec:tasks` | diff --git a/README.md b/README.md index cd81c71..2a7961a 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,8 @@ For the full setup manual, see [docs/how-to/README.md](docs/how-to/README.md). | Situation | Start here | | --- | --- | | Simplest one-off setup | [uv and uvx setup](docs/how-to/setup/uv.md) | -| Persistent macOS/Linux package install | [Homebrew setup](docs/how-to/setup/homebrew.md) | | Approved Windows package install | [WinGet setup](docs/how-to/setup/winget.md) | +| Persistent macOS/Linux package install | [Homebrew setup](docs/how-to/setup/homebrew.md) | | CLI setup paths are blocked | [Manual copy setup](docs/how-to/setup/manual-copy.md) | Install profiles let you choose which AI coding agent files to copy. Most multi-agent teams can start with `--profile all`; single-tool teams can use a smaller profile such as `copilot`, `codex`, `cursor`, `claude`, `gemini`, or `antigravity`. @@ -74,7 +74,13 @@ Then run the work-item flow: /devspec.review ``` -Use `/devspec.clarify` only when a work item records a blocking question. Use `/devspec.diagram` when a diagram would clarify architecture, workflow, state, sequence, or domain behavior. +For a missed related requirement after finalization, use the append-only change-request route: + +![Work-item command selection guide](docs/assets/command-flow-work-item-selection.svg) + +`/devspec.changerequest` -> `/devspec.finalize` -> `/devspec.tasks` -> `/devspec.implement` -> `/devspec.review` + +Use `/devspec.clarify` only when a work item records a blocking question. Use `/devspec.changerequest` for a missed related requirement after finalization; it appends to existing work-item Markdown artifacts rather than creating a separate CR file. Use `/devspec.diagram` when a diagram would clarify architecture, workflow, state, sequence, or domain behavior. ## AI Tool Support diff --git a/devspec/adapters/antigravity.md b/devspec/adapters/antigravity.md index 7997b46..f3dde1b 100644 --- a/devspec/adapters/antigravity.md +++ b/devspec/adapters/antigravity.md @@ -13,6 +13,7 @@ Google Antigravity support is implemented through workspace rules under `.agents | `/devspec.coding-standards` | `/devspec-coding-standards` | | `/devspec.rules` | `/devspec-rules` | | `/devspec.story` | `/devspec-story` | +| `/devspec.changerequest` | `/devspec-changerequest` | | `/devspec.clarify` | `/devspec-clarify` | | `/devspec.finalize` | `/devspec-finalize` | | `/devspec.tasks` | `/devspec-tasks` | diff --git a/devspec/adapters/claude-code.md b/devspec/adapters/claude-code.md index 7c4b65e..775809a 100644 --- a/devspec/adapters/claude-code.md +++ b/devspec/adapters/claude-code.md @@ -13,6 +13,7 @@ Claude Code support is implemented through project skills under `.claude/skills/ | `/devspec.coding-standards` | `/devspec-coding-standards` | | `/devspec.rules` | `/devspec-rules` | | `/devspec.story` | `/devspec-story` | +| `/devspec.changerequest` | `/devspec-changerequest` | | `/devspec.clarify` | `/devspec-clarify` | | `/devspec.finalize` | `/devspec-finalize` | | `/devspec.tasks` | `/devspec-tasks` | diff --git a/devspec/adapters/command-registry.md b/devspec/adapters/command-registry.md index ebb5053..929d27d 100644 --- a/devspec/adapters/command-registry.md +++ b/devspec/adapters/command-registry.md @@ -22,6 +22,7 @@ This registry is the provider-neutral contract for all `devspec` adapters. The G | `/devspec.coding-standards` | Capture evidence-backed engineering standards, observed patterns, anti-patterns, source links, and examples. | Standards input, source links, or evidence to confirm. | `.github/prompts/devspec.coding-standards.prompt.md` | `.github/agents/devspec.coding-standards.agent.md` | `devspec/foundation/coding-standards.md` | `artifact-write` | `/devspec.rules` | | `/devspec.rules` | Capture operational hard constraints, compliance requirements, forbidden patterns, delivery gates, exceptions, enforcement points, source, and confidence. | Rules, gates, governance, compliance, or constraint input. | `.github/prompts/devspec.rules.prompt.md` | `.github/agents/devspec.rules.agent.md` | `devspec/foundation/rules.md` | `artifact-write` | `/devspec.story` | | `/devspec.story` | Create or update one work-item intake from a provider URL, provider identifier, manual feature request, bug report, security issue, task, or PBI; append related post-baseline change requests for existing work items without rewriting baseline rows. | One work-item reference, manual intake details, or change-request input for an existing work item. | `.github/prompts/devspec.story.prompt.md` | `.github/agents/devspec.story.agent.md` | `devspec/work-items//meta.md`, `story.md`, `decisions.md`, `notes.md` | `artifact-write` | `/devspec.clarify` if blocked; otherwise `/devspec.finalize` | +| `/devspec.changerequest` | Record one missed, related requirement for a finalized-or-later work item as an append-only change request without rewriting baseline history. | Existing work-item reference and one missing description, acceptance criterion, requirement, quality constraint, or edge case. | `.github/prompts/devspec.changerequest.prompt.md` | `.github/agents/devspec.changerequest.agent.md` | Existing work-item `meta.md`, `story.md`, and `decisions.md`; no new CR-specific Markdown file | `artifact-write` | `/devspec.finalize` for an accepted related CR; `/devspec.story` for a linked independent item | | `/devspec.clarify` | Ask, resolve, and record one active blocking clarification for an existing work item. | Existing work item with a recorded blocker or clarification need. | `.github/prompts/devspec.clarify.prompt.md` | `.github/agents/devspec.clarify.agent.md` | `devspec/work-items//clarify.md` | `artifact-write` | Repeat until unblocked, then `/devspec.finalize` | | `/devspec.finalize` | Create or update an implementation readiness brief with readiness assessment, foundation and architecture alignment, implementation brief, validation plan, and blockers; append CR-scoped readiness and validation rows for accepted post-baseline change requests. | Existing upstream work-item artifacts. Optional additive readiness or change-request input. | `.github/prompts/devspec.finalize.prompt.md` | `.github/agents/devspec.finalize.agent.md` | `devspec/work-items//finalize.md` | `artifact-write` | `/devspec.tasks` when ready | | `/devspec.tasks` | Break a ready finalized brief into ordered executable implementation tasks with scope, source refs, planning basis, task-quality review, validation, and done criteria; append CR-scoped task rows after existing tasks for accepted change requests. | `finalize.md` marked `ready`; optional task-planning or change-request planning input. | `.github/prompts/devspec.tasks.prompt.md` | `.github/agents/devspec.tasks.agent.md` | `devspec/work-items//tasks.md` | `artifact-write` | `/devspec.implement` | @@ -36,3 +37,4 @@ This registry is the provider-neutral contract for all `devspec` adapters. The G | New repository foundation | `/devspec.projectcontext` -> `/devspec.techstack` -> `/devspec.codebase-structure` -> `/devspec.coding-standards` -> `/devspec.rules` | Foundation artifacts exist, no extraction artifact is required, and each command records sources, confidence, blockers, and next action. | | Existing repository foundation | `/devspec.extract` -> `/devspec.projectcontext` -> `/devspec.techstack` -> `/devspec.codebase-structure` -> `/devspec.coding-standards` -> `/devspec.rules` | Extraction evidence is recorded, foundation artifacts are refined, exclusions are respected, blockers are explicit, and confirmations are preserved. | | Story lifecycle | `/devspec.story` -> optional `/devspec.clarify` -> `/devspec.finalize` -> `/devspec.tasks` -> `/devspec.implement` -> `/devspec.review` | Work-item artifacts exist, readiness is honored, tasks are executable, scoped, and source-referenced, append-only change requests preserve baseline history, implementation ledger is current, validation evidence is recorded, task-to-review alignment is checked, and review status uses glossary values. | +| Post-baseline completeness | `/devspec.changerequest` -> `/devspec.finalize` -> `/devspec.tasks` -> `/devspec.implement` -> `/devspec.review` | A related omission is appended as `CR-###` in the existing work-item ledger; baseline rows and prior evidence remain immutable. | diff --git a/devspec/adapters/gemini-cli.md b/devspec/adapters/gemini-cli.md index 88a719e..ebb09a3 100644 --- a/devspec/adapters/gemini-cli.md +++ b/devspec/adapters/gemini-cli.md @@ -13,6 +13,7 @@ Gemini CLI support is implemented through root `GEMINI.md` plus project custom c | `/devspec.coding-standards` | `/devspec:coding-standards` | | `/devspec.rules` | `/devspec:rules` | | `/devspec.story` | `/devspec:story` | +| `/devspec.changerequest` | `/devspec:changerequest` | | `/devspec.clarify` | `/devspec:clarify` | | `/devspec.finalize` | `/devspec:finalize` | | `/devspec.tasks` | `/devspec:tasks` | diff --git a/devspec/adapters/validation-flows.md b/devspec/adapters/validation-flows.md index 70ca588..1211504 100644 --- a/devspec/adapters/validation-flows.md +++ b/devspec/adapters/validation-flows.md @@ -79,11 +79,11 @@ Validate that post-baseline scope changes preserve the original story ledger. | --- | --- | --- | | 1 | `/devspec.story` with `.NET 10 upgrade` | Baseline `story.md` records the upgrade scope with `AC-*`, `FR-*`, and related planning rows. | | 2 | `/devspec.finalize` -> `/devspec.tasks` -> `/devspec.implement` | Baseline `finalize.md`, `tasks.md`, and `implement.md` record ready scope, `baseline` task rows such as `T-001..T-003`, and implementation evidence. | -| 3 | `/devspec.story` with `Change request for existing .NET 10 upgrade story: increase code coverage from 60% to 80%` | `story.md#change-requests` appends `CR-001`; CR-scoped criteria such as `CR-001-AC-001` are added without rewriting baseline summary, description, or criteria. | +| 3 | `/devspec.changerequest` with `Existing .NET 10 upgrade story: missing acceptance criterion requiring 80% coverage` | `story.md#change-requests` appends `CR-001`; CR-scoped criteria such as `CR-001-AC-001` are added without rewriting baseline summary, description, or criteria, and no CR-specific Markdown file is created. | | 4 | `/devspec.finalize` -> `/devspec.tasks` -> `/devspec.implement` | `finalize.md` appends `CR-001` readiness, implementation brief, and validation rows; `tasks.md` appends new `Scope` = `CR-001` rows after the highest existing task ID; `implement.md` appends CR-scoped evidence and execution-log rows while `tasks.md` updates only the matching `CR-001` task rows. | -| 5 | `/devspec.story` with another related request | `story.md#change-requests` appends `CR-002`; task planning later appends new task IDs without renumbering or rewriting `CR-001` or baseline rows. | -| 6 | `/devspec.story` with an unrelated feature request for the same target | The agent asks one structured `selection` question to append to the current item, create a new linked work item, or provide `Custom Answer`; when the linked-item option is chosen, the new work-item folder follows the standard folder naming pattern, its `meta.md#work-item-record` `Parent work item` points to the original item, and the original item does not receive a `CR-###` row for that linked request. | -| 7 | `/devspec.clarify` with post-baseline scope input | `clarify.md` records routing to `/devspec.story`; baseline intake remains unchanged. | +| 5 | `/devspec.changerequest` with another related omission | `story.md#change-requests` appends `CR-002`; task planning later appends new task IDs without renumbering or rewriting `CR-001` or baseline rows. | +| 6 | `/devspec.changerequest` with an unrelated feature request for the same target | The agent asks one interactive `selection` question with examples for `Append to the current item`, `Create a new linked work item`, and `Custom Answer`, plus exactly one recommendation with its justification; when the linked-item option is chosen, `/devspec.story` creates the new work-item folder under the standard naming pattern, its `meta.md#work-item-record` `Parent work item` points to the original item, and the original item does not receive a `CR-###` row for that linked request. | +| 7 | `/devspec.clarify` with post-baseline scope input | `clarify.md` records routing to `/devspec.changerequest`; baseline intake remains unchanged. | | 8 | `/devspec.review` | Review flags missing CR task rows, missing CR source refs, CR work implemented outside appended tasks, source-ref drift, or overwritten baseline content. | Acceptance checklist: @@ -97,7 +97,19 @@ Acceptance checklist: - `tasks.md#implementation-tasks` includes `Scope` with `baseline` or `CR-###`. - New CR task rows append after the highest existing `T-###`. - `/devspec.implement` processes the active `CR-###` scope without rewriting baseline or prior CR implementation evidence. -- No `/devspec.change` command is introduced or recommended. +- No unregistered change-request alias such as `/devspec.change` is introduced or recommended; use `/devspec.changerequest`. + +## Interactive Question Contract Scenario + +Validate the same question behavior in every supported coding-agent adapter. + +| Step | Scenario | Expected evidence | +| --- | --- | --- | +| 1 | A finite selection is required | The agent asks exactly one interactive multiple-choice question with 2-5 contextual options plus `Custom Answer`; every option has a non-binding example and exactly one option is recommended with a justification. | +| 2 | Interactive controls are unavailable | The agent renders the identical option labels and examples as text, accepts an option label or `Custom Answer`, and preserves the same recommendation and justification. | +| 3 | An open-ended fact is required | The agent asks exactly one clarification question with `Provide the missing detail` and `Custom Answer`, each with an example, then waits for the answer. | +| 4 | The answer is incomplete, ambiguous, conflicting, or custom | The agent records the response and asks only the next clarification needed to resolve it before continuing. | +| 5 | The question is persisted | The relevant state records intent, source, gap, material impact, option labels and examples, the `Custom Answer` entry or response, recommendation and justification, continuation condition, and next action. | ## Cross-Tool Recovery Scenario diff --git a/devspec/architecture/_template/diagram.md b/devspec/architecture/_template/diagram.md index ea80876..b927565 100644 --- a/devspec/architecture/_template/diagram.md +++ b/devspec/architecture/_template/diagram.md @@ -14,7 +14,10 @@ Use this optional Markdown artifact for one durable Mermaid architecture, module | Last completed step | | | Next required action | | | Pending user question | | -| Recommended option | | +| Question options and examples | | +| Custom Answer entry or response | | +| Recommended option and justification | | +| Continuation condition | | | Resume command | `/devspec.diagram` | | Resume notes | | | Updated | | diff --git a/devspec/foundation/_template/extraction-state.md b/devspec/foundation/_template/extraction-state.md index 9581fc2..d17262a 100644 --- a/devspec/foundation/_template/extraction-state.md +++ b/devspec/foundation/_template/extraction-state.md @@ -14,7 +14,10 @@ Use this artifact only for the `/devspec.extract` queue, resume state, blockers, | Last completed step | | | Next required action | | | Pending user question | | -| Recommended option | | +| Question options and examples | | +| Custom Answer entry or response | | +| Recommended option and justification | | +| Continuation condition | | | Resume command | `/devspec.extract` | | Resume notes | | | Updated | | diff --git a/devspec/foundation/_template/provider-integrations.md b/devspec/foundation/_template/provider-integrations.md index fecbf80..e8d86ec 100644 --- a/devspec/foundation/_template/provider-integrations.md +++ b/devspec/foundation/_template/provider-integrations.md @@ -67,6 +67,7 @@ Offer only these structured `confirmation` actions: | Cancel | Stop intake. | | Custom Answer | Route to clarification; do not create or update the work-item folder until resolved. | +Present these actions as one interactive multiple-choice question, or the identical text fallback. Give every action a contextual, non-binding example; include `Custom Answer` with an example of another requested handling; and show exactly one recommendation with its justification. ## Integration Tooling and Access | Area | Requirement | diff --git a/devspec/foundation/provider-integrations.md b/devspec/foundation/provider-integrations.md index fecbf80..e8d86ec 100644 --- a/devspec/foundation/provider-integrations.md +++ b/devspec/foundation/provider-integrations.md @@ -67,6 +67,7 @@ Offer only these structured `confirmation` actions: | Cancel | Stop intake. | | Custom Answer | Route to clarification; do not create or update the work-item folder until resolved. | +Present these actions as one interactive multiple-choice question, or the identical text fallback. Give every action a contextual, non-binding example; include `Custom Answer` with an example of another requested handling; and show exactly one recommendation with its justification. ## Integration Tooling and Access | Area | Requirement | diff --git a/devspec/work-items/_template/clarify.md b/devspec/work-items/_template/clarify.md index a00077d..be24870 100644 --- a/devspec/work-items/_template/clarify.md +++ b/devspec/work-items/_template/clarify.md @@ -14,15 +14,18 @@ Use this artifact only for blocking ambiguity resolution. Keep state in `Resume | Last completed step | | | Next required action | | | Pending user question | active blocker ID or none | -| Recommended option | active blocker option and reason or none | +| Question options and examples | active blocker options, including `Custom Answer`, and examples or none | +| Custom Answer entry or response | active blocker entry or response, or none | +| Recommended option and justification | active blocker option and justification or none | +| Continuation condition | active blocker continuation condition or none | | Resume command | `/devspec.clarify` | | Resume notes | | | Updated | | ## Clarification Log -Use one row per blocker and at most one `open` row. Open blockers must preserve the question basis: source artifact or evidence, blocking gap, material impact, question intent, option labels including `Custom Answer`, recommended option with reason, impacted artifacts, continuation condition, and next action. When no blocker is active, set `Pending user question` to `none` and put the handoff in `Next required action`. +Use one row per blocker and at most one `open` row. Open blockers must preserve the question basis: source artifact or evidence, blocking gap, material impact, question intent, option labels and examples including `Custom Answer`, recommended option with justification, impacted artifacts, continuation condition, and next action. When no blocker is active, set `Pending user question` to `none` and put the handoff in `Next required action`. -| ID | Status | Source artifact or evidence | Blocking gap | Material impact | Question intent and prompt | Options | Recommended option and reason | User answer | Impacted artifacts | Continuation condition or next action | Updated | +| ID | Status | Source artifact or evidence | Blocking gap | Material impact | Question intent and prompt | Options | Recommended option and justification | User answer | Impacted artifacts | Continuation condition or next action | Updated | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | -| CLAR-001 | open, resolved, superseded, withdrawn | `story.md`, `finalize.md`, user input, provider evidence, repository evidence, or other source | | | intent and prompt text | option labels including `Custom Answer` | | | | | | +| CLAR-001 | open, resolved, superseded, withdrawn | `story.md`, `finalize.md`, user input, provider evidence, repository evidence, or other source | | | intent and prompt text | option labels and examples, including `Custom Answer` | | | | | | diff --git a/devspec/work-items/_template/diagrams.md b/devspec/work-items/_template/diagrams.md index e36e025..1e21c7a 100644 --- a/devspec/work-items/_template/diagrams.md +++ b/devspec/work-items/_template/diagrams.md @@ -16,7 +16,10 @@ Reusable default SVG diagrams live under `devspec/architecture/images/`; optiona | Last completed step | | | Next required action | | | Pending user question | | -| Recommended option | | +| Question options and examples | | +| Custom Answer entry or response | | +| Recommended option and justification | | +| Continuation condition | | | Resume command | `/devspec.diagram` | | Resume notes | | | Updated | | diff --git a/devspec/work-items/_template/finalize.md b/devspec/work-items/_template/finalize.md index 6dbedb1..41df1d8 100644 --- a/devspec/work-items/_template/finalize.md +++ b/devspec/work-items/_template/finalize.md @@ -14,7 +14,10 @@ Use this artifact for readiness, foundation and architecture alignment, implemen | Last completed step | | | Next required action | | | Pending user question | | -| Recommended option | | +| Question options and examples | | +| Custom Answer entry or response | | +| Recommended option and justification | | +| Continuation condition | | | Resume command | `/devspec.finalize` | | Resume notes | | | Updated | | diff --git a/devspec/work-items/_template/implement.md b/devspec/work-items/_template/implement.md index dcd4a32..7c13232 100644 --- a/devspec/work-items/_template/implement.md +++ b/devspec/work-items/_template/implement.md @@ -14,7 +14,10 @@ Use this artifact for implementation recovery, evidence, and handoff. Keep task | Last completed step | | | Next required action | | | Pending user question | | -| Recommended option | | +| Question options and examples | | +| Custom Answer entry or response | | +| Recommended option and justification | | +| Continuation condition | | | Resume command | `/devspec.implement` | | Resume notes | | | Updated | | diff --git a/devspec/work-items/_template/meta.md b/devspec/work-items/_template/meta.md index 4f91ad7..5b8f5f8 100644 --- a/devspec/work-items/_template/meta.md +++ b/devspec/work-items/_template/meta.md @@ -57,7 +57,10 @@ Use this section for routing and lookup only; details live in `story.md`. | Last completed step | | | Next required action | | | Pending user question | | -| Recommended option | | +| Question options and examples | | +| Custom Answer entry or response | | +| Recommended option and justification | | +| Continuation condition | | | Resume command | | | Resume notes | | | Updated | | diff --git a/devspec/work-items/_template/review.md b/devspec/work-items/_template/review.md index 1dfe1eb..d290b12 100644 --- a/devspec/work-items/_template/review.md +++ b/devspec/work-items/_template/review.md @@ -14,7 +14,10 @@ Use this artifact for review outcome, actionable findings, and handoff. Omit pla | Last completed step | | | Next required action | | | Pending user question | | -| Recommended option | | +| Question options and examples | | +| Custom Answer entry or response | | +| Recommended option and justification | | +| Continuation condition | | | Resume command | `/devspec.review` | | Resume notes | | | Updated | | diff --git a/devspec/work-items/_template/story.md b/devspec/work-items/_template/story.md index b8f057c..019cc9f 100644 --- a/devspec/work-items/_template/story.md +++ b/devspec/work-items/_template/story.md @@ -14,7 +14,10 @@ Use this artifact for one work item or story at a time. Keep identity and routin | Last completed step | | | Next required action | | | Pending user question | | -| Recommended option | | +| Question options and examples | | +| Custom Answer entry or response | | +| Recommended option and justification | | +| Continuation condition | | | Resume command | `/devspec.story` | | Resume notes | | | Updated | | diff --git a/devspec/work-items/_template/tasks.md b/devspec/work-items/_template/tasks.md index 639f796..4d51990 100644 --- a/devspec/work-items/_template/tasks.md +++ b/devspec/work-items/_template/tasks.md @@ -14,7 +14,10 @@ Use this artifact for executable implementation checkpoints. Keep recovery in `R | Last completed step | | | Next required action | | | Pending user question | | -| Recommended option | | +| Question options and examples | | +| Custom Answer entry or response | | +| Recommended option and justification | | +| Continuation condition | | | Resume command | `/devspec.tasks` | | Resume notes | | | Updated | | diff --git a/docs/assets/command-flow-work-item-lifecycle.svg b/docs/assets/command-flow-work-item-lifecycle.svg index c42db8a..042088a 100644 --- a/docs/assets/command-flow-work-item-lifecycle.svg +++ b/docs/assets/command-flow-work-item-lifecycle.svg @@ -1,6 +1,6 @@ Work-item lifecycle flow - Work-item lifecycle command sequence from story to review, with clarify as a conditional blocker-resolution branch and diagram as an optional supporting command. + Work-item lifecycle command sequence from story to review, with clarify as a conditional blocker-resolution branch, an append-only post-finalization change-request loop, and diagram as an optional supporting command. @@ -17,6 +17,7 @@ .node { fill: #064e3b; stroke: #34d399; stroke-width: 2; rx: 12; } .gate { fill: #431407; stroke: #fb923c; } .support { fill: #3b0764; stroke: #c084fc; } + .change { fill: #4c1d12; stroke: #fb923c; } .label { fill: #f8fafc; font-size: 13px; font-weight: 700; } .note { fill: #94a3b8; font-size: 12px; } .flow { fill: none; stroke: #34d399; stroke-width: 3; marker-end: url(#arrow-green); } @@ -67,6 +68,13 @@ + + /devspec.changerequest + missed related requirement + + + post-finalization only + /devspec.diagram optional visual diff --git a/docs/assets/command-flow-work-item-selection.svg b/docs/assets/command-flow-work-item-selection.svg new file mode 100644 index 0000000..89ff9e1 --- /dev/null +++ b/docs/assets/command-flow-work-item-selection.svg @@ -0,0 +1,41 @@ + + Work-item command selection guide + Decision guide for choosing story, clarify, changerequest, or a linked work item based on requirement timing and relationship to the current work item. + + + + + + + Which work-item command should I use? + Choose by timing, relationship to the existing outcome, and whether a recorded blocker is active. + + + + + + + + + Requirement update + or discovered omission + + Where does it fit? + timing + relationship + + /devspec.story + new or pre-finalization scope + + /devspec.changerequest + related omission after finalization + + /devspec.clarify + active blocker in current scope + + Linked /devspec.story + independent feature or outcome + + /devspec.finalize → tasks + then implement and review the CR + Baseline records are immutable after finalization; a related omission appends CR-scoped rows to existing work-item Markdown files. + diff --git a/docs/how-to/README.md b/docs/how-to/README.md index 49df66d..0c81c94 100644 --- a/docs/how-to/README.md +++ b/docs/how-to/README.md @@ -132,6 +132,7 @@ Canonical command names remain `/devspec.*`. Some AI coding agents expose host-n | `/devspec.coding-standards` | `/devspec.coding-standards` | `/devspec-coding-standards` | `Run /devspec.coding-standards ...` | `Run /devspec.coding-standards ...` | `/devspec:coding-standards` | `/devspec-coding-standards` | | `/devspec.rules` | `/devspec.rules` | `/devspec-rules` | `Run /devspec.rules ...` | `Run /devspec.rules ...` | `/devspec:rules` | `/devspec-rules` | | `/devspec.story` | `/devspec.story` | `/devspec-story` | `Run /devspec.story ...` | `Run /devspec.story ...` | `/devspec:story` | `/devspec-story` | +| `/devspec.changerequest` | `/devspec.changerequest` | `/devspec-changerequest` | `Run /devspec.changerequest ...` | `Run /devspec.changerequest ...` | `/devspec:changerequest` | `/devspec-changerequest` | | `/devspec.clarify` | `/devspec.clarify` | `/devspec-clarify` | `Run /devspec.clarify ...` | `Run /devspec.clarify ...` | `/devspec:clarify` | `/devspec-clarify` | | `/devspec.finalize` | `/devspec.finalize` | `/devspec-finalize` | `Run /devspec.finalize ...` | `Run /devspec.finalize ...` | `/devspec:finalize` | `/devspec-finalize` | | `/devspec.tasks` | `/devspec.tasks` | `/devspec-tasks` | `Run /devspec.tasks ...` | `Run /devspec.tasks ...` | `/devspec:tasks` | `/devspec-tasks` | @@ -292,7 +293,7 @@ Use the work-item lifecycle after the foundation exists. | Step | Command | Gate or note | | --- | --- | --- | -| 1 | `/devspec.story` | Accepts a provider URL, provider identifier, manual feature request, bug report, security issue, task, PBI, or related post-baseline change request. | +| 1 | `/devspec.story` | Accepts a provider URL, provider identifier, manual feature request, bug report, security issue, task, or PBI. | | 2 | `/devspec.clarify` | Use only when intake or finalization records a blocking question. | | 3 | `/devspec.finalize` | Creates the implementation readiness brief. | | 4 | `/devspec.tasks` | Requires `finalize.md` marked `ready`. | @@ -345,16 +346,19 @@ If a blocking question is recorded, resolve it before continuing: /devspec.clarify ``` -Use `/devspec.clarify` only for active blockers inside the current scope. If the user introduces new scope after the work item is finalized or later, route that input through `/devspec.story` as a change request. +Use `/devspec.clarify` only for active blockers inside the current scope. If the user introduces a missed related requirement after the work item is finalized or later, route that input through `/devspec.changerequest`. ## Post-Baseline Change Requests -Use `/devspec.story` again when a related request arrives after the baseline work item is finalized, tasks-planned, implementing, implemented, reviewing, or reviewed. Related requests append as `CR-001`, `CR-002`, and so on inside the same work-item folder. The original baseline summary, description, acceptance criteria, completed task rows, implementation evidence, and review history stay intact. +![Work-item command selection guide](../assets/command-flow-work-item-selection.svg) + + +Use `/devspec.changerequest` when a related omission is discovered after the baseline work item is finalized, tasks-planned, implementing, implemented, reviewing, or reviewed. It appends `CR-001`, `CR-002`, and so on inside the same work-item folder; no separate change-request Markdown file is created. The original baseline summary, description, acceptance criteria, completed task rows, implementation evidence, and review history stay intact. Canonical command for a related coverage change on an existing .NET 10 upgrade story: ```text -/devspec.story "Change request for existing .NET 10 upgrade story: increase code coverage from 60% to 80%" +/devspec.changerequest "Existing .NET 10 upgrade story: missing acceptance criterion requiring 80% coverage" ``` Then continue the normal work-item flow for the active change request: @@ -369,7 +373,7 @@ Then continue the normal work-item flow for the active change request: For OpenAI Codex or Cursor, use the same intent as chat input: ```text -Run /devspec.story with change request for existing .NET 10 upgrade story: increase code coverage from 60% to 80%. +Run /devspec.changerequest for the existing .NET 10 upgrade story with the missing acceptance criterion requiring 80% coverage. Run /devspec.finalize. Run /devspec.tasks. Run /devspec.implement. @@ -379,7 +383,7 @@ Run /devspec.review. For Gemini CLI: ```text -/devspec:story "Change request for existing .NET 10 upgrade story: increase code coverage from 60% to 80%" +/devspec:changerequest "Existing .NET 10 upgrade story: missing acceptance criterion requiring 80% coverage" /devspec:finalize /devspec:tasks /devspec:implement @@ -389,14 +393,16 @@ For Gemini CLI: For Claude Code or Google Antigravity: ```text -/devspec-story "Change request for existing .NET 10 upgrade story: increase code coverage from 60% to 80%" +/devspec-changerequest "Existing .NET 10 upgrade story: missing acceptance criterion requiring 80% coverage" /devspec-finalize /devspec-tasks /devspec-implement /devspec-review ``` -If the request appears independent or unrelated, the agent asks one structured selection question before writing: append to the current work item, create a new linked work item, or provide `Custom Answer`. Choose a new linked work item when the request should have its own scope, tasks, implementation record, and review. +If the request appears independent or unrelated, the agent asks one structured selection question before writing with `Append to the current work item` (example: a closely related refinement), `Create a new linked work item` (example: an independent feature with its own tasks), and `Custom Answer` (example: another relationship). It shows one recommendation with its justification; choose a new linked work item when the request should have its own scope, tasks, implementation record, and review. + +Every Devspec question is asked one at a time with interactive multiple-choice options when the host supports them, or the identical text options otherwise. Each option, including `Custom Answer`, includes a non-binding example, and the agent shows one recommended option with its justification before waiting for the response. ## Command Examples @@ -409,8 +415,9 @@ Use these examples as starting points. The command registry remains authoritativ | `/devspec.techstack` | Runtime, framework, hosting, tooling, CI, support constraints | `devspec/foundation/tech-stack.md` | `/devspec.codebase-structure` | | `/devspec.codebase-structure` | Repository layout, work areas, integration boundaries, access requirements | `devspec/foundation/codebase-structure.md` | `/devspec.coding-standards` | | `/devspec.coding-standards` | Style guides, observed patterns, testing expectations, anti-patterns | `devspec/foundation/coding-standards.md` | `/devspec.rules` | +| `/devspec.changerequest` | Existing finalized work item plus one missing related description, criterion, requirement, quality constraint, or edge case | Existing `meta.md`, `story.md`, `decisions.md`; no new CR-specific Markdown file | `/devspec.finalize` or `/devspec.story` for a linked independent item | | `/devspec.rules` | Compliance requirements, delivery gates, forbidden patterns, operational governance rules | `devspec/foundation/rules.md` | `/devspec.story` | -| `/devspec.story` | `https://github.com/example/repo/issues/123`; `owner/repo#123`; `JIRA-123`; manual bug report; `"Change request for existing .NET 10 upgrade story: increase code coverage from 60% to 80%"` | Work-item `meta.md`, `story.md`, `decisions.md`, `notes.md` | `/devspec.clarify` if blocked, otherwise `/devspec.finalize` | +| `/devspec.story` | `https://github.com/example/repo/issues/123`; `owner/repo#123`; `JIRA-123`; manual bug report | Work-item `meta.md`, `story.md`, `decisions.md`, `notes.md` | `/devspec.clarify` if blocked, otherwise `/devspec.finalize` | | `/devspec.clarify` | Existing work item with a recorded blocker | Work-item `clarify.md` | Repeat until unblocked, then `/devspec.finalize` | | `/devspec.finalize` | Existing story artifacts plus optional readiness or accepted change-request input | Work-item `finalize.md` | `/devspec.tasks` when ready | | `/devspec.tasks` | Ready `finalize.md`; optional task-planning or accepted change-request planning guidance | Work-item `tasks.md` | `/devspec.implement` | @@ -698,16 +705,16 @@ For WinGet releases, publish the Windows portable executable from GitHub Release ```text dist/winget/devspec.exe dist/winget/devspec.exe.sha256 -dist/winget/manifests/s/SpecLabs/Devspec/0.1.3/SpecLabs.Devspec.yaml -dist/winget/manifests/s/SpecLabs/Devspec/0.1.3/SpecLabs.Devspec.locale.en-US.yaml -dist/winget/manifests/s/SpecLabs/Devspec/0.1.3/SpecLabs.Devspec.installer.yaml +dist/winget/manifests/s/SpecLabs/Devspec/0.2.0/SpecLabs.Devspec.yaml +dist/winget/manifests/s/SpecLabs/Devspec/0.2.0/SpecLabs.Devspec.locale.en-US.yaml +dist/winget/manifests/s/SpecLabs/Devspec/0.2.0/SpecLabs.Devspec.installer.yaml ``` The manifest path is case-sensitive and must match `PackageIdentifier: SpecLabs.Devspec`. Validate the generated manifest directory on Windows before submission: ```text -winget validate dist/winget/manifests/s/SpecLabs/Devspec/0.1.3 -winget install --manifest dist/winget/manifests/s/SpecLabs/Devspec/0.1.3 +winget validate dist/winget/manifests/s/SpecLabs/Devspec/0.2.0 +winget install --manifest dist/winget/manifests/s/SpecLabs/Devspec/0.2.0 ``` When adapter files are added, removed, or moved, update: diff --git a/packaging/homebrew/devspec.rb b/packaging/homebrew/devspec.rb index 6101f23..e871cdf 100644 --- a/packaging/homebrew/devspec.rb +++ b/packaging/homebrew/devspec.rb @@ -3,20 +3,20 @@ class Devspec < Formula desc "Installer and synchronizer CLI for the devspec workflow framework" homepage "https://github.com/speclabs/devspec" - url "https://github.com/speclabs/devspec/archive/refs/tags/v0.1.3.tar.gz" - sha256 "REPLACE_WITH_V0_1_3_RELEASE_SHA256" + url "https://github.com/speclabs/devspec/archive/refs/tags/v0.2.0.tar.gz" + sha256 "REPLACE_WITH_V0_2_0_RELEASE_SHA256" license "Apache-2.0" depends_on "python@3.12" resource "hatchling" do - url "https://files.pythonhosted.org/packages/63/4c/8717ccb844b4fa5a5ba6352e97d743ed24e9a22cf90b7c109c17030a46a1/hatchling-1.30.1.tar.gz" - sha256 "eee4fd45357f72ebb3d7a42e5d72cfb5e29ed426d79e8836288926c4258d5f2e" + url "https://files.pythonhosted.org/packages/69/08/33331757185504aae48b8d9bd78cec03a76e3aecfb52e549d05a2347c0dd/hatchling-1.32.0.tar.gz" + sha256 "0bdbde4a52b06c37e3eca395f85a762bf0ef06fe374fd8ae429dc6be10230f5f" end resource "packaging" do - url "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz" - sha256 "ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661" + url "https://files.pythonhosted.org/packages/7d/fa/3944b40b07da9ce895c0e6303a5ab7d53da063554f534556b134a54d6093/packaging-26.3.tar.gz" + sha256 "94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79" end resource "pathspec" do diff --git a/packaging/homebrew/tap/Formula/devspec.rb b/packaging/homebrew/tap/Formula/devspec.rb index 6101f23..e871cdf 100644 --- a/packaging/homebrew/tap/Formula/devspec.rb +++ b/packaging/homebrew/tap/Formula/devspec.rb @@ -3,20 +3,20 @@ class Devspec < Formula desc "Installer and synchronizer CLI for the devspec workflow framework" homepage "https://github.com/speclabs/devspec" - url "https://github.com/speclabs/devspec/archive/refs/tags/v0.1.3.tar.gz" - sha256 "REPLACE_WITH_V0_1_3_RELEASE_SHA256" + url "https://github.com/speclabs/devspec/archive/refs/tags/v0.2.0.tar.gz" + sha256 "REPLACE_WITH_V0_2_0_RELEASE_SHA256" license "Apache-2.0" depends_on "python@3.12" resource "hatchling" do - url "https://files.pythonhosted.org/packages/63/4c/8717ccb844b4fa5a5ba6352e97d743ed24e9a22cf90b7c109c17030a46a1/hatchling-1.30.1.tar.gz" - sha256 "eee4fd45357f72ebb3d7a42e5d72cfb5e29ed426d79e8836288926c4258d5f2e" + url "https://files.pythonhosted.org/packages/69/08/33331757185504aae48b8d9bd78cec03a76e3aecfb52e549d05a2347c0dd/hatchling-1.32.0.tar.gz" + sha256 "0bdbde4a52b06c37e3eca395f85a762bf0ef06fe374fd8ae429dc6be10230f5f" end resource "packaging" do - url "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz" - sha256 "ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661" + url "https://files.pythonhosted.org/packages/7d/fa/3944b40b07da9ce895c0e6303a5ab7d53da063554f534556b134a54d6093/packaging-26.3.tar.gz" + sha256 "94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79" end resource "pathspec" do diff --git a/packaging/winget/manifests/s/SpecLabs/Devspec/0.2.0/SpecLabs.Devspec.installer.yaml b/packaging/winget/manifests/s/SpecLabs/Devspec/0.2.0/SpecLabs.Devspec.installer.yaml new file mode 100644 index 0000000..592b6a2 --- /dev/null +++ b/packaging/winget/manifests/s/SpecLabs/Devspec/0.2.0/SpecLabs.Devspec.installer.yaml @@ -0,0 +1,12 @@ +# yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.12.0.schema.json +PackageIdentifier: SpecLabs.Devspec +PackageVersion: 0.2.0 +InstallerType: portable +Commands: + - devspec +Installers: + - Architecture: x64 + InstallerUrl: https://github.com/speclabs/devspec/releases/download/v0.2.0/devspec.exe + InstallerSha256: REPLACE_WITH_RELEASE_SHA256 +ManifestType: installer +ManifestVersion: 1.12.0 diff --git a/packaging/winget/manifests/s/SpecLabs/Devspec/0.2.0/SpecLabs.Devspec.locale.en-US.yaml b/packaging/winget/manifests/s/SpecLabs/Devspec/0.2.0/SpecLabs.Devspec.locale.en-US.yaml new file mode 100644 index 0000000..abe187f --- /dev/null +++ b/packaging/winget/manifests/s/SpecLabs/Devspec/0.2.0/SpecLabs.Devspec.locale.en-US.yaml @@ -0,0 +1,21 @@ +# yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.12.0.schema.json +PackageIdentifier: SpecLabs.Devspec +PackageVersion: 0.2.0 +PackageLocale: en-US +Publisher: SpecLabs +PublisherUrl: https://github.com/speclabs +PublisherSupportUrl: https://github.com/speclabs/devspec/issues +PackageName: devspec +PackageUrl: https://github.com/speclabs/devspec +License: Apache-2.0 +LicenseUrl: https://github.com/speclabs/devspec/blob/main/LICENSE +ShortDescription: Installer and synchronizer CLI for the devspec workflow framework. +Description: devspec installs and synchronizes spec-driven development framework files for supported coding agents and IDE adapters. +Moniker: devspec +Tags: + - ai + - cli + - developer-tools + - spec-driven-development + - workflow +ManifestType: defaultLocale diff --git a/packaging/winget/manifests/s/SpecLabs/Devspec/0.2.0/SpecLabs.Devspec.yaml b/packaging/winget/manifests/s/SpecLabs/Devspec/0.2.0/SpecLabs.Devspec.yaml new file mode 100644 index 0000000..4919c80 --- /dev/null +++ b/packaging/winget/manifests/s/SpecLabs/Devspec/0.2.0/SpecLabs.Devspec.yaml @@ -0,0 +1,6 @@ +# yaml-language-server: $schema=https://aka.ms/winget-manifest.version.1.12.0.schema.json +PackageIdentifier: SpecLabs.Devspec +PackageVersion: 0.2.0 +DefaultLocale: en-US +ManifestType: version +ManifestVersion: 1.12.0 diff --git a/pyproject.toml b/pyproject.toml index 7d4c7ee..767977c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,10 @@ [build-system] -requires = ["hatchling>=1.26"] +requires = ["hatchling>=1.32.0"] build-backend = "hatchling.build" [project] name = "devspec" -version = "0.1.3" +version = "0.2.0" description = "Installer and synchronizer CLI for the devspec workflow framework." readme = "README.md" requires-python = ">=3.10" @@ -23,13 +23,14 @@ classifiers = [ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Topic :: Software Development", ] dependencies = [] [dependency-groups] dev = [ - "pytest>=8.0", + "pytest>=9.1.1", ] [project.scripts] diff --git a/src/devspec_installer/__init__.py b/src/devspec_installer/__init__.py index 89a852b..29bde5f 100644 --- a/src/devspec_installer/__init__.py +++ b/src/devspec_installer/__init__.py @@ -1,3 +1,3 @@ """Installer CLI for the devspec framework.""" -__version__ = "0.1.3" +__version__ = "0.2.0" diff --git a/tests/test_cli.py b/tests/test_cli.py index b727961..f8d20c4 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -2,6 +2,7 @@ import json import xml.etree.ElementTree as ET +import re from pathlib import Path, PurePosixPath from devspec_installer import __version__ @@ -17,6 +18,30 @@ ) +def test_release_metadata_is_consistent() -> None: + root = Path(__file__).parent.parent + project = (root / "pyproject.toml").read_text(encoding="utf-8") + version_match = re.search(r'^version = "([^"]+)"$', project, re.MULTILINE) + + assert version_match is not None + assert version_match.group(1) == __version__ + assert 'requires-python = ">=3.10"' in project + assert '"Programming Language :: Python :: 3.14"' in project + + for formula_path in (root / "packaging/homebrew/devspec.rb", root / "packaging/homebrew/tap/Formula/devspec.rb"): + formula = formula_path.read_text(encoding="utf-8") + assert f"/v{__version__}.tar.gz" in formula + assert f"REPLACE_WITH_V{__version__.replace('.', '_')}_RELEASE_SHA256" in formula + + manifest_directory = root / "packaging/winget/manifests/s/SpecLabs/Devspec" / __version__ + for manifest_path in manifest_directory.glob("*.yaml"): + assert f"PackageVersion: {__version__}" in manifest_path.read_text(encoding="utf-8") + assert (manifest_directory / "SpecLabs.Devspec.installer.yaml").is_file() + + homebrew_workflow = (root / ".github/workflows/homebrew-package-publish.yml").read_text(encoding="utf-8") + winget_workflow = (root / ".github/workflows/winget-package-publish.yml").read_text(encoding="utf-8") + + def test_profiles_resolve_core_and_all_payloads() -> None: payload = Payload() @@ -29,6 +54,8 @@ def test_profiles_resolve_core_and_all_payloads() -> None: assert "devspec/architecture/_template/diagram.html" in core_paths assert "devspec/architecture/_template/diagram.svg" not in core_paths assert "devspec/architecture/images/README.md" in core_paths + assert ".github/prompts/devspec.changerequest.prompt.md" in core_paths + assert ".github/agents/devspec.changerequest.agent.md" in core_paths assert "devspec/architecture/html/README.md" in core_paths assert ".github/prompts/devspec.story.prompt.md" in core_paths assert ".github/agents/devspec.story.agent.md" in core_paths @@ -41,6 +68,9 @@ def test_profiles_resolve_core_and_all_payloads() -> None: assert ".claude/skills/devspec-story/SKILL.md" in all_paths assert ".gemini/commands/devspec/story.toml" in all_paths assert ".agents/skills/devspec-story.md" in all_paths + assert ".claude/skills/devspec-changerequest/SKILL.md" in all_paths + assert ".gemini/commands/devspec/changerequest.toml" in all_paths + assert ".agents/skills/devspec-changerequest.md" in all_paths def test_payload_excludes_github_workflows_even_from_broad_patterns() -> None: diff --git a/uv.lock b/uv.lock index 8c91a96..cd6e73c 100644 --- a/uv.lock +++ b/uv.lock @@ -13,7 +13,7 @@ wheels = [ [[package]] name = "devspec" -version = "0.1.3" +version = "0.2.0" source = { editable = "." } [package.dev-dependencies] @@ -24,14 +24,14 @@ dev = [ [package.metadata] [package.metadata.requires-dev] -dev = [{ name = "pytest", specifier = ">=8.0" }] +dev = [{ name = "pytest", specifier = ">=9.1.1" }] [[package]] name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ @@ -49,11 +49,11 @@ wheels = [ [[package]] name = "packaging" -version = "26.2" +version = "26.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/fa/3944b40b07da9ce895c0e6303a5ab7d53da063554f534556b134a54d6093/packaging-26.3.tar.gz", hash = "sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79", size = 313412, upload-time = "2026-08-04T18:15:28.737Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" }, + { url = "https://files.pythonhosted.org/packages/63/34/ba1c580383c9eada3711951fef0795c80b829a078d72188184bcab9dd527/packaging-26.3-py3-none-any.whl", hash = "sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c", size = 129956, upload-time = "2026-08-04T18:15:27.159Z" }, ] [[package]] @@ -67,16 +67,16 @@ wheels = [ [[package]] name = "pygments" -version = "2.20.0" +version = "2.21.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } +sdist = { url = "https://files.pythonhosted.org/packages/49/2e/ced460408999b33da6b31b0021b0f37d329e202d4169aeb164493778f25b/pygments-2.21.0.tar.gz", hash = "sha256:610ca751c9bc2492b38eb9a38a7fbc93edbbb2d7182edaf34e66ae493dee5c8c", size = 5005329, upload-time = "2026-08-17T08:02:48.824Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, + { url = "https://files.pythonhosted.org/packages/71/46/17f022dd3e953bf20a04a028a21ec746d942f8d2af30fa0f124fa0e6a684/pygments-2.21.0-py3-none-any.whl", hash = "sha256:2363c69b61c4a97c838da3b130dcd6468f4848992b21a82f2a63ec34377137d9", size = 1250147, upload-time = "2026-08-17T08:02:44.912Z" }, ] [[package]] name = "pytest" -version = "9.0.3" +version = "9.1.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -87,9 +87,9 @@ dependencies = [ { name = "pygments" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c", size = 1572165, upload-time = "2026-04-07T17:16:18.027Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9", size = 375249, upload-time = "2026-04-07T17:16:16.13Z" }, + { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" }, ] [[package]] @@ -148,9 +148,9 @@ wheels = [ [[package]] name = "typing-extensions" -version = "4.15.0" +version = "4.16.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, + { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" }, ]