Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions .extensionignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# .extensionignore — files and directories NOT to vendor when this
# extension is installed via `specify extension add v-model`.
#
# Pattern syntax: gitignore-compatible (per upstream spec-kit's
# _load_extensionignore). This reduces install footprint from the full
# repo (~700 files at v0.7.1) to runtime essentials — commands, scripts,
# templates, and extension metadata.

# === Version control ===
.git/
.gitignore
.gitmodules

# === Spec-Kit dogfooding state (recursive-vendor hazard) ===
# This repo dogfoods the extension on itself, which means
# .specify/extensions/v-model/ already contains a vendored copy of the
# extension. Including .specify/ in the install would recursively vendor
# the extension into itself on every refresh.
.specify/

# === GitHub workflows + dogfood agent files ===
# These belong to THIS repo's CI/dogfood state, not to consumers.
.github/

# === Development sources not needed at install time ===
tests/ # Unit / integration / system test suites for the extension itself
specs/ # Historical feature specifications (development artifacts)
docs/ # User-facing documentation (rendered to the project's website)
site/ # MkDocs build output (generated from docs/)
media/ # Project images
presentations/ # Talks / decks (not extension content)
refactoring_plan/ # Transient stabilization roadmap (cycle-local)

# === Build / tooling artifacts ===
.editorconfig
.pytest_cache/
.deepeval/
__pycache__/
*.pyc
*.pyo
.coverage
htmlcov/
*.egg-info/
dist/
build/
node_modules/

# === IDE / OS cruft ===
.vscode/
.idea/
*.swp
*.swo
*~
.DS_Store
Thumbs.db

# === Local environment files (defensive; already in .gitignore) ===
.env
.env.local
.env.example

# === Project-internal files not for end users ===
testResults.xml
conftest.py # Root pytest conftest, not extension code
requirements-dev.txt # Development-only Python dependencies
AGENTS.md # Contributor operating manual (read on GitHub)

# === This file itself ===
.extensionignore
106 changes: 103 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,107 @@ When introducing a new command, an agent MUST:

---

## 11. Cleanup is welcome; sprawl needs approval
## 11. Handoff graph

Every `commands/*.md` declares zero or more handoffs in its YAML
frontmatter. A handoff names a **target command**, a one-line **reason**
(the `prompt:` field), and whether it **auto-dispatches** (`send: true`)
or is offered to the user as a button (`send: false` or omitted). This
section documents the resulting graph so contributors can reason about
workflow ergonomics without re-reading 17 frontmatter blocks. Every
handoff has all four fields; reasons live in the source files.

### Forward V-Model lifecycle (`send: true`)

Each design-side command auto-dispatches to its paired test-side
command; each test-side command auto-dispatches to `trace`:

| Level | Design → Test | Test → Trace |
|---|---|---|
| L1 — Acceptance | `requirements` → `acceptance` | `acceptance` → `trace` |
| L2 — System | `system-design` → `system-test` | `system-test` → `trace` |
| L3 — Architecture | `architecture-design` → `integration-test` | `integration-test` → `trace` |
| L4 — Module | `module-design` → `unit-test` | `unit-test` → `trace` |

`trace` is the convergence point — every test-side level and most
cross-cutting commands route through it.

### Cross-cutting and reporting

| Source | Forward (`send: true`) | Backward (user button) |
|---|---|---|
| `hazard-analysis` | `trace` | `system-design` |
| `impact-analysis` | `trace` | `peer-review` |
| `peer-review` | `trace` | `peer-review` (self-loop — see Cycles) |
| `test-results` | `trace` | `impact-analysis` |
| `audit-report` | `trace` + `test-results` (both `send: true`) | (none) |

### Bridge commands (v0.7.x reconciliation flow)

| Source | Forward (`send: true`) | Backward (user button) |
|---|---|---|
| `plan` (OPTIONAL) | `tasks` | (none) |
| `tasks` (OPTIONAL) | `implement` | `plan` (Re-Plan) |
| `implement` (CORE) | `trace` | `tasks` (Re-Tasks) |

### Backward / refinement handoffs (user buttons)

Every design-side and test-side command offers a backward handoff to
its parent so users can iterate without re-typing slash commands:

- `acceptance` → `requirements` (Back to Requirements)
- `system-design` → `requirements` (Back to Requirements)
- `system-test` → `system-design` (Back to System Design)
- `architecture-design` → `system-design` (Back to System Design)
- `integration-test` → `architecture-design` (Back to Architecture Design)
- `module-design` → `architecture-design` (Back to Architecture Design)
- `unit-test` → `module-design` (Back to Module Design)
- `requirements` → `specify` (Back to Specify — into spec-kit core)
- `trace` → `requirements` (Update Requirements)

### Intentional cycles

Three cycles exist in the graph; **all three are intentional**:

1. **`peer-review` → `peer-review` (self-loop, user button).** "Review
Another Artifact" lets a user run consecutive peer-review passes on
different artefacts without re-typing the slash command.
2. **`trace` ↔ `acceptance` (gap-fix loop, auto-dispatch).** When
`trace` detects coverage gaps, its forward dispatches `acceptance`
("Fix Coverage Gaps"). `acceptance` then dispatches back to `trace`.
The loop terminates when coverage closes.
3. **`plan` ↔ `tasks` ↔ `implement` (bridge refinement, user buttons).**
Each consecutive bridge offers a backward "Re-X" button to the
previous one. If `implement` surfaces new modules/hazards, it
suggests re-running `tasks`; if `tasks` finds the upstream plan
missing context, it suggests re-running `plan`. Refinement is
user-initiated to prevent runaway loops.

Adding any new cycle requires documenting it here with its termination
condition.

### Removed handoffs (do not re-introduce)

- **`plan` → `implement` (direct):** removed in v0.7.0 per MF-10. The
V-Model lifecycle is `plan` → `tasks` → `implement`; jumping
`plan` → `implement` skips the TDD-ordered task decomposition the
rest of the system expects. The rationale is preserved as a comment
in `commands/plan.md`'s frontmatter.

### Invariants enforced by this graph

- Every auto-dispatched (`send: true`) forward chain converges
eventually on `trace` — no auto-dispatch terminates before
traceability is validated.
- Every backward handoff is a user button (never `send: true`) —
auto-dispatching backward would create unintended infinite loops.
- All four handoff fields (`label`, `agent`, `prompt`, `send`) MUST
be present in every handoff entry; the `prompt:` field is the
one-line reason a contributor or audit reader can consult.

---

## 12. Cleanup is welcome; sprawl needs approval

The project periodically enters **stabilization cycles** to pay down
the kind of debt that accumulates when features ship faster than the
Expand Down Expand Up @@ -341,7 +441,7 @@ absence does not relax the rule above.

---

## 12. Common pitfalls
## 13. Common pitfalls

Drawn from the v0.7.0 audit. An agent that finds itself about to do one
of these things should stop and ask.
Expand Down Expand Up @@ -372,7 +472,7 @@ of these things should stop and ask.

---

## 13. When in doubt
## 14. When in doubt

1. Re-read [`.specify/memory/constitution.md`](.specify/memory/constitution.md).
2. Re-read [`docs/product-vision.md`](docs/product-vision.md) for *why*.
Expand Down
32 changes: 32 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,38 @@ All notable changes to the V-Model Extension Pack are documented here.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.7.2] — Extension Packaging Hygiene & Handoff Documentation — 2026-05-17

> **Release theme**: address two drift hazards surfaced during the v0.7.1 release and subsequent dogfood-refresh investigation — (1) the README's hardcoded install-URL drift, (2) the `specify extension add` install vendoring the entire repo because no `.extensionignore` existed — plus two Epic 3 stabilization tasks land: handoff-graph documentation and template-overlay mismatch cleanup. No new commands. No new features. No new functionality.

### Fixed

- **README install URL drift.** The Quick Start snippet in `README.md` hardcoded `v0.7.0.zip`, so end users following the README after v0.7.1 were still installing v0.7.0. Updated to `v0.7.1.zip` mid-cycle (during this release's preparation) and to `v0.7.2.zip` as part of the v0.7.2 ceremony. Going forward, the release ceremony bumps this URL alongside `pyproject.toml` / `extension.yml` / `catalog-entry.json`.

### Changed — Extension packaging hygiene

- **New `.extensionignore` at repo root.** Tells `specify extension add` to skip development sources (`tests/`, `specs/`, `docs/`, `site/`, `.specify/`, `.github/`, `examples/`, `media/`, `presentations/`, `refactoring_plan/`, plus build/IDE/OS cruft) when vendoring the extension into a user's project. Without this file, an install via the GitHub archive zip vendored the entire repo (~700 files at v0.7.1), including the recursive-vendor hazard `.specify/extensions/v-model/.specify/...`. With this file, the install footprint drops to ~165 files — commands, scripts, templates, and extension metadata. Takes effect when consumers use a `specify-cli` recent enough to honour `.extensionignore`.

### Changed — Epic 3 stabilization

- **Handoff graph documented (Epic 3 Task 5).** New `AGENTS.md` §11 inventories every handoff declared in `commands/*.md` frontmatter: the forward V-Model lifecycle (L1–L4 design→test→trace), cross-cutting handoffs (hazard-analysis, impact-analysis, peer-review, test-results, audit-report), bridge handoffs (plan→tasks→implement), and the nine backward "Back to X" user buttons. Documents the **three intentional cycles** (peer-review self-loop; trace↔acceptance gap-fix loop; plan↔tasks↔implement bridge refinement) with their termination conditions. Documents the **one historically-removed handoff** (`plan` → `implement` direct, removed in v0.7.0 per MF-10) so it doesn't get re-introduced. States the invariants the graph enforces (every auto-dispatch converges on `trace`; backward handoffs are user-button only; every handoff has all four fields). Renumbers existing §11/§12/§13 → §12/§13/§14.

- **Template overlay mismatch resolved (Epic 3 Task 7).** `commands/requirements.md` and `commands/acceptance.md` instructed the LLM to read domain-specific template overlays (`templates/overlays/{domain}/*-template.md`), but those files never existed — only empty `.gitkeep` placeholders in the three domain directories. Per the audit's Definition of Done ("either implement OR remove the instructions"), the instructions are removed. The empty directories are kept as placeholders for future intent. The `commands/overlays/{domain}/<command>.md` mechanism (which IS populated and DOES work) is unchanged.

### Test infrastructure

- `tests/structural/test_extension_yml.py::test_no_spec_kit_core_file_modified_outside_extension_yml` allow-list now permits `.extensionignore` at the repo root.

### Deferred to a later v0.7.x or v0.8.0

- **Epic 3 Tasks 2, 3, 4** (extract shared prompt policies; reduce each command to single responsibility; refactor bridge prompts especially `implement`). The audit's Definition of Done for these tasks presupposes either a build-time generator or an install-time include mechanism — tooling we don't have. Lightweight versions (standardize-and-CI-test rather than extract-and-include) were considered but defer the bigger architectural decision (build the tooling, redesign the prompts, or adapt the DoDs) to a later release.

### Known Limitations

(unchanged from v0.7.1 — see [0.7.1] entry below for the two LLM-eval variance flakes and the PowerShell mirror gap for `update-agent-context.sh`.)

---

## [0.7.1] — Bridge Command Reconciliation & Governance — 2026-05-17

> **Release theme**: reconcile the v0.7.0 bridge commands with their user-facing intent — that `/speckit.v-model.implement` produces *a fully working and validated implementation* from the V-Model artefact set — and adopt a real contributor operating manual + an additive constitution amendment that codifies the discipline the v0.7.0 design did not yet capture. No new commands, no new features, no new functionality. Surgical reconciliation.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ AI-native teams ship fast but produce no traceability. Regulated teams have full
```bash
# Install the extension
specify extension add v-model \
--from https://github.com/leocamello/spec-kit-v-model/archive/refs/tags/v0.7.0.zip
--from https://github.com/leocamello/spec-kit-v-model/archive/refs/tags/v0.7.2.zip

# Generate requirements from your spec
/speckit.v-model.requirements
Expand Down
4 changes: 2 additions & 2 deletions catalog-entry.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
"id": "v-model",
"description": "Enforces V-Model paired generation of development specs and test specs with full traceability.",
"author": "leocamello",
"version": "0.7.1",
"download_url": "https://github.com/leocamello/spec-kit-v-model/archive/refs/tags/v0.7.1.zip",
"version": "0.7.2",
"download_url": "https://github.com/leocamello/spec-kit-v-model/archive/refs/tags/v0.7.2.zip",
"repository": "https://github.com/leocamello/spec-kit-v-model",
"license": "MIT",
"requires": {
Expand Down
5 changes: 1 addition & 4 deletions commands/acceptance.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,7 @@ Load `v-model-config.yml` (if it exists at the repository root).
1. Read the command overlay: `commands/overlays/{domain}/acceptance.md`
- If it exists: note its domain-specific guidance for test case generation — acceptance criteria rigor, structural coverage expectations, and validation methods required by the domain standard
- If it does not exist: this domain does not extend this command — proceed with base only
2. Read the template overlay: `templates/overlays/{domain}/acceptance-plan-template.md`
- If it exists: its output sections will be appended after the base template's output — additional sections, mandatory fields, or compliance-specific headings
- If it does not exist: use the base template only
3. Where the base command has a domain-variant section (marked with "If a domain overlay is loaded, prefer its content"), use the overlay's version instead of the base default (e.g., domain-specific acceptance criteria replace generic criteria)
2. Where the base command has a domain-variant section (marked with "If a domain overlay is loaded, prefer its content"), use the overlay's version instead of the base default (e.g., domain-specific acceptance criteria replace generic criteria)

**If `domain` is empty or absent:**
- Proceed with the base command only
Expand Down
5 changes: 1 addition & 4 deletions commands/requirements.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,7 @@ Load `v-model-config.yml` (if it exists at the repository root).
1. Read the command overlay: `commands/overlays/{domain}/requirements.md`
- If it exists: note its additional sections and preferences
- If it does not exist: this domain does not extend this command — proceed with base only
2. Read the template overlay: `templates/overlays/{domain}/requirements-template.md`
- If it exists: its output sections will be appended after the base template's output
- If it does not exist: use the base template only
3. Where the base command has a domain-variant section (marked with "If a domain overlay is loaded, prefer its content"), use the overlay's version instead of the base default
2. Where the base command has a domain-variant section (marked with "If a domain overlay is loaded, prefer its content"), use the overlay's version instead of the base default

**If `domain` is empty or absent:**
- Proceed with the base command only
Expand Down
2 changes: 1 addition & 1 deletion extension.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ schema_version: "1.0"
extension:
id: "v-model"
name: "V-Model Extension Pack"
version: "0.7.1"
version: "0.7.2"
description: "Enforces V-Model paired generation of development specs and test specs with full traceability."
author: "leocamello"
repository: "https://github.com/leocamello/spec-kit-v-model"
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "spec-kit-v-model"
version = "0.7.1"
version = "0.7.2"
description = "V-Model Extension Pack for Spec Kit"
requires-python = ">=3.11"
license = "MIT"
Expand Down
1 change: 1 addition & 0 deletions tests/structural/test_extension_yml.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ def test_no_spec_kit_core_file_modified_outside_extension_yml():
".github/",
".specify/",
".gitignore",
".extensionignore",
"v-model-config.yml.example",
"catalog-entry.json",
"site/",
Expand Down
Loading