diff --git a/.github/workflows/community-smoke.yml b/.github/workflows/community-smoke.yml index 188fd6b63e..a11853fc1b 100644 --- a/.github/workflows/community-smoke.yml +++ b/.github/workflows/community-smoke.yml @@ -59,8 +59,8 @@ jobs: registry = json.loads(Path(".specify/presets/.registry").read_text(encoding="utf-8")) manifest_version = manifest["preset"]["version"] registry_version = registry["presets"]["workflow-preset"]["version"] - assert manifest_version == "1.3.4", manifest_version - assert registry_version == "1.3.4", registry_version + assert manifest_version == "1.3.5", manifest_version + assert registry_version == "1.3.5", registry_version assert registry_version == manifest_version PY test -f .specify/presets/workflow-preset/templates/behavior/behavior-scenarios-draft.json diff --git a/.gitignore b/.gitignore index 1688c8299e..a3c3a5d87c 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ venv/ ENV/ env/ .venv +.venv*/ # IDE .vscode/ diff --git a/presets/catalog.json b/presets/catalog.json index d9e6938143..5b0b24585b 100644 --- a/presets/catalog.json +++ b/presets/catalog.json @@ -29,7 +29,7 @@ "workflow-preset": { "name": "Workflow Preset", "id": "workflow-preset", - "version": "1.3.4", + "version": "1.3.5", "description": "Behavior-first specification, design artifacts, and agent-native handoff orchestration", "author": "bigsmartben", "repository": "https://github.com/bigsmartben/spec-kit-workflow-preset", diff --git a/presets/workflow-preset/README.md b/presets/workflow-preset/README.md index e4226b4ed5..83d8a701e4 100644 --- a/presets/workflow-preset/README.md +++ b/presets/workflow-preset/README.md @@ -33,6 +33,7 @@ Requirement capabilities: - Wraps `/speckit.specify` so it produces or updates `spec.md` only. - Wraps `/speckit.clarify` so it resolves requirement ambiguity in `spec.md` only. +- When a Figma Evidence Packet has already been written into `spec.md`, `/speckit.clarify` clarifies Figma-derived gaps already written in `spec.md` and does not call Figma. - Wraps `/speckit.checklist` to add `checklists/behavior-testability.md` as a BDD readiness gate and NFR readiness gate. - Checks user stories, acceptance criteria, Given/When/Then readiness, roles, permissions, states, data, validation, boundary, exception, state-conflict behavior, and non-functional requirements directly from `spec.md`. - Requires NFR dimensions to be marked Required, Not Applicable, or Unknown in product language before planning. @@ -123,7 +124,7 @@ Context-load controls: Release install: ```bash -specify preset add workflow-preset --from https://github.com/bigsmartben/spec-kit-workflow-preset/releases/download/v1.3.4/spec-kit-workflow-preset-v1.3.4.zip +specify preset add workflow-preset --from https://github.com/bigsmartben/spec-kit-workflow-preset/releases/download/v1.3.5/spec-kit-workflow-preset-v1.3.5.zip ``` Local development install: @@ -348,7 +349,7 @@ Release install smoke validation is intentionally owned by GitHub Actions, not b After tagging a release, validate archive installation: ```bash -specify preset add workflow-preset --from https://github.com/bigsmartben/spec-kit-workflow-preset/releases/download/v1.3.4/spec-kit-workflow-preset-v1.3.4.zip +specify preset add workflow-preset --from https://github.com/bigsmartben/spec-kit-workflow-preset/releases/download/v1.3.5/spec-kit-workflow-preset-v1.3.5.zip ``` ## Source Rationale diff --git a/presets/workflow-preset/commands/speckit.clarify.md b/presets/workflow-preset/commands/speckit.clarify.md index 4cdae34f65..9505245c51 100644 --- a/presets/workflow-preset/commands/speckit.clarify.md +++ b/presets/workflow-preset/commands/speckit.clarify.md @@ -9,6 +9,27 @@ Use `spec.md` as the clarification source. Ask and record clarification only for Do not read or update behavior draft artifacts. Do not use behavior drafts as clarification inputs, and do not open a separate behavior-question channel. Product requirements stay in `spec.md`; update `spec.md` only after user-provided answers make the requirement clear. +## Figma-Derived Clarification Strategy + +When `spec.md` was created from a Figma Evidence Packet, prioritize clarification questions for Figma-derived gaps already written in `spec.md`. Scan `spec.md` first for `Missing / Needs clarification`, `[NEEDS CLARIFICATION]`, `Inferred from structure`, and gaps about Figma-unprovided states, responsive behavior, business rules, permissions, and error handling. + +Do not call Figma MCP. Do not re-extract design facts, re-parse Figma links, or turn clarification into a Figma extraction step. `/speckit.specify` owns writing Figma evidence into `spec.md`; `/speckit.clarify` only selects high-impact questions from existing `spec.md` gaps and records confirmed answers. + +Ask at most 5 high-impact questions whose answers materially affect requirements, implementation planning, or validation readiness. Prefer questions in this order: + +1. Required frames, states, and breakpoints for acceptance. +2. visual fidelity scope: pixel-perfect, design-system faithful, or functional equivalent. +3. missing UI states such as loading, empty, error, disabled, hover, and focus. +4. responsive behavior, scrolling, safe areas, and long-copy handling. +5. component mapping from Figma components to existing code components. +6. data semantics for mock copy, API-backed copy, and interface-driven values. +7. Prototype-uncovered navigation, dialogs, recovery paths, and failure handling. +8. acceptance evidence, visual-difference tolerance, and exception approval flow. + +After the user answers, write confirmed answers back into `spec.md` in the relevant Requirements, User Scenarios, Acceptance Criteria, Assumptions, Open Questions, or visual/responsive/state sections. Do not create a separate Figma clarification document. + +Do not generate visual restoration checklists. Clarification fills requirement gaps in `spec.md`; `/speckit.checklist` remains responsible for checking requirement text quality and readiness. + {CORE_TEMPLATE} ## Clarification Reporting diff --git a/presets/workflow-preset/docs/extension-governance.md b/presets/workflow-preset/docs/extension-governance.md index ce018dd3c5..817479c9aa 100644 --- a/presets/workflow-preset/docs/extension-governance.md +++ b/presets/workflow-preset/docs/extension-governance.md @@ -44,6 +44,10 @@ Stage ownership: - `/speckit.analyze`: vertical consistency checks across requirements, behavior drafts, contracts, and tasks only. - `/speckit.implement`: implementation handoff execution only. +When a Figma Evidence Packet has already been written into `spec.md`, +`/speckit.clarify` may clarify those requirement gaps from `spec.md`, but +external design extraction is not a clarification responsibility. + ## Structured Artifact Rules Machine-readable JSON artifacts are contracts, not prose examples. Stable diff --git a/presets/workflow-preset/preset.yml b/presets/workflow-preset/preset.yml index 560692a088..386e763f67 100644 --- a/presets/workflow-preset/preset.yml +++ b/presets/workflow-preset/preset.yml @@ -1,232 +1,201 @@ -schema_version: "1.0" - +schema_version: '1.0' preset: - id: "workflow-preset" - name: "Workflow Preset" - version: "1.3.4" - description: "Behavior-first specification, design artifacts, and agent-native handoff orchestration" - author: "bigsmartben" - repository: "https://github.com/bigsmartben/spec-kit-workflow-preset" - license: "MIT" - + id: workflow-preset + name: Workflow Preset + version: 1.3.5 + description: Behavior-first specification, design artifacts, and agent-native handoff + orchestration + author: bigsmartben + repository: https://github.com/bigsmartben/spec-kit-workflow-preset + license: MIT requires: - speckit_version: ">=0.8.10.dev0" - + speckit_version: '>=0.8.10.dev0' provides: templates: - - type: "template" - name: "plan-template" - file: "templates/plan-template.md" - description: "Add design artifact navigation to the plan template" - replaces: "plan-template" - strategy: "wrap" - - - type: "template" - name: "constitution-template" - file: "templates/constitution-template.md" - description: "Add change scope granularity governance to the constitution template" - replaces: "constitution-template" - strategy: "wrap" - - - type: "command" - name: "speckit.specify" - file: "commands/speckit.specify.md" - description: "Wrap core specification with spec-only requirement ownership" - replaces: "speckit.specify" - strategy: "wrap" - - - type: "command" - name: "speckit.clarify" - file: "commands/speckit.clarify.md" - description: "Wrap core clarification with spec-only ambiguity resolution" - replaces: "speckit.clarify" - strategy: "wrap" - - - type: "command" - name: "speckit.checklist" - file: "commands/speckit.checklist.md" - description: "Wrap core checklist generation with BDD and NFR readiness gate" - replaces: "speckit.checklist" - strategy: "wrap" - - - type: "command" - name: "speckit.constitution" - file: "commands/speckit.constitution.md" - description: "Wrap core constitution updates with change scope granularity governance" - replaces: "speckit.constitution" - strategy: "wrap" - - - type: "command" - name: "speckit.analyze" - file: "commands/speckit.analyze.md" - description: "Wrap core analysis with behavior-first vertical consistency checks" - replaces: "speckit.analyze" - strategy: "wrap" - - - type: "command" - name: "speckit.plan" - file: "commands/speckit.plan.md" - description: "Wrap core planning with Phase 0 behavior projection and optional design artifacts" - replaces: "speckit.plan" - strategy: "wrap" - - - type: "command" - name: "speckit.tasks" - file: "commands/speckit.tasks.md" - description: "Wrap task generation with optional design artifact awareness" - replaces: "speckit.tasks" - strategy: "wrap" - - - type: "command" - name: "speckit.implement" - file: "commands/speckit.implement.md" - description: "Run agent-native handoff orchestration or execute one worker handoff" - replaces: "speckit.implement" - strategy: "replace" - - - type: "template" - name: "behavior-bdd-draft-template" - file: "templates/behavior/bdd-draft.feature" - description: "Template for Phase 0 BDD drafts" - replaces: "behavior-bdd-draft-template" - strategy: "replace" - - - type: "template" - name: "behavior-scenarios-draft-template" - file: "templates/behavior/behavior-scenarios-draft.json" - description: "Template for structured behavior scenario drafts" - replaces: "behavior-scenarios-draft-template" - strategy: "replace" - - - type: "template" - name: "behavior-uif-intent-template" - file: "templates/behavior/uif-intent.json" - description: "Template for Phase 0 UIF intent" - replaces: "behavior-uif-intent-template" - strategy: "replace" - - - type: "template" - name: "behavior-data-fixtures-intent-template" - file: "templates/behavior/data-fixtures-intent.json" - description: "Template for Phase 0 data fixture intent" - replaces: "behavior-data-fixtures-intent-template" - strategy: "replace" - - - type: "template" - name: "behavior-testability-checklist-template" - file: "templates/behavior/behavior-testability-checklist.md" - description: "Template for BDD and NFR readiness gate output" - replaces: "behavior-testability-checklist-template" - strategy: "replace" - - - type: "template" - name: "behavior-bdd-contract-template" - file: "templates/behavior/bdd-contract.feature" - description: "Template for formal BDD contracts" - replaces: "behavior-bdd-contract-template" - strategy: "replace" - - - type: "template" - name: "behavior-uif-expected-template" - file: "templates/behavior/uif-expected.json" - description: "Template for Expected UIF contracts" - replaces: "behavior-uif-expected-template" - strategy: "replace" - - - type: "template" - name: "behavior-scenario-instances-template" - file: "templates/behavior/scenario-instances.json" - description: "Template for formal behavior scenario instances" - replaces: "behavior-scenario-instances-template" - strategy: "replace" - - - type: "template" - name: "behavior-data-fixtures-template" - file: "templates/behavior/data-fixtures.json" - description: "Template for formal behavior data fixtures" - replaces: "behavior-data-fixtures-template" - strategy: "replace" - - - type: "template" - name: "behavior-assertions-template" - file: "templates/behavior/assertions.json" - description: "Template for formal behavior assertions" - replaces: "behavior-assertions-template" - strategy: "replace" - - - type: "template" - name: "speckit-behavior-scenarios-draft-v1-schema" - file: "schemas/speckit.behavior.scenarios.draft.v1.schema.json" - description: "Schema for structured behavior scenario drafts" - replaces: "speckit-behavior-scenarios-draft-v1-schema" - strategy: "replace" - - - type: "template" - name: "speckit-behavior-uif-intent-v1-schema" - file: "schemas/speckit.behavior.uif.intent.v1.schema.json" - description: "Schema for Phase 0 UIF intent" - replaces: "speckit-behavior-uif-intent-v1-schema" - strategy: "replace" - - - type: "template" - name: "speckit-behavior-data-fixtures-intent-v1-schema" - file: "schemas/speckit.behavior.data-fixtures.intent.v1.schema.json" - description: "Schema for data fixture intent" - replaces: "speckit-behavior-data-fixtures-intent-v1-schema" - strategy: "replace" - - - type: "template" - name: "speckit-behavior-uif-expected-v1-schema" - file: "schemas/speckit.behavior.uif.expected.v1.schema.json" - description: "Schema for Expected UIF contracts" - replaces: "speckit-behavior-uif-expected-v1-schema" - strategy: "replace" - - - type: "template" - name: "speckit-behavior-scenario-instances-v1-schema" - file: "schemas/speckit.behavior.scenario-instances.v1.schema.json" - description: "Schema for formal behavior scenario instances" - replaces: "speckit-behavior-scenario-instances-v1-schema" - strategy: "replace" - - - type: "template" - name: "speckit-behavior-data-fixtures-v1-schema" - file: "schemas/speckit.behavior.data-fixtures.v1.schema.json" - description: "Schema for formal behavior data fixtures" - replaces: "speckit-behavior-data-fixtures-v1-schema" - strategy: "replace" - - - type: "template" - name: "speckit-behavior-assertions-v1-schema" - file: "schemas/speckit.behavior.assertions.v1.schema.json" - description: "Schema for formal behavior assertions" - replaces: "speckit-behavior-assertions-v1-schema" - strategy: "replace" - - - type: "template" - name: "speckit-implement-manifest-v1-schema" - file: "schemas/speckit.implement.manifest.v1.schema.json" - description: "Decouple the handoff manifest JSON contract" - replaces: "speckit-implement-manifest-v1-schema" - strategy: "replace" - - - type: "template" - name: "speckit-implement-handoff-v2-schema" - file: "schemas/speckit.implement.handoff.v2.schema.json" - description: "Decouple the handoff JSON contract" - replaces: "speckit-implement-handoff-v2-schema" - strategy: "replace" - - - type: "template" - name: "speckit-implement-receipt-v1-schema" - file: "schemas/speckit.implement.receipt.v1.schema.json" - description: "Decouple the receipt JSON contract" - replaces: "speckit-implement-receipt-v1-schema" - strategy: "replace" - + - type: template + name: plan-template + file: templates/plan-template.md + description: Add design artifact navigation to the plan template + replaces: plan-template + strategy: wrap + - type: template + name: constitution-template + file: templates/constitution-template.md + description: Add change scope granularity governance to the constitution template + replaces: constitution-template + strategy: wrap + - type: command + name: speckit.specify + file: commands/speckit.specify.md + description: Wrap core specification with spec-only requirement ownership + replaces: speckit.specify + strategy: wrap + - type: command + name: speckit.clarify + file: commands/speckit.clarify.md + description: Wrap core clarification with spec-only ambiguity resolution + replaces: speckit.clarify + strategy: wrap + - type: command + name: speckit.checklist + file: commands/speckit.checklist.md + description: Wrap core checklist generation with BDD and NFR readiness gate + replaces: speckit.checklist + strategy: wrap + - type: command + name: speckit.constitution + file: commands/speckit.constitution.md + description: Wrap core constitution updates with change scope granularity governance + replaces: speckit.constitution + strategy: wrap + - type: command + name: speckit.analyze + file: commands/speckit.analyze.md + description: Wrap core analysis with behavior-first vertical consistency checks + replaces: speckit.analyze + strategy: wrap + - type: command + name: speckit.plan + file: commands/speckit.plan.md + description: Wrap core planning with Phase 0 behavior projection and optional + design artifacts + replaces: speckit.plan + strategy: wrap + - type: command + name: speckit.tasks + file: commands/speckit.tasks.md + description: Wrap task generation with optional design artifact awareness + replaces: speckit.tasks + strategy: wrap + - type: command + name: speckit.implement + file: commands/speckit.implement.md + description: Run agent-native handoff orchestration or execute one worker handoff + replaces: speckit.implement + strategy: replace + - type: template + name: behavior-bdd-draft-template + file: templates/behavior/bdd-draft.feature + description: Template for Phase 0 BDD drafts + replaces: behavior-bdd-draft-template + strategy: replace + - type: template + name: behavior-scenarios-draft-template + file: templates/behavior/behavior-scenarios-draft.json + description: Template for structured behavior scenario drafts + replaces: behavior-scenarios-draft-template + strategy: replace + - type: template + name: behavior-uif-intent-template + file: templates/behavior/uif-intent.json + description: Template for Phase 0 UIF intent + replaces: behavior-uif-intent-template + strategy: replace + - type: template + name: behavior-data-fixtures-intent-template + file: templates/behavior/data-fixtures-intent.json + description: Template for Phase 0 data fixture intent + replaces: behavior-data-fixtures-intent-template + strategy: replace + - type: template + name: behavior-testability-checklist-template + file: templates/behavior/behavior-testability-checklist.md + description: Template for BDD and NFR readiness gate output + replaces: behavior-testability-checklist-template + strategy: replace + - type: template + name: behavior-bdd-contract-template + file: templates/behavior/bdd-contract.feature + description: Template for formal BDD contracts + replaces: behavior-bdd-contract-template + strategy: replace + - type: template + name: behavior-uif-expected-template + file: templates/behavior/uif-expected.json + description: Template for Expected UIF contracts + replaces: behavior-uif-expected-template + strategy: replace + - type: template + name: behavior-scenario-instances-template + file: templates/behavior/scenario-instances.json + description: Template for formal behavior scenario instances + replaces: behavior-scenario-instances-template + strategy: replace + - type: template + name: behavior-data-fixtures-template + file: templates/behavior/data-fixtures.json + description: Template for formal behavior data fixtures + replaces: behavior-data-fixtures-template + strategy: replace + - type: template + name: behavior-assertions-template + file: templates/behavior/assertions.json + description: Template for formal behavior assertions + replaces: behavior-assertions-template + strategy: replace + - type: template + name: speckit-behavior-scenarios-draft-v1-schema + file: schemas/speckit.behavior.scenarios.draft.v1.schema.json + description: Schema for structured behavior scenario drafts + replaces: speckit-behavior-scenarios-draft-v1-schema + strategy: replace + - type: template + name: speckit-behavior-uif-intent-v1-schema + file: schemas/speckit.behavior.uif.intent.v1.schema.json + description: Schema for Phase 0 UIF intent + replaces: speckit-behavior-uif-intent-v1-schema + strategy: replace + - type: template + name: speckit-behavior-data-fixtures-intent-v1-schema + file: schemas/speckit.behavior.data-fixtures.intent.v1.schema.json + description: Schema for data fixture intent + replaces: speckit-behavior-data-fixtures-intent-v1-schema + strategy: replace + - type: template + name: speckit-behavior-uif-expected-v1-schema + file: schemas/speckit.behavior.uif.expected.v1.schema.json + description: Schema for Expected UIF contracts + replaces: speckit-behavior-uif-expected-v1-schema + strategy: replace + - type: template + name: speckit-behavior-scenario-instances-v1-schema + file: schemas/speckit.behavior.scenario-instances.v1.schema.json + description: Schema for formal behavior scenario instances + replaces: speckit-behavior-scenario-instances-v1-schema + strategy: replace + - type: template + name: speckit-behavior-data-fixtures-v1-schema + file: schemas/speckit.behavior.data-fixtures.v1.schema.json + description: Schema for formal behavior data fixtures + replaces: speckit-behavior-data-fixtures-v1-schema + strategy: replace + - type: template + name: speckit-behavior-assertions-v1-schema + file: schemas/speckit.behavior.assertions.v1.schema.json + description: Schema for formal behavior assertions + replaces: speckit-behavior-assertions-v1-schema + strategy: replace + - type: template + name: speckit-implement-manifest-v1-schema + file: schemas/speckit.implement.manifest.v1.schema.json + description: Decouple the handoff manifest JSON contract + replaces: speckit-implement-manifest-v1-schema + strategy: replace + - type: template + name: speckit-implement-handoff-v2-schema + file: schemas/speckit.implement.handoff.v2.schema.json + description: Decouple the handoff JSON contract + replaces: speckit-implement-handoff-v2-schema + strategy: replace + - type: template + name: speckit-implement-receipt-v1-schema + file: schemas/speckit.implement.receipt.v1.schema.json + description: Decouple the receipt JSON contract + replaces: speckit-implement-receipt-v1-schema + strategy: replace tags: - - "behavior" - - "bdd" - - "planning" - - "implementation" - - "handoff" +- behavior +- bdd +- planning +- implementation +- handoff diff --git a/presets/workflow-preset/tests/test_preset_contract.py b/presets/workflow-preset/tests/test_preset_contract.py index 15b7748850..98d57e8019 100644 --- a/presets/workflow-preset/tests/test_preset_contract.py +++ b/presets/workflow-preset/tests/test_preset_contract.py @@ -401,7 +401,7 @@ def test_preset_manifest_contract(self) -> None: self.assertEqual("1.0", data["schema_version"]) self.assertEqual("workflow-preset", data["preset"]["id"]) self.assertEqual("Workflow Preset", data["preset"]["name"]) - self.assertEqual("1.3.4", data["preset"]["version"]) + self.assertEqual("1.3.5", data["preset"]["version"]) self.assertEqual( "Behavior-first specification, design artifacts, and agent-native handoff orchestration", data["preset"]["description"], @@ -511,7 +511,7 @@ def test_preset_manifest_contract(self) -> None: template = entries[template_name] self.assertEqual("template", template["type"]) self.assertEqual( - str(template_path.relative_to(REPO_ROOT)), + template_path.relative_to(REPO_ROOT).as_posix(), template["file"], ) self.assertEqual(template_name, template["replaces"]) @@ -521,7 +521,7 @@ def test_preset_manifest_contract(self) -> None: schema_name = f"{contract_type}-schema".replace(".", "-").replace("_", "-") schema = entries[schema_name] self.assertEqual("template", schema["type"]) - self.assertEqual(str(schema_path.relative_to(REPO_ROOT)), schema["file"]) + self.assertEqual(schema_path.relative_to(REPO_ROOT).as_posix(), schema["file"]) self.assertEqual(schema_name, schema["replaces"]) self.assertEqual("replace", schema["strategy"]) @@ -689,12 +689,32 @@ def test_behavior_first_command_wrapper_contracts(self) -> None: self.assertIn("Product requirements stay in `spec.md`", clarify) self.assertIn("non-functional requirement assumptions", clarify) self.assertIn("only after user-provided answers", clarify) + self.assertIn("Figma Evidence Packet", clarify) + self.assertIn("Missing / Needs clarification", clarify) + self.assertIn("[NEEDS CLARIFICATION]", clarify) + self.assertIn("Inferred from structure", clarify) + self.assertIn("Do not call Figma MCP", clarify) + self.assertIn("Do not re-extract design facts", clarify) + self.assertIn("Ask at most 5 high-impact questions", clarify) + self.assertIn("visual fidelity scope", clarify) + self.assertIn("missing UI states", clarify) + self.assertIn("responsive behavior", clarify) + self.assertIn("component mapping", clarify) + self.assertIn("data semantics", clarify) + self.assertIn("acceptance evidence", clarify) + self.assertIn("write confirmed answers back into `spec.md`", clarify) + self.assertIn("Do not generate visual restoration checklists", clarify) for forbidden in ( "behavior/bdd.draft.feature", "behavior/behavior-scenarios.draft.json", "behavior/uif.intent.json", "behavior/data-fixtures.intent.json", "behavior/open-questions.json", + "use_figma", + "get_design_context", + "fetch Figma URL", + "read Figma URL", + "update checklists/behavior-testability.md", ): self.assertNotIn(forbidden, clarify) @@ -1103,6 +1123,7 @@ def test_contract_schemas_are_decoupled_json_files(self) -> None: self.assertIn("checked_sources", review_conclusion["required"]) data_side_effect_review = receipt["properties"]["data_side_effect_review"] self.assertIn("reviewed_diff_paths", data_side_effect_review["required"]) + self.assertIn("runtime_data_writes_found", data_side_effect_review["required"]) self.assertIn("mutation_findings", data_side_effect_review["required"]) def test_manifest_schema_declares_runtime_neutral_execution_mode(self) -> None: @@ -1919,6 +1940,43 @@ def test_validate_receipt_contract_requires_mutation_findings_for_code_review_ta RECEIPT_PATH, ) + def test_validate_receipt_contract_rejects_malformed_data_side_effect_finding( + self, + ) -> None: + handoff = minimal_handoff(task_ids=["T099"], task_type="code_review") + handoff["allowed_read_paths"] = [TASKS_PATH, SERVICE_PATH] + + with self.assertRaisesRegex(ValueError, "mutation_findings\\[0\\] must include id"): + validate_receipt_contract( + handoff, + minimal_receipt( + task_ids=["T099"], + task_type="code_review", + review_conclusion={ + "status": "approved", + "summary": "Review complete.", + "checked_sources": [SERVICE_PATH], + "findings": [], + }, + data_side_effect_review={ + "reviewed_diff_paths": [SERVICE_PATH], + "runtime_data_writes_found": True, + "mutation_findings": [ + { + "severity": "low", + "category": "field_level_update", + "summary": "Missing id should fail validation.", + "operation": "update", + "tables_or_entities": ["orders"], + "fields": ["status"], + "resolution": "accepted", + } + ], + }, + ), + RECEIPT_PATH, + ) + def test_validate_receipt_contract_rejects_approved_with_unresolved_high_data_side_effect( self, ) -> None: @@ -1958,57 +2016,6 @@ def test_validate_receipt_contract_rejects_approved_with_unresolved_high_data_si RECEIPT_PATH, ) - def test_validate_receipt_contract_requires_data_side_effect_finding_fields( - self, - ) -> None: - handoff = minimal_handoff(task_ids=["T099"], task_type="code_review") - handoff["allowed_read_paths"] = [TASKS_PATH, SERVICE_PATH] - required_fields = [ - "id", - "severity", - "category", - "summary", - "operation", - "tables_or_entities", - "fields", - "resolution", - ] - finding = { - "id": "DSE-001", - "severity": "low", - "category": "field_level_update", - "summary": "Order status update affects fulfillment flow.", - "operation": "update", - "tables_or_entities": ["orders"], - "fields": ["status"], - "resolution": "accepted", - } - - for missing_field in required_fields: - invalid_finding = dict(finding) - invalid_finding.pop(missing_field) - with self.subTest(missing_field=missing_field): - with self.assertRaisesRegex(ValueError, missing_field): - validate_receipt_contract( - handoff, - minimal_receipt( - task_ids=["T099"], - task_type="code_review", - review_conclusion={ - "status": "approved", - "summary": "Review complete.", - "checked_sources": [SERVICE_PATH], - "findings": [], - }, - data_side_effect_review={ - "reviewed_diff_paths": [SERVICE_PATH], - "runtime_data_writes_found": True, - "mutation_findings": [invalid_finding], - }, - ), - RECEIPT_PATH, - ) - def test_validate_receipt_contract_rejects_checked_source_outside_allowed_reads( self, ) -> None: @@ -2384,6 +2391,9 @@ def test_readme_contract(self) -> None: self.assertIn("The preset has four goals:", readme) self.assertIn("BDD readiness gate", readme) self.assertIn("NFR readiness", readme) + self.assertIn("Figma Evidence Packet", readme) + self.assertIn("clarifies Figma-derived gaps already written in `spec.md`", readme) + self.assertIn("does not call Figma", readme) self.assertIn("explicit non-functional requirement declarations", readme) self.assertIn("Required, Not Applicable, or Unknown", readme) self.assertIn("missing or unverifiable NFR assumptions", readme) @@ -2520,6 +2530,8 @@ def test_extension_governance_document_contract(self) -> None: "BDD and UIF artifacts need independent templates", "`/speckit.constitution`: constitution governance and project principles only", "`/speckit.checklist`: checklist artifacts and BDD/NFR readiness gates only", + "Figma Evidence Packet", + "external design extraction is not a clarification responsibility", "NFR readiness belongs in `spec.md` product requirements", "`/speckit.plan`: Phase 0 behavior projection, planning artifacts, and formal contracts", "Handoff extensions must update schema, validator, command, and cross-agent documentation together", diff --git a/tests/integrations/test_cli.py b/tests/integrations/test_cli.py index 9257cd4022..cc9392c542 100644 --- a/tests/integrations/test_cli.py +++ b/tests/integrations/test_cli.py @@ -992,8 +992,8 @@ def test_workflow_preset_registers_commands_and_composes_wrappers(self, tmp_path preset_registry = json.loads((project / ".specify" / "presets" / ".registry").read_text()) workflow_entry = preset_registry["presets"]["workflow-preset"] installed_manifest = yaml.safe_load((preset_dir / "preset.yml").read_text(encoding="utf-8")) - assert installed_manifest["preset"]["version"] == "1.3.4" - assert workflow_entry["version"] == "1.3.4" + assert installed_manifest["preset"]["version"] == "1.3.5" + assert workflow_entry["version"] == "1.3.5" assert workflow_entry["version"] == installed_manifest["preset"]["version"] expected_preset_commands = { "speckit.specify", diff --git a/tests/test_presets.py b/tests/test_presets.py index d947324383..3898f992af 100644 --- a/tests/test_presets.py +++ b/tests/test_presets.py @@ -3490,7 +3490,7 @@ def test_workflow_preset_catalog_matches_manifest(self): template_count = sum(1 for item in provided if item["type"] == "template") assert entry["bundled"] is True - assert entry["version"] == "1.3.4" + assert entry["version"] == "1.3.5" assert entry["version"] == manifest["preset"]["version"] assert entry["repository"] == manifest["preset"]["repository"] assert entry["requires"]["speckit_version"] == manifest["requires"]["speckit_version"] @@ -3558,8 +3558,8 @@ def test_community_smoke_checks_wheel_assets_and_extension_dev_reinstall(self): assert ( 'registry = json.loads(Path(".specify/presets/.registry").read_text(encoding="utf-8"))' ) in verify_run - assert 'manifest_version == "1.3.4"' in verify_run - assert 'registry_version == "1.3.4"' in verify_run + assert 'manifest_version == "1.3.5"' in verify_run + assert 'registry_version == "1.3.5"' in verify_run assert "registry_version == manifest_version" in verify_run assert ( 'for extension_id in arch preview repository-governance; do'