Skip to content

feat(strategy): speckit v0.20 scope emission + GA docs/glossary/issue:ingest (#436, #432, #433, #457, #429, #454)#475

Merged
MScottAdams merged 8 commits intophase2/vbrief-cutoverfrom
agent3/ga-strategy-docs/436-432-433-457-429-454-speckit-v020
Apr 20, 2026
Merged

feat(strategy): speckit v0.20 scope emission + GA docs/glossary/issue:ingest (#436, #432, #433, #457, #429, #454)#475
MScottAdams merged 8 commits intophase2/vbrief-cutoverfrom
agent3/ga-strategy-docs/436-432-433-457-429-454-speckit-v020

Conversation

@MScottAdams
Copy link
Copy Markdown
Collaborator

speckit v0.20 scope emission + GA docs / glossary / issue:ingest

This PR lands six GA-blocker items for the v0.20.0 release, split one commit per issue:

  • speckit Phase 4 collides with plan.vbrief.json definition (no scope vBRIEFs emitted) #436 (Task A) — speckit Phase 4 emits scope vBRIEFs per implementation phase

    • strategies/speckit.md Phase 4 now writes one scope vBRIEF per IP to vbrief/pending/YYYY-MM-DD-ip<NNN>-<slug>.vbrief.json (3-digit padded) with canonical Description / Acceptance / Traces narratives, a references entry linking back to vbrief/specification.vbrief.json via x-vbrief/plan, and cross-scope dependencies in plan.metadata.dependencies (plan-level).
    • plan.vbrief.json reverts to its canonical session-todo role.
    • scripts/migrate_vbrief.py gains migrate_speckit_plan() and a --speckit-plan <path> CLI flag that converts an existing speckit-shaped plan.vbrief.json into N scope vBRIEFs using a bilingual edge reader (from/to preferred, fall back to source/target) so both legacy and canonical edges[].blocks dialects translate correctly (covers the v0.20.0 GA blocker: align plan.edges[] field names (from/to vs source/target) #458 migrate_vbrief.py touchpoint).
    • vbrief/vbrief.md documents the ip<NNN> 3-digit padded convention (Risk 5), plan-level plan.metadata.dependencies placement (Risk 6), and canonical narrative keys (Risk 7).
  • speckit Phase 3 -> Phase 4 advances without enforcing ! task spec:render #432 (Task B) — enforce task spec:render as Phase 3 → 4 transition gate

    • Post-Phase 3 section restructured from prose into a 5-step numbered transition gate (mirrors the Phase 2 approval gate).
    • New Phase 3 → 4 transition criterion: SPECIFICATION.md MUST exist AND its hash MUST match the rendered output of vbrief/specification.vbrief.json narratives.
    • skills/deft-directive-setup/SKILL.md invokes task spec:render at the boundary (mandatory for speckit-strategy projects even if the user declines the prompt).
  • Greenfield projects can complete speckit with no PRD/SPECIFICATION export and no prompt #433 (Task C) — prompt to render PRD/SPECIFICATION at end of Phase 3

    • strategies/speckit.md Artifacts Summary gains a 3c. Render PRD row alongside the existing 3b.
    • skills/deft-directive-setup/SKILL.md adds an End-of-Phase-3 Export Prompt with four numbered choices (both / spec-only / PRD-only / skip) before handoff to deft-directive-build.
  • v0.20.0 GA blocker: add deft/glossary.md with v0.20 canonical vocabulary #457 (Task D) — glossary.md canonical v0.20 vocabulary

    • New glossary.md at the repo root with the RFC2119 legend and exactly 13 required terms (Scope vBRIEF, Lifecycle folder, Plan-level narrative, Item-level narrative, Filename stem, Cross-scope dependency, Exit Commands, Origin provenance, Canonical narrative key, Preparatory strategy, Spec-generating strategy, Rendered export, Source of truth). File stays well under 150 lines.
    • Cross-refs added from vbrief/vbrief.md See-also banner, README.md (new "Glossary" section), and UPGRADING.md v0.20 References.
  • release(v0.20.0): remove or revise RC testing safety banner from README before cutting final #429 (Task E) — remove v0.20.0 RC testing safety banner

    • Removed the RC banner + "we are still refining" wording from README.md.
    • Moved a distilled, version-agnostic "test on a fork or copy first" paragraph to UPGRADING.md under a new "Upgrade safety" subsection (Option C).
  • v0.20.0 GA blocker: add task issue:ingest for GitHub issue -> vBRIEF ingestion #454 (Task F) — task issue:ingest for GitHub issue → vBRIEF ingestion

    • New scripts/issue_ingest.py with single-issue (<N> [--status]) and bulk (--all [--label] [--status] [--dry-run]) modes.
    • Deduplicates against existing references[type=github-issue] via scripts/reconcile_issues.py::scan_vbrief_dir. Exit codes: 0 success / 1 duplicate (single) / 2 gh or API error.
    • Shared helpers slugify and create_scope_vbrief extracted into new scripts/_vbrief_build.py; scripts/migrate_vbrief.py re-exports the legacy underscore-prefixed aliases for backward compatibility.
    • Wired via tasks/issue.yml. Documented in vbrief/vbrief.md Quick Reference, README.md (new "Ingesting GitHub issues" subsection + two Document Generation rows), and UPGRADING.md v0.20 expectations.

Tests

  • New tests: tests/content/test_speckit_phase4.py, tests/content/test_speckit_phase3_gate.py, tests/content/test_phase3_export_prompt.py, tests/content/test_glossary.py, tests/cli/test_issue_ingest.py (+ expanded tests/cli/test_migrate_vbrief.py for the speckit-plan translator).
  • task check green on final commit (1763 passed, 1 xfailed).

Closes

Closes #436, closes #432, closes #433, closes #457, closes #429, closes #454.

…436)

- Rewrite strategies/speckit.md Phase 4: emit one scope vBRIEF per IP to vbrief/pending/YYYY-MM-DD-ip<NNN>-<slug>.vbrief.json (3-digit padded) with canonical Description/Acceptance/Traces narratives, x-vbrief/plan reference back to specification.vbrief.json, and plan.metadata.dependencies (plan-level)

- plan.vbrief.json reverts to session-todo role; carries planRef to active scope

- scripts/migrate_vbrief.py: add migrate_speckit_plan() and --speckit-plan CLI flag with bilingual edge reader (from/to preferred, source/target fallback) covering #458

- vbrief/vbrief.md: document ip<NNN> 3-digit padded filename (Risk 5), plan.metadata.dependencies plan-level placement (Risk 6), canonical narrative keys (Risk 7)

- Add tests/content/test_speckit_phase4.py and migrator tests in tests/cli/test_migrate_vbrief.py

- CHANGELOG entry under [Unreleased]
…#432)

- Restructure strategies/speckit.md Post-Phase 3 section from prose into a numbered transition gate (5 steps: run task spec:render, confirm SPECIFICATION.md exists, confirm hash match vs vbrief narratives, describe rendered-view semantics, human approval)

- Add Phase 3 -> Phase 4 transition criterion requiring SPECIFICATION.md exists AND hash matches rendered output of specification.vbrief.json narratives

- Add End-of-Phase-3 Export Prompt and Render Gate to skills/deft-directive-setup/SKILL.md that invokes task spec:render at the speckit Phase 3 -> 4 boundary (mandatory for speckit-strategy projects)

- tests/content/test_speckit_phase3_gate.py: new content tests

- CHANGELOG entry under [Unreleased]
…433)

- Add 3c. Render PRD row to strategies/speckit.md Artifacts Summary alongside the existing 3b. Render SPECIFICATION row (landed with #436 Artifacts Summary refactor, dedicated coverage here)

- End-of-Phase-3 Export Prompt in skills/deft-directive-setup/SKILL.md asks whether to generate SPECIFICATION.md and/or PRD.md with 4 numbered choices (both/spec-only/PRD-only/skip) before handoff to deft-directive-build

- tests/content/test_phase3_export_prompt.py: new content tests

- CHANGELOG entry under [Unreleased]
- Create glossary.md with RFC2119 legend + 13 required v0.20 terms (Scope vBRIEF, Lifecycle folder, Plan-level narrative, Item-level narrative, Filename stem, Cross-scope dependency, Exit Commands, Origin provenance, Canonical narrative key, Preparatory strategy, Spec-generating strategy, Rendered export, Source of truth)

- File stays under 150 lines per scope cap

- Cross-refs from vbrief/vbrief.md See-also banner, README Glossary section, UPGRADING v0.20 References

- tests/content/test_glossary.py asserts existence, <150 lines, RFC2119 legend, all 13 term labels present with cross-links, cross-ref coverage

- CHANGELOG entry under [Unreleased]
- Remove the v0.20.0 release-candidate safety banner from README.md (line 23 block that directed testers to run migrate:vbrief against a fork/copy and mentioned we are still refining)

- Move a distilled, version-agnostic test-on-fork-first paragraph to UPGRADING.md under a new Upgrade safety subsection so advice is preserved without RC-specific wording (Option C from the issue)

- README no longer contains RC-specific or in-progress refining language ahead of the v0.20.0 final tag

- CHANGELOG entry under [Unreleased]
…tion (#454)

- scripts/issue_ingest.py single-issue + bulk modes with gh api/list, dedup via reconcile_issues.scan_vbrief_dir, writes vbrief/<status>/YYYY-MM-DD-<N>-<slug>.vbrief.json with origin provenance

- Exit codes: 0 success, 1 duplicate (single), 2 gh/API error

- Extract shared slugify + create_scope_vbrief helpers into scripts/_vbrief_build.py; migrate_vbrief.py re-exports legacy underscore aliases for backward compat

- tasks/issue.yml wires task issue:ingest

- tests/cli/test_issue_ingest.py: single-issue happy path, dedup hit + CLI exit 1, bulk summary, label filter, dry-run (single+bulk), gh API error CLI exit 2, --help subprocess

- Doc cross-refs: vbrief/vbrief.md Quick Reference, README Document Generation table + new Ingesting GitHub issues subsection, UPGRADING.md v0.20 section

- CHANGELOG entry under [Unreleased]
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 20, 2026

Greptile Summary

This PR lands six GA-blocker items for v0.20.0: speckit Phase 4 scope vBRIEF emission, the Phase 3→4 task spec:render transition gate, end-of-Phase-3 PRD export prompt, a canonical glossary.md, RC-banner removal, and the new task issue:ingest / scripts/issue_ingest.py pipeline. All three issues surfaced in the prior review (slugify underscore stripping, _build_issue_vbrief return-type annotation, and ingest_bulk summary dict annotation) have been resolved correctly.

Confidence Score: 5/5

Safe to merge; all prior P1 issues resolved; remaining findings are P2 style/consistency suggestions that do not affect correctness

All three previously flagged issues are fixed. The two new findings are P2: an empty-string Phase key inconsistency in create_scope_vbrief (Tier uses a guard, Phase does not) and a theoretical re-migration edge case in migrate_speckit_plan. Neither affects current callers or test-suite correctness. 1763 tests pass.

scripts/_vbrief_build.py (Phase/Tier inconsistency), scripts/migrate_vbrief.py (re-migration guard)

Important Files Changed

Filename Overview
scripts/_vbrief_build.py New shared helper module with slugify (underscore fix applied), TODAY, and create_scope_vbrief; minor inconsistency: Phase key is unconditionally included while Tier is conditional
scripts/issue_ingest.py New GitHub issue → scope vBRIEF ingestion script; return type annotation and summary dict type annotation (flagged in prior review) now correctly reflect actual types; dedup, bulk, and dry-run paths look correct
scripts/migrate_vbrief.py Adds migrate_speckit_plan() and bilingual edge reader; plan.vbrief.json always rewritten to session-todo scaffold unconditionally — safe on first run, but accidental re-run after adding session items could silently consume them as new IPs
tasks/issue.yml Clean Taskfile entry for task issue:ingest wiring; --repo is left to CLI_ARGS or auto-detection, which is the documented pattern
tests/cli/test_issue_ingest.py Thorough tests covering happy path, dedup, bulk, dry-run, and gh CLI error paths; no issues found
tests/cli/test_migrate_vbrief.py New speckit-plan section (TestMigrateSpeckitPlan) covers IP emission, 3-digit padding, bilingual edge translation, spec-ref linking, and session-scaffold rewrite; comprehensive
glossary.md New RFC2119 glossary with 13 required v0.20 terms; all cross-reference links verified as present; stays well under 150 lines
tests/content/test_speckit_phase4.py Content tests validating Phase 4 emission conventions against speckit.md and vbrief.md; no issues
tests/content/test_glossary.py Content tests verifying glossary.md has all 13 required terms and RFC2119 legend; no issues
tests/content/test_phase3_export_prompt.py Tests for end-of-Phase-3 export prompt in SKILL.md; no issues
tests/content/test_speckit_phase3_gate.py Tests for Phase 3→4 transition gate in speckit.md; no issues

Sequence Diagram

sequenceDiagram
    participant User
    participant Taskfile
    participant issue_ingest
    participant reconcile_issues
    participant _vbrief_build
    participant vbrief_dir

    User->>Taskfile: task issue:ingest N / --all
    Taskfile->>issue_ingest: uv run issue_ingest.py --vbrief-dir ...
    issue_ingest->>reconcile_issues: scan_vbrief_dir(vbrief_dir)
    reconcile_issues-->>issue_ingest: existing refs {number -> [paths]}
    alt single-issue mode
        issue_ingest->>issue_ingest: _fetch_single_issue(repo, N) via gh api
        issue_ingest->>issue_ingest: ingest_one(issue, ...)
    else bulk mode
        issue_ingest->>reconcile_issues: fetch_open_issues(repo)
        reconcile_issues-->>issue_ingest: [issue dicts]
        issue_ingest->>issue_ingest: ingest_bulk(issues, ...)
    end
    issue_ingest->>_vbrief_build: slugify(title)
    _vbrief_build-->>issue_ingest: slug
    issue_ingest->>vbrief_dir: write pending|proposed|active/YYYY-MM-DD-N-slug.vbrief.json
    issue_ingest-->>User: exit 0 (created) / 1 (duplicate) / 2 (error)
Loading
Prompt To Fix All With AI
This is a comment left during a code review.
Path: scripts/_vbrief_build.py
Line: 82-85

Comment:
**`Phase` key unconditionally included even when empty**

`"Phase": phase` is always written to `narratives` even when `phase` is `""`. This is inconsistent with the `Tier` key which is only added if non-empty (`if tier: narratives["Tier"] = tier`). Any caller that provides an item with no `phase` field will get a spurious `"Phase": ""` in the emitted vBRIEF's narratives dict.

```suggestion
    narratives: dict[str, str] = {
        "Description": title,
    }
    if phase:
        narratives["Phase"] = phase
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: scripts/migrate_vbrief.py
Line: 978-992

Comment:
**`migrate_speckit_plan` re-migration can silently treat session-todo items as new IPs**

After a successful first run, `plan.vbrief.json` is rewritten to an empty session-todo scaffold (`items: []`). The early-exit guard (`if not items: return False, [error]`) prevents a clean re-run on a fully-empty plan. However, if a user adds session-level `items` to `plan.vbrief.json` after migration and then runs `--speckit-plan` again, those items would be parsed as new IP entries — generating spurious scope vBRIEF files — and the plan would be wiped again.

Consider adding a sentinel key (e.g. `"migrated": true` in `vBRIEFInfo`) checked at the top of the function so accidental re-runs on a partially-populated session-todo fail loudly rather than quietly consuming its items.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (3): Last reviewed commit: "Merge phase2/vbrief-cutover into agent3 ..." | Re-trigger Greptile

Comment thread scripts/_vbrief_build.py Outdated
Comment thread scripts/issue_ingest.py Outdated
Comment thread scripts/issue_ingest.py Outdated
- _vbrief_build.py: fix slugify underscore handling (P1)

- issue_ingest.py: annotate _build_issue_vbrief and summary (P2 x2)

- tests: regression test for slugify underscore bug
@MScottAdams
Copy link
Copy Markdown
Collaborator Author

Merged phase2/vbrief-cutover HEAD (710a09c) into this branch to sync with #472 and #474 merges. Only conflict was CHANGELOG.md -- resolved by combining all six agent3 Added entries with the interim #435 entry and the three new Fixed entries (#431, #458, #434). No logic changes in any .py/.md source. task check green (1802 passed, 1 xfailed).

@MScottAdams MScottAdams merged commit d47fc12 into phase2/vbrief-cutover Apr 20, 2026
3 checks passed
MScottAdams added a commit that referenced this pull request Apr 20, 2026
Housekeeping: 10 GA-blocker vBRIEFs for issues #429, #431, #432, #433, #434, #435, #436, #454, #457, #458 moved to completed/ with status: completed. All work is landed on this branch via PRs #472, #474, #475. Origin issues remain OPEN and will auto-close when PR #403 merges to master.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant