@ikon85/agent-workflow-kit 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/ask-matt/SKILL.md +139 -0
- package/.agents/skills/ask-matt/THIRD-PARTY-NOTICES.md +29 -0
- package/.agents/skills/audit-skills/SKILL.md +145 -0
- package/.agents/skills/board-to-waves/SKILL.md +135 -0
- package/.agents/skills/code-review/SKILL.md +64 -0
- package/.agents/skills/codebase-design/DEEPENING.md +37 -0
- package/.agents/skills/codebase-design/DESIGN-IT-TWICE.md +44 -0
- package/.agents/skills/codebase-design/SKILL.md +114 -0
- package/.agents/skills/codebase-design/THIRD-PARTY-NOTICES.md +29 -0
- package/.agents/skills/codex-adapter-sync/SKILL.md +151 -0
- package/.agents/skills/decision-gate/SKILL.md +67 -0
- package/.agents/skills/diagnose/SKILL.md +136 -0
- package/.agents/skills/diagnose/THIRD-PARTY-NOTICES.md +29 -0
- package/.agents/skills/diagnose/scripts/hitl-loop.template.sh +41 -0
- package/.agents/skills/domain-modeling/ADR-FORMAT.md +47 -0
- package/.agents/skills/domain-modeling/CONTEXT-FORMAT.md +60 -0
- package/.agents/skills/domain-modeling/SKILL.md +76 -0
- package/.agents/skills/domain-modeling/THIRD-PARTY-NOTICES.md +29 -0
- package/.agents/skills/git-worktree-recover/SKILL.md +176 -0
- package/.agents/skills/grill-me/SKILL.md +54 -0
- package/.agents/skills/grill-me/THIRD-PARTY-NOTICES.md +29 -0
- package/.agents/skills/grill-with-docs/ADR-FORMAT.md +47 -0
- package/.agents/skills/grill-with-docs/CONTEXT-FORMAT.md +60 -0
- package/.agents/skills/grill-with-docs/SKILL.md +137 -0
- package/.agents/skills/grill-with-docs/THIRD-PARTY-NOTICES.md +29 -0
- package/.agents/skills/implement/SKILL.md +15 -0
- package/.agents/skills/implement/THIRD-PARTY-NOTICES.md +29 -0
- package/.agents/skills/improve-codebase-architecture/ADR-FORMAT.md +47 -0
- package/.agents/skills/improve-codebase-architecture/CONTEXT-FORMAT.md +60 -0
- package/.agents/skills/improve-codebase-architecture/DEEPENING.md +37 -0
- package/.agents/skills/improve-codebase-architecture/HTML-REPORT.md +123 -0
- package/.agents/skills/improve-codebase-architecture/INTERFACE-DESIGN.md +46 -0
- package/.agents/skills/improve-codebase-architecture/LANGUAGE.md +53 -0
- package/.agents/skills/improve-codebase-architecture/SKILL.md +88 -0
- package/.agents/skills/improve-codebase-architecture/THIRD-PARTY-NOTICES.md +29 -0
- package/.agents/skills/kit-release/SKILL.md +56 -0
- package/.agents/skills/local-ci/SKILL.md +94 -0
- package/.agents/skills/orchestrate-wave/SKILL.md +261 -0
- package/.agents/skills/orchestrate-wave/references/builder-contract.md +67 -0
- package/.agents/skills/prototype/LOGIC.md +79 -0
- package/.agents/skills/prototype/SKILL.md +30 -0
- package/.agents/skills/prototype/THIRD-PARTY-NOTICES.md +29 -0
- package/.agents/skills/prototype/UI.md +112 -0
- package/.agents/skills/research/SKILL.md +12 -0
- package/.agents/skills/research/THIRD-PARTY-NOTICES.md +29 -0
- package/.agents/skills/resolving-merge-conflicts/SKILL.md +14 -0
- package/.agents/skills/resolving-merge-conflicts/THIRD-PARTY-NOTICES.md +29 -0
- package/.agents/skills/retro/SKILL.md +209 -0
- package/.agents/skills/scale-check/SKILL.md +141 -0
- package/.agents/skills/security-audit/SKILL.md +67 -0
- package/.agents/skills/setup-workflow/SKILL.md +187 -0
- package/.agents/skills/setup-workflow/THIRD-PARTY-NOTICES.md +29 -0
- package/.agents/skills/setup-workflow/board-sync.md +111 -0
- package/.agents/skills/setup-workflow/code-review.md +26 -0
- package/.agents/skills/setup-workflow/domain.md +51 -0
- package/.agents/skills/setup-workflow/issue-tracker-github.md +35 -0
- package/.agents/skills/setup-workflow/issue-tracker-gitlab.md +34 -0
- package/.agents/skills/setup-workflow/issue-tracker-local.md +30 -0
- package/.agents/skills/setup-workflow/orchestrate-wave-seed.md +44 -0
- package/.agents/skills/setup-workflow/spec-completeness-seed.md +44 -0
- package/.agents/skills/setup-workflow/spec-self-critique-seed.md +43 -0
- package/.agents/skills/setup-workflow/triage-labels.md +18 -0
- package/.agents/skills/setup-workflow/workflow-overview.md +33 -0
- package/.agents/skills/spec-self-critique/SKILL.md +152 -0
- package/.agents/skills/spec-self-critique/scenarios.md +82 -0
- package/.agents/skills/tdd/SKILL.md +120 -0
- package/.agents/skills/tdd/THIRD-PARTY-NOTICES.md +29 -0
- package/.agents/skills/tdd/deep-modules.md +33 -0
- package/.agents/skills/tdd/interface-design.md +31 -0
- package/.agents/skills/tdd/mocking.md +59 -0
- package/.agents/skills/tdd/refactoring.md +10 -0
- package/.agents/skills/tdd/tests.md +61 -0
- package/.agents/skills/to-issues/SKILL.md +325 -0
- package/.agents/skills/to-issues/THIRD-PARTY-NOTICES.md +29 -0
- package/.agents/skills/to-prd/PROGRAM-PRD-FORMAT.md +162 -0
- package/.agents/skills/to-prd/SKILL.md +180 -0
- package/.agents/skills/to-prd/THIRD-PARTY-NOTICES.md +29 -0
- package/.agents/skills/to-waves/SKILL.md +260 -0
- package/.agents/skills/to-waves/SLICE-METADATA-FORMAT.md +74 -0
- package/.agents/skills/triage/AGENT-BRIEF.md +168 -0
- package/.agents/skills/triage/OUT-OF-SCOPE.md +101 -0
- package/.agents/skills/triage/SKILL.md +122 -0
- package/.agents/skills/triage/THIRD-PARTY-NOTICES.md +29 -0
- package/.agents/skills/verify-spike/SKILL.md +39 -0
- package/.agents/skills/wayfinder/SKILL.md +127 -0
- package/.agents/skills/wayfinder/THIRD-PARTY-NOTICES.md +29 -0
- package/.agents/skills/wrapup/SKILL.md +71 -0
- package/.agents/skills/wrapup/SOURCES.txt +6 -0
- package/.agents/skills/zoom-out/SKILL.md +7 -0
- package/.agents/skills/zoom-out/THIRD-PARTY-NOTICES.md +29 -0
- package/.claude/hooks/_hook_utils.py +184 -0
- package/.claude/hooks/drift-guard.py +176 -0
- package/.claude/hooks/skill-drift-hint.py +122 -0
- package/.claude/hooks/sync-board-status.py +191 -0
- package/.claude/skills/ask-matt/SKILL.md +139 -0
- package/.claude/skills/ask-matt/THIRD-PARTY-NOTICES.md +29 -0
- package/.claude/skills/audit-skills/SKILL.md +145 -0
- package/.claude/skills/board-to-waves/SKILL.md +148 -0
- package/.claude/skills/code-review/SKILL.md +64 -0
- package/.claude/skills/codebase-design/DEEPENING.md +37 -0
- package/.claude/skills/codebase-design/DESIGN-IT-TWICE.md +44 -0
- package/.claude/skills/codebase-design/SKILL.md +114 -0
- package/.claude/skills/codebase-design/THIRD-PARTY-NOTICES.md +29 -0
- package/.claude/skills/codex-build/SKILL.md +126 -0
- package/.claude/skills/codex-build/THIRD-PARTY-NOTICES.md +35 -0
- package/.claude/skills/codex-review/SKILL.md +145 -0
- package/.claude/skills/codex-review/THIRD-PARTY-NOTICES.md +31 -0
- package/.claude/skills/decision-gate/SKILL.md +67 -0
- package/.claude/skills/diagnose/SKILL.md +136 -0
- package/.claude/skills/diagnose/THIRD-PARTY-NOTICES.md +29 -0
- package/.claude/skills/diagnose/scripts/hitl-loop.template.sh +41 -0
- package/.claude/skills/domain-modeling/ADR-FORMAT.md +47 -0
- package/.claude/skills/domain-modeling/CONTEXT-FORMAT.md +60 -0
- package/.claude/skills/domain-modeling/SKILL.md +76 -0
- package/.claude/skills/domain-modeling/THIRD-PARTY-NOTICES.md +29 -0
- package/.claude/skills/git-guardrails-claude-code/SKILL.md +96 -0
- package/.claude/skills/git-guardrails-claude-code/THIRD-PARTY-NOTICES.md +29 -0
- package/.claude/skills/git-guardrails-claude-code/scripts/block-dangerous-git.sh +28 -0
- package/.claude/skills/git-worktree-recover/SKILL.md +182 -0
- package/.claude/skills/grill-me/SKILL.md +54 -0
- package/.claude/skills/grill-me/THIRD-PARTY-NOTICES.md +29 -0
- package/.claude/skills/grill-me-codex/SKILL.md +158 -0
- package/.claude/skills/grill-me-codex/THIRD-PARTY-NOTICES.md +32 -0
- package/.claude/skills/grill-with-docs/ADR-FORMAT.md +47 -0
- package/.claude/skills/grill-with-docs/CONTEXT-FORMAT.md +60 -0
- package/.claude/skills/grill-with-docs/SKILL.md +137 -0
- package/.claude/skills/grill-with-docs/THIRD-PARTY-NOTICES.md +29 -0
- package/.claude/skills/grill-with-docs-codex/ADR-FORMAT.md +47 -0
- package/.claude/skills/grill-with-docs-codex/CONTEXT-FORMAT.md +60 -0
- package/.claude/skills/grill-with-docs-codex/SKILL.md +233 -0
- package/.claude/skills/grill-with-docs-codex/THIRD-PARTY-NOTICES.md +33 -0
- package/.claude/skills/implement/SKILL.md +15 -0
- package/.claude/skills/implement/THIRD-PARTY-NOTICES.md +29 -0
- package/.claude/skills/improve-codebase-architecture/ADR-FORMAT.md +47 -0
- package/.claude/skills/improve-codebase-architecture/CONTEXT-FORMAT.md +60 -0
- package/.claude/skills/improve-codebase-architecture/DEEPENING.md +37 -0
- package/.claude/skills/improve-codebase-architecture/HTML-REPORT.md +123 -0
- package/.claude/skills/improve-codebase-architecture/INTERFACE-DESIGN.md +46 -0
- package/.claude/skills/improve-codebase-architecture/LANGUAGE.md +53 -0
- package/.claude/skills/improve-codebase-architecture/SKILL.md +88 -0
- package/.claude/skills/improve-codebase-architecture/THIRD-PARTY-NOTICES.md +29 -0
- package/.claude/skills/kit-release/SKILL.md +56 -0
- package/.claude/skills/local-ci/SKILL.md +94 -0
- package/.claude/skills/orchestrate-wave/SKILL.md +269 -0
- package/.claude/skills/orchestrate-wave/references/builder-contract.md +67 -0
- package/.claude/skills/prototype/LOGIC.md +79 -0
- package/.claude/skills/prototype/SKILL.md +30 -0
- package/.claude/skills/prototype/THIRD-PARTY-NOTICES.md +29 -0
- package/.claude/skills/prototype/UI.md +112 -0
- package/.claude/skills/research/SKILL.md +12 -0
- package/.claude/skills/research/THIRD-PARTY-NOTICES.md +29 -0
- package/.claude/skills/resolving-merge-conflicts/SKILL.md +14 -0
- package/.claude/skills/resolving-merge-conflicts/THIRD-PARTY-NOTICES.md +29 -0
- package/.claude/skills/retro/SKILL.md +209 -0
- package/.claude/skills/scale-check/SKILL.md +141 -0
- package/.claude/skills/security-audit/SKILL.md +67 -0
- package/.claude/skills/setup-pre-commit/SKILL.md +104 -0
- package/.claude/skills/setup-pre-commit/scripts/pre-commit.template.sh +35 -0
- package/.claude/skills/setup-workflow/SKILL.md +187 -0
- package/.claude/skills/setup-workflow/THIRD-PARTY-NOTICES.md +29 -0
- package/.claude/skills/setup-workflow/board-sync.md +111 -0
- package/.claude/skills/setup-workflow/code-review.md +26 -0
- package/.claude/skills/setup-workflow/domain.md +51 -0
- package/.claude/skills/setup-workflow/issue-tracker-github.md +35 -0
- package/.claude/skills/setup-workflow/issue-tracker-gitlab.md +34 -0
- package/.claude/skills/setup-workflow/issue-tracker-local.md +30 -0
- package/.claude/skills/setup-workflow/orchestrate-wave-seed.md +44 -0
- package/.claude/skills/setup-workflow/spec-completeness-seed.md +44 -0
- package/.claude/skills/setup-workflow/spec-self-critique-seed.md +43 -0
- package/.claude/skills/setup-workflow/triage-labels.md +18 -0
- package/.claude/skills/setup-workflow/workflow-overview.md +33 -0
- package/.claude/skills/skill-manifest.json +389 -0
- package/.claude/skills/spec-self-critique/SKILL.md +152 -0
- package/.claude/skills/spec-self-critique/scenarios.md +82 -0
- package/.claude/skills/tdd/SKILL.md +120 -0
- package/.claude/skills/tdd/THIRD-PARTY-NOTICES.md +29 -0
- package/.claude/skills/tdd/deep-modules.md +33 -0
- package/.claude/skills/tdd/interface-design.md +31 -0
- package/.claude/skills/tdd/mocking.md +59 -0
- package/.claude/skills/tdd/refactoring.md +10 -0
- package/.claude/skills/tdd/tests.md +61 -0
- package/.claude/skills/to-issues/SKILL.md +325 -0
- package/.claude/skills/to-issues/THIRD-PARTY-NOTICES.md +29 -0
- package/.claude/skills/to-prd/PROGRAM-PRD-FORMAT.md +162 -0
- package/.claude/skills/to-prd/SKILL.md +180 -0
- package/.claude/skills/to-prd/THIRD-PARTY-NOTICES.md +29 -0
- package/.claude/skills/to-waves/SKILL.md +260 -0
- package/.claude/skills/to-waves/SLICE-METADATA-FORMAT.md +74 -0
- package/.claude/skills/triage/AGENT-BRIEF.md +168 -0
- package/.claude/skills/triage/OUT-OF-SCOPE.md +101 -0
- package/.claude/skills/triage/SKILL.md +122 -0
- package/.claude/skills/triage/THIRD-PARTY-NOTICES.md +29 -0
- package/.claude/skills/verify-spike/SKILL.md +39 -0
- package/.claude/skills/wayfinder/SKILL.md +127 -0
- package/.claude/skills/wayfinder/THIRD-PARTY-NOTICES.md +29 -0
- package/.claude/skills/wrapup/SKILL.md +81 -0
- package/.claude/skills/wrapup/SOURCES.txt +6 -0
- package/.claude/skills/write-a-skill/GLOSSARY.md +201 -0
- package/.claude/skills/write-a-skill/SKILL.md +88 -0
- package/.claude/skills/write-a-skill/THIRD-PARTY-NOTICES.md +29 -0
- package/.claude/skills/zoom-out/SKILL.md +7 -0
- package/.claude/skills/zoom-out/THIRD-PARTY-NOTICES.md +29 -0
- package/LICENSE +28 -0
- package/PROVENANCE.md +39 -0
- package/README.md +619 -0
- package/agent-workflow-kit.package.json +1939 -0
- package/docs/agents/board-sync.md +71 -0
- package/docs/agents/code-review.md +14 -0
- package/docs/agents/domain.md +7 -0
- package/docs/agents/issue-tracker.md +12 -0
- package/docs/agents/security-audit-runbook-template.md +205 -0
- package/docs/agents/skills/orchestrate-wave.md +13 -0
- package/docs/agents/skills/spec-self-critique.md +18 -0
- package/docs/agents/triage-labels.md +10 -0
- package/docs/agents/wave-anchor-template.md +88 -0
- package/docs/conventions/spec-completeness.md +23 -0
- package/docs/index.html +56 -0
- package/docs/methodology.html +488 -0
- package/docs/methodology.svg +93 -0
- package/docs/workflow.png +0 -0
- package/package.json +40 -0
- package/scripts/anchor_table.py +343 -0
- package/scripts/board-sync.py +1232 -0
- package/scripts/board_config.py +147 -0
- package/scripts/board_fields.py +192 -0
- package/scripts/build-kit.mjs +116 -0
- package/scripts/build-kit.test.mjs +59 -0
- package/scripts/check-kit-staleness.mjs +45 -0
- package/scripts/check-kit-staleness.test.mjs +19 -0
- package/scripts/execute-ready-check.py +516 -0
- package/scripts/issue_deps.py +79 -0
- package/scripts/kit-release.mjs +100 -0
- package/scripts/kit-release.test.mjs +67 -0
- package/scripts/lib/audit-refs.mjs +146 -0
- package/scripts/lib/scrub.mjs +113 -0
- package/scripts/lib/scrub.test.mjs +187 -0
- package/scripts/loc_offender_core.py +196 -0
- package/scripts/loc_offender_gate.py +182 -0
- package/scripts/node_kind.py +68 -0
- package/scripts/portability_profile_scan.py +53 -0
- package/scripts/pr-body-check.py +263 -0
- package/scripts/program_graph.py +125 -0
- package/scripts/program_graph_parse.py +275 -0
- package/scripts/program_graph_validate.py +256 -0
- package/scripts/program_sync.py +160 -0
- package/scripts/release-delta-guard.mjs +96 -0
- package/scripts/release-delta-guard.test.mjs +53 -0
- package/scripts/test_board_sync_create_idempotency.py +104 -0
- package/scripts/test_dist_kit_smoke.py +199 -0
- package/scripts/test_kit_docs_language_census.py +178 -0
- package/scripts/test_skill_code_review_seed.py +89 -0
- package/scripts/test_skill_frontmatter_lint.py +226 -0
- package/scripts/test_skill_gh_lint.py +124 -0
- package/scripts/test_skill_language_census.py +254 -0
- package/scripts/test_skill_portability_lint.py +773 -0
- package/scripts/test_skill_publish_audit.py +300 -0
- package/scripts/test_skill_selfcontainment_lint.py +255 -0
- package/scripts/test_skill_setup_workflow_seeds.py +200 -0
- package/scripts/test_skill_stale_name_lint.py +126 -0
- package/scripts/test_skill_surface_refs.py +300 -0
- package/scripts/test_skill_trailing_artifact_lint.py +71 -0
- package/scripts/wrapup-land.py +573 -0
- package/src/cli.mjs +70 -0
- package/src/commands/diff.mjs +6 -0
- package/src/commands/init.mjs +59 -0
- package/src/commands/uninstall.mjs +43 -0
- package/src/commands/update.mjs +95 -0
- package/src/lib/atomicWrite.mjs +49 -0
- package/src/lib/bundle.mjs +133 -0
- package/src/lib/hash.mjs +13 -0
- package/src/lib/manifest.mjs +58 -0
- package/src/lib/sentinel.mjs +20 -0
- package/src/lib/settings.mjs +23 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: to-prd
|
|
3
|
+
disable-model-invocation: true
|
|
4
|
+
description: "Turn a locked plan (PLAN.md in the worktree, conversation context, or an externally-authored spec) into a Draft-PRD issue on the project board, then run spec-self-critique. Use after a grill (grill-me / grill-with-docs / their -codex variants) when you want to publish the PRD. Three modes — create fresh, reuse an existing cluster/Wave-less issue, or auto-detect a Program-PRD from a plan's Wellenplan chapter. Does NOT decompose into slices (that is to-issues) and does NOT set type:cluster / Wave (that is to-issues promotion)."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# to-prd — Draft PRD to the Board
|
|
8
|
+
|
|
9
|
+
> **Skill identity (don't get confused):** the folder `to-prd` + invocation `/to-prd` map to Matt Pocock's upstream skill **`to-spec`**. Upstream renamed `to-prd` → `to-spec` (v1.1.0); we deliberately keep the folder name `to-prd` (invocation stability, and PRD is this workflow's vocabulary). Content remains our fork, compared against upstream `to-spec` @ `d574778`. Provenance/rename ledger: `docs/agents/provenance.md` (§Re-Sync-Log), at the project root.
|
|
10
|
+
|
|
11
|
+
Takes an **already-locked plan** and publishes it as a **Draft-PRD issue**. **Never invents requirements** — only synthesizes what's already decided. Pipeline: `board-to-waves → grill(-with-docs) → to-prd → to-issues`. The **grill sits upstream**; to-prd writes the PRD after the grill. **Slicing + promotion to an anchor (cluster/Wave, child link) = `to-issues`** (future), not here.
|
|
12
|
+
|
|
13
|
+
Board constants (project node, field/status IDs) + helpers live **consumer-side**: read `docs/agents/board-sync.md` from the project root + use the helper `scripts/board-sync.py` (missing → `/setup-workflow` scaffolds the project layer). Issue body **always** via `--body-file` (inline `--body` with backticks/parens crashes bash).
|
|
14
|
+
|
|
15
|
+
## 1. Input — source-agnostic
|
|
16
|
+
|
|
17
|
+
to-prd reads the locked plan regardless of source:
|
|
18
|
+
<!-- mirror-xform:start codex-escalation -->
|
|
19
|
+
- **Default: `PLAN.md` in the current worktree** — `grill-me` / `grill-with-docs` only write `PLAN.md` conditionally (on a worktree/session cut).
|
|
20
|
+
<!-- mirror-xform:end -->
|
|
21
|
+
- **Fallback: conversation context** (same-session, no PLAN.md).
|
|
22
|
+
- **Externally supplied:** a spec authored elsewhere (e.g. Claude Web/Codex), handed into context.
|
|
23
|
+
|
|
24
|
+
If a `PLAN.md` exists in the worktree, it's the source; otherwise conversation/external.
|
|
25
|
+
|
|
26
|
+
**Cold start = extract-or-synthesize, not assume-or-fail (anchor).** `to-prd` is the **universal normalizer** for loose artifacts (plan/doc/external PRD without a board issue): the PRD template sections are **extracted from what exists**, instead of assuming a prior grill. `to-prd` **mandates no** grill and **no** Codex — depth is the entry person's choice.
|
|
27
|
+
- **A non-derivable required section ≠ a silent "complete" placeholder (anchor):** if a required section (e.g. "Testing Decisions") can't be derived from the input, the open content moves into a **`## Open Questions (not derivable from input)`** section — the PRD is then honestly *open* instead of falsely *complete*. `spec-self-critique` (step 5) remains mandatory.
|
|
28
|
+
- **Downstream contract:** a non-empty `## Open Questions` forces `to-issues` to publish the affected slices as **HITL** (`headings.vorBau` heading, board profile `docs/agents/board-sync.md`; <project> currently `## Vor Bau zu klären`) or ask first — open questions never disappear silently (see `to-issues` §3b). Each open question is classified by **gate type** (🧭 design grill / 🔬 verify-spike / 📐 trade-off research / 📝 review note) so `to-issues` sequences it as a gate slice **before** the dependent build slice (gate-before-build) — a 📝 review note is **not** cut into a slice (see template section "Review Notes" + `to-issues` §3b). (Retro anchor)
|
|
29
|
+
|
|
30
|
+
## 2. Detect mode — new vs existing issue
|
|
31
|
+
|
|
32
|
+
No user flag — auto:
|
|
33
|
+
- **Mode A (fresh):** no target issue → to-prd creates a new Draft-PRD.
|
|
34
|
+
- **Mode B (reuse):** a **cluster/Wave-less** issue already exists (an earlier Draft-PRD on re-run, or a de-cored `board-to-waves` candidate stub) → to-prd writes the PRD **into that issue** (no duplicate).
|
|
35
|
+
- **Mode program (auto-detected, no flag, same as A/B):** the plan/source carries a `## Wellenplan` chapter (the machine-parsable table `.claude/skills/to-prd/PROGRAM-PRD-FORMAT.md` defines) → to-prd writes a **Program-PRD** per that format instead of the regular `<prd-template>` below (§4b), stamps `<!-- prd: program -->` instead of `<!-- prd: awaiting-decomposition -->` (§4), and the §8 audit line names the mode loudly (`mode=program`). Detection is purely content-based — a program-mode write can still be a fresh create (Mode A) or a reuse (Mode B); the Wellenplan chapter flips the format/marker/label, not the target-selection logic.
|
|
36
|
+
|
|
37
|
+
**Cluster/Wave discriminator (identical wording — `to-prd` §2 / `to-issues` §5):** `type:cluster` (label) always stops. A Wave number also stops, **unless** the target carries the `wave-stub` label — a Wave-stamped `wave-stub` issue is a **Stufe-1p Program-stub** (`to-waves`-published, native parent = a Program-PRD) and remains a **valid target**. A Wave-stamped issue **without** `wave-stub` (an already-assigned leaf, or a drifted item) is still a hard stop.
|
|
38
|
+
|
|
39
|
+
**Hard stop before any write:** per the discriminator above → **abort** and report: "cluster/Wave anchor is not a to-prd target — belongs on the Wave-model/`to-issues` path". to-prd **never sets** cluster/Wave and **never strips** them — it only ever operates on cluster/Wave-less issues, or on a `wave-stub`-labeled Stufe-1p stub (the exception above — this is how `to-waves`'s per-wave-start content pass writes into a wave stub, `to-waves` SKILL.md §7). Wave lives in the Projects-v2 **field**, not as a label → read the board item + its labels before writing:
|
|
40
|
+
```bash
|
|
41
|
+
gh project item-list 1 --owner <owner> --limit 500 --format json # check target's Wave/cluster/wave-stub membership
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Programm-Verdacht net (a plan without a Wellenplan chapter, but oversized).** When the source carries **no** `## Wellenplan` chapter but its scope trips the `scale-check` altitude criteria (owned at `.claude/skills/scale-check/SKILL.md` § "Altitude criteria (the single source of truth)" — referenced here, **never** re-forked) — e.g. **staged delivery across >~7 slices** or **several subsystems that each stand on their own** — to-prd does **not** silently write a plain Feature-PRD. It surfaces a loud hint first: "Programm-Verdacht — scale-check-Kriterien prüfen", catching a mis-entry below the program altitude before the Feature-PRD write proceeds. Only after that hint is seen (confirmed as a Feature by the doubt-default, or re-routed through `scale-check`/a program grill) does the write continue.
|
|
45
|
+
|
|
46
|
+
## 3. Target identity — identity ≠ content
|
|
47
|
+
|
|
48
|
+
- **Mode B:** target issue number **explicit** (passed in/from context). Branch derivation `feat/<#>-…` **only** when the operation explicitly says "update this issue" — the slice branch is **not** automatically the PRD.
|
|
49
|
+
- **Mode A — idempotency via two separate markers in the body:**
|
|
50
|
+
- **Stable source identity** `<!-- prd-source-id: <id> -->` — **never** changes across plan content edits (otherwise search-before-create misses the changed re-run → duplicate). **Default rule** for `<id>` (identity ≠ content; set on the **first** to-prd run, **never** changed after — the slug then lives in the issue body and is discoverable via search-before-create): kebab-case slug of the plan topic. Priority: **(1)** explicitly passed ID / durable issue number → **(2)** existing slug from a prior run (found via search-before-create) → **(3)** new kebab-case slug from the plan/title topic. The `PLAN.md` path is only a **secondary hint** (not stable across worktrees; external specs have none), **never** the identity itself.
|
|
51
|
+
- **Separate content fingerprint** `<!-- prd-content-fp: <hash> -->` — only for diff/audit/bump decisions, **not** for identity.
|
|
52
|
+
- **search-before-create:** **no** reliance on GitHub Search (doesn't index HTML comments). Bounded, local:
|
|
53
|
+
```bash
|
|
54
|
+
gh issue list --repo <owner>/<repo> --state open --limit 500 --json number,body,labels
|
|
55
|
+
# filter locally on `prd-source-id: <id>` → 1 match ⇒ update; >1 ⇒ STOP+report; 0 ⇒ create
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## 4. Write the Draft PRD (deliverable)
|
|
59
|
+
|
|
60
|
+
1. Understand repo/code (if not already), respect the domain glossary + ADRs. Sketch deep modules, align with the user (which get tested).
|
|
61
|
+
2. Write the PRD per the template below.
|
|
62
|
+
3. **Board sync (mandatory):**
|
|
63
|
+
- **Status `Spec`**, exactly **one** `type:*` (default `type:feature`; pure process/workflow scope → `type:followup`/`type:research` per intent) **plus** one `priority:*` (mandatory vocabulary "type+priority"). **No** `type:cluster`, **no** Wave, **no** `ready-for-agent` — a Draft PRD isn't buildable yet, it's waiting on `to-issues` decomposition.
|
|
64
|
+
- Board sync via helper:
|
|
65
|
+
```bash
|
|
66
|
+
python3 scripts/board-sync.py create --title "<PRD title>" --body-file <prd.md> \
|
|
67
|
+
--label type:feature --label priority:medium --status-role spec # Mode A
|
|
68
|
+
# Mode B: gh issue edit <target> --body-file <prd.md> + board-sync.py add --issue <target> --status-role spec
|
|
69
|
+
```
|
|
70
|
+
- **Mode B — explicit status flip:** writing the PRD into a `board-to-waves` stub, `board-sync.py add --issue <target> --status-role spec` flips the board status **triaged → spec** (role names; the stub sat at the triaged-role status, a Draft PRD sits at the spec-role status).
|
|
71
|
+
- **mode=program's `type:*`:** the Program-PRD's one `type:*` label is the profile's `labels.programType` value (`board_config.program_type_label()`, literal default `type:program` when unset) — never `type:feature` **and** `type:program` together (the "exactly one `type:*`" invariant is unchanged, program mode just uses a different vocabulary member). `type_labels_to_strip` protects this label from ever being stripped at promote (a Program-PRD is never itself a promote target).
|
|
72
|
+
4. **Body markers (top of the PRD body):**
|
|
73
|
+
- `**plan_revision:** r1`
|
|
74
|
+
- `<!-- prd: awaiting-decomposition -->` — durable distinguishability marker: makes "PRD awaiting `to-issues`" board-discoverable **without** a new label (status `Spec` alone also covers planned anchors/other specs).
|
|
75
|
+
- **mode=program:** `<!-- prd: program -->` **instead of** `awaiting-decomposition` — the program-altitude counterpart marker (never both on the same issue).
|
|
76
|
+
- `<!-- prd-source-id: <id> -->` + `<!-- prd-content-fp: <hash> -->` (see step 3).
|
|
77
|
+
5. **Mode B label normalization:** if the reused issue carries wrong/multiple `type:*`, missing `priority:*`, `ready-for-agent`, or `needs-info` → **normalize onto the PRD contract** (exactly one `type:*`, one `priority:*`, no `ready-for-agent`/`needs-info`). Exception per the discriminator (§2): `type:cluster` always, or Wave **without** `wave-stub` → **no** normalization, **hard stop** (step 2); a `wave-stub`-labeled Stufe-1p target normalizes normally — it is a valid Mode B target.
|
|
78
|
+
|
|
79
|
+
## 4b. Program-PRD body (mode=program)
|
|
80
|
+
|
|
81
|
+
mode=program writes the Program-PRD per `.claude/skills/to-prd/PROGRAM-PRD-FORMAT.md` instead of the `<prd-template>` below — a **parallel** grammar for the program altitude, not a replacement (a Feature-PRD keeps using `<prd-template>` unchanged). It carries: the `## Scope` chapter with stable Scope-Item IDs (`S1`, `S2`, …), the machine-parsable `## Wellenplan` table (`Welle | Status | Name | Phase | Slices | Gate | covers`), the `## Phasen-Gates` checklist (only when the program uses phases), the `## Slices` per-slice detail chapter (one `####` section per planned slice, per `SLICE-METADATA-FORMAT.md`'s grammar), and the Abbruch-Konvention. `scripts/program_graph.py` (`board-sync.py validate-graph`) is the parser — to-prd writes the shape, it does not itself validate the graph (that is `to-waves`'s job, run once the Program-PRD exists).
|
|
82
|
+
|
|
83
|
+
## 5. `spec-self-critique` — mandatory next step
|
|
84
|
+
|
|
85
|
+
to-prd has `disable-model-invocation: true` and can't literally invoke a skill. **After** the PRD write, the agent **must** run `spec-self-critique` on the Draft PRD; its visible two-liner (`Self-critique complete — N corrections: …` or `…no corrections needed`) is required output **before** the user review question.
|
|
86
|
+
|
|
87
|
+
## 6. Idempotent reconcile (re-run)
|
|
88
|
+
|
|
89
|
+
- **`plan_revision` parse:** counter `r<N>`; missing/malformed → treat as `r1` + warn. **Body-changing** = a non-empty diff over the **canonical PRD sections** (Problem/Solution/User-Stories/Implementation-Decisions/Testing), **excluding** metadata markers, the child-drift section, and critique output. An identical plan re-run does **not** bump.
|
|
90
|
+
- **R1 — no children:** update body instead of duplicating; bump `plan_revision` only on a body-changing run; critique re-runs.
|
|
91
|
+
- **R2 — children/cluster exist:** update body + bump + **flag durably** — a **`## Child Drift (as of r<N>)`** section in the body (not ephemeral chat output) lists children + their revision. **No** child mutation (= `to-issues`/1d), **no** blocking guard (= 1g).
|
|
92
|
+
- **Program-stub exception to R2 (Stufe-1p pre-created skeleton):** if the Mode B target is a `wave-stub`-labeled Stufe-1p Program-stub (native parent = a Program-PRD), its existing native children are the **slice leaves `to-waves` pre-created** for this wave — that is the program's **expected skeleton**, not R2's `## Child Drift` finding, as long as they match the Program-Graph's `Wellenplan` row for this wave. A mismatch (a missing or a foreign child) is `validate-graph`'s finding to raise, not this reconcile heuristic's — to-prd Mode B does not re-derive graph conformance itself. An ordinary Mode B target (a plain cluster/Wave-less reuse, or a `board-to-waves` candidate stub) keeps the unmodified R2 behavior.
|
|
93
|
+
- **Child discovery:** native sub-issues (via `python3 scripts/board-sync.py parent-of <#>` / rollup) are the authoritative set; report native-vs-body-listed mismatches in the drift section.
|
|
94
|
+
|
|
95
|
+
## 7. Execute-ready assertion (exit)
|
|
96
|
+
|
|
97
|
+
- **Before the write (gate):** target carries cluster/Wave → **fail before write** (hard stop, step 2) — never "reconcile after the write".
|
|
98
|
+
- **After the write:** assert that the Draft PRD **exists as a board item** (status write = `Spec`), exactly **one** `type:*` + **one** `priority:*`, **no** `ready-for-agent`, **no** `type:cluster` + **no** Wave (defensive against accidental mutation), carries `plan_revision` + `awaiting-decomposition` + `prd-source-id`, body complete (critique ran). = an unambiguous "PRD-awaiting-decomposition" state (neither AFK leaf nor HITL child — that's `to-issues`'s call). mode=program asserts the same shape with its own markers: `plan_revision` + `<!-- prd: program -->` + `prd-source-id`, the profile's `programType` label (default `type:program`) as the one `type:*`, still no `ready-for-agent`, still no `type:cluster`/Wave — a Program-PRD is exactly as "awaiting further work" as a Feature-PRD, just at a higher altitude (its own lifecycle, §9).
|
|
99
|
+
|
|
100
|
+
## 8. Audit block (visible output)
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
to-prd: mode=<A|B|program> target=#<n> <created|updated> rev <old>→<new>
|
|
104
|
+
status=Spec labels=<type:*, priority:*> cluster/Wave=none
|
|
105
|
+
source=<plan|conversation|external> synthesized=<marker-list | none> readiness=<ok | open-questions>
|
|
106
|
+
child-drift=<none | #a(r1) #b(r1) …>
|
|
107
|
+
```
|
|
108
|
+
`source` = where the input came from (make cold start visible anchor). `synthesized` = which markers `to-prd` freshly set (e.g. `prd-source-id`). `readiness=open-questions` ⇔ the PRD carries a non-empty `## Open Questions` section. For `mode=program`, `labels` shows the profile's `programType` value (default `type:program`) as the one `type:*`, and `cluster/Wave=none` still holds for the Program-PRD itself.
|
|
109
|
+
|
|
110
|
+
## 9. Program-PRD lifecycle (mode=program only)
|
|
111
|
+
|
|
112
|
+
A Program-PRD's board Status travels a longer arc than a Feature-PRD's:
|
|
113
|
+
|
|
114
|
+
- **spec role** — set here, at the mode=program write (§4's board sync, same as any Draft-PRD).
|
|
115
|
+
- **in-progress role** — flipped by `to-issues`, at the **first** wave-stub promotion under this PRD (not by to-prd itself; a re-run of to-prd on an already-in-progress Program-PRD leaves the status untouched).
|
|
116
|
+
- **done role** — set **manually**, by the maintainer, at the program's last Phasen-Gate. `closes` **never** targets a Program-PRD (same close-protection contract as any Welle-Anchor, `to-waves` §8) — it is closed last, by hand, once every wave/stub/leaf under it is done (or, on an abort, closed per the Abbruch-Konvention in `PROGRAM-PRD-FORMAT.md`).
|
|
117
|
+
|
|
118
|
+
<prd-template>
|
|
119
|
+
|
|
120
|
+
## Problem Statement
|
|
121
|
+
|
|
122
|
+
The problem that the user is facing, from the user's perspective.
|
|
123
|
+
|
|
124
|
+
## Solution
|
|
125
|
+
|
|
126
|
+
The solution to the problem, from the user's perspective.
|
|
127
|
+
|
|
128
|
+
## User Stories
|
|
129
|
+
|
|
130
|
+
A LONG, numbered list of user stories. **Write each story in the same language as the rest of the PRD** (this project is German-first → German stories; never mix an English scaffold onto German content). Each user story follows the actor/feature/benefit shape:
|
|
131
|
+
|
|
132
|
+
- Deutsch: `Als <Akteur> möchte ich <Funktion>, damit <Nutzen>.`
|
|
133
|
+
- English: `As a(n) <actor>, I want <feature>, so that <benefit>.`
|
|
134
|
+
|
|
135
|
+
<user-story-example lang="de">
|
|
136
|
+
1. Als QA-Lead möchte ich den Testfortschritt je Phase auf einen Blick sehen, damit ich Engpässe früh erkenne.
|
|
137
|
+
</user-story-example>
|
|
138
|
+
<user-story-example lang="en">
|
|
139
|
+
1. As a mobile bank customer, I want to see balance on my accounts, so that I can make better informed decisions about my spending.
|
|
140
|
+
</user-story-example>
|
|
141
|
+
|
|
142
|
+
This list of user stories should be extremely extensive and cover all aspects of the feature.
|
|
143
|
+
|
|
144
|
+
## Implementation Decisions
|
|
145
|
+
|
|
146
|
+
A list of implementation decisions that were made. This can include:
|
|
147
|
+
|
|
148
|
+
- The modules that will be built/modified
|
|
149
|
+
- The interfaces of those modules that will be modified
|
|
150
|
+
- Technical clarifications from the developer
|
|
151
|
+
- Architectural decisions
|
|
152
|
+
- Schema changes
|
|
153
|
+
- API contracts
|
|
154
|
+
- Specific interactions
|
|
155
|
+
|
|
156
|
+
Do NOT include specific file paths or code snippets. They may end up being outdated very quickly.
|
|
157
|
+
|
|
158
|
+
Exception: if a prototype produced a snippet that encodes a decision more precisely than prose can (state machine, reducer, schema, type shape), inline it within the relevant decision and note briefly that it came from a prototype. Trim to the decision-rich parts — not a working demo, just the important bits.
|
|
159
|
+
|
|
160
|
+
## Testing Decisions
|
|
161
|
+
|
|
162
|
+
A list of testing decisions that were made. Include:
|
|
163
|
+
|
|
164
|
+
- A description of what makes a good test (only test external behavior, not implementation details)
|
|
165
|
+
- Which modules will be tested
|
|
166
|
+
- Prior art for the tests (i.e. similar types of tests in the codebase)
|
|
167
|
+
|
|
168
|
+
## Review Notes (findings that do NOT become slices)
|
|
169
|
+
|
|
170
|
+
Findings that are real but **not a buildable item** — e.g. a review-only smell no linter/gate catches (SoC drift in a handler, a style question). Per entry: what + why it's not a slice. These carry the gate tag 📝; `to-issues` does **not** cut them into a slice. Fixed opportunistically at the next touch, not tracked. (Boundary: a buildable finding belongs in Implementation Decisions; an open decision/research question belongs in `## Open Questions`.)
|
|
171
|
+
|
|
172
|
+
## Out of Scope
|
|
173
|
+
|
|
174
|
+
A description of the things that are out of scope for this PRD.
|
|
175
|
+
|
|
176
|
+
## Further Notes
|
|
177
|
+
|
|
178
|
+
Any further notes about the feature.
|
|
179
|
+
|
|
180
|
+
</prd-template>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Third-Party Notices
|
|
2
|
+
|
|
3
|
+
This skill is adapted from **Matt Pocock's skills**
|
|
4
|
+
(https://github.com/mattpocock/skills), `skills/engineering/to-spec` @ d574778, Copyright (c) 2026 Matt Pocock,
|
|
5
|
+
used under the MIT License. Locally adapted (fork-and-own); see PROVENANCE.md.
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
MIT License
|
|
9
|
+
|
|
10
|
+
Copyright (c) 2026 Matt Pocock
|
|
11
|
+
|
|
12
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
13
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
14
|
+
in the Software without restriction, including without limitation the rights
|
|
15
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
16
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
17
|
+
furnished to do so, subject to the following conditions:
|
|
18
|
+
|
|
19
|
+
The above copyright notice and this permission notice shall be included in all
|
|
20
|
+
copies or substantial portions of the Software.
|
|
21
|
+
|
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
23
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
24
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
25
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
26
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
27
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
28
|
+
SOFTWARE.
|
|
29
|
+
```
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: to-waves
|
|
3
|
+
disable-model-invocation: true
|
|
4
|
+
description: "Unfold a Program-PRD's wave plan onto the board — parse + graph-validate it, show the complete Wellenplan as a chat preview before ANY board write, then after approval publish named wave stubs (native parent = the PRD) + slice leaves (native parent = their stub) with Wave and Phase stamped in one batch, and report a counted completion. Idempotent + crash-recoverable on re-run; adopts referenced existing issues instead of duplicating them. Use on a Program-PRD, the native anchor over several waves. NOT for a single-wave feature (to-issues) and NOT for clustering a backlog (board-to-waves)."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# to-waves — Unfold a Program-PRD's wave plan onto the board
|
|
8
|
+
|
|
9
|
+
Takes a **Program-PRD** — the native Sub-Issue anchor over a multi-wave program
|
|
10
|
+
(Programm → Phase → Welle → Slice) — and turns its `## Wellenplan` chapter into
|
|
11
|
+
**named wave stubs + slice leaves** on the board. Pipeline position:
|
|
12
|
+
`scale-check → grill → to-prd (program mode) → to-waves → …per wave: to-issues`.
|
|
13
|
+
The **grill and to-prd sit upstream**; to-waves runs once the Program-PRD exists.
|
|
14
|
+
It **never invents structure** — it only unfolds what the plan already decided.
|
|
15
|
+
|
|
16
|
+
Board constants (project node, field/status IDs) + helpers live **consumer-side**:
|
|
17
|
+
read `docs/agents/board-sync.md` from the project root + use the helper
|
|
18
|
+
`scripts/board-sync.py` (missing → `/setup-workflow` scaffolds the project layer).
|
|
19
|
+
Issue bodies **always** via `--body-file` (inline `--body` with backticks/parens
|
|
20
|
+
crashes bash).
|
|
21
|
+
|
|
22
|
+
The two grammars to-waves consumes: the Program-PRD body grammar
|
|
23
|
+
(`.claude/skills/to-prd/PROGRAM-PRD-FORMAT.md` — the 8-column
|
|
24
|
+
`Welle | Status | Issue | Name | Phase | Slices | Gate | covers` Wellenplan table) and the
|
|
25
|
+
per-slice metadata block (`SLICE-METADATA-FORMAT.md`, next to this file). Read both;
|
|
26
|
+
to-waves does not re-parse them by hand — `scripts/program_graph.py` (via the helper)
|
|
27
|
+
is the parser.
|
|
28
|
+
|
|
29
|
+
## 1. Input — a Program-PRD
|
|
30
|
+
|
|
31
|
+
The target is a Program-PRD issue: it carries the `<!-- prd: program -->` marker (or
|
|
32
|
+
the program-type label) and a `## Wellenplan` table. Passed in / from context. If the
|
|
33
|
+
issue is a plain feature-PRD or a Welle-Anchor, stop — a feature-PRD is `to-issues`'
|
|
34
|
+
target, an anchor is already a single wave.
|
|
35
|
+
|
|
36
|
+
## 2. Parse + validate — the graph preflight
|
|
37
|
+
|
|
38
|
+
Run the graph preflight first — it is **read-only** (a single board read, zero
|
|
39
|
+
mutations):
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
python3 scripts/board-sync.py validate-graph --issue <prd#>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
It parses the Wellenplan table + the per-slice metadata blocks and reports the
|
|
46
|
+
counted Programm-Graph findings: cycles and backward refs across wave boundaries
|
|
47
|
+
(blocking), a Gate-Slice with dependents outside its own wave (a non-blocking
|
|
48
|
+
"Struktur-Verdacht" warning), capacity preflight (the 100-children-per-parent
|
|
49
|
+
GitHub limit), the phase-option preflight, revision coherence, and **both
|
|
50
|
+
completeness axes counted** — vertical Rollup-Kette (every leaf → one wave, every
|
|
51
|
+
wave → ≥1 slice + outcome gate + phase where used) and horizontal Scope-Abdeckung
|
|
52
|
+
(every Scope-Item covered by ≥1 wave; every wave covers ≥1 Scope-Item or is an
|
|
53
|
+
explicit `enabler`). The command exits non-zero when a **blocking** finding exists.
|
|
54
|
+
|
|
55
|
+
**A blocking finding stops the run — do not publish a broken graph.** Report it and
|
|
56
|
+
send the fix back to the PRD (a structural fix is an escalation, see §8).
|
|
57
|
+
|
|
58
|
+
## 3. Preview gate — before ANY board write
|
|
59
|
+
|
|
60
|
+
This is a **hard stop**. Show the whole plan in chat and get explicit approval
|
|
61
|
+
**before the first write**. Because nothing has been written yet, **a rejection
|
|
62
|
+
costs nothing** — the board is never left half-built.
|
|
63
|
+
|
|
64
|
+
Show:
|
|
65
|
+
|
|
66
|
+
- The **complete Wellenplan table**, one row per wave: number, name, phase, the
|
|
67
|
+
slices with their bucket (AFK/HITL) + Gate tag, and each wave's dependencies.
|
|
68
|
+
- The **counted graph result** from `validate-graph` verbatim (Scope-Abdeckung
|
|
69
|
+
`X von Y`, Rollup-Kette ✓/gaps, any warnings).
|
|
70
|
+
- The **publish plan**: how many stubs + leaves will be created, which referenced
|
|
71
|
+
existing issues will be **adopted** (§4) rather than created, and which
|
|
72
|
+
Wave/Phase stamps will be applied.
|
|
73
|
+
|
|
74
|
+
Then ask for approval. Only on an explicit "yes" proceed to §4/§5. On "no", stop —
|
|
75
|
+
no writes happened.
|
|
76
|
+
|
|
77
|
+
## 4. Publish — the fixed order
|
|
78
|
+
|
|
79
|
+
After approval, publish in **exactly this order** (issue CREATES stay sequential so
|
|
80
|
+
the numbering is deterministic; only the field stamps are batched):
|
|
81
|
+
|
|
82
|
+
1. **Wave stubs — Stufe 1p.** One per Wellenplan row, native parent = the PRD.
|
|
83
|
+
Title `Welle <N> — <Name>`; created with the `wave-stub` label and Status Spec.
|
|
84
|
+
Body = the Stufe-1p stub template (named header, the program idempotency marker,
|
|
85
|
+
the revision marker — see §6). Not yet Wave/Phase-stamped (that is step 4).
|
|
86
|
+
```bash
|
|
87
|
+
python3 scripts/board-sync.py create --title "Welle <N> — <Name>" \
|
|
88
|
+
--body-file <stub.md> --wave-stub --status-role spec
|
|
89
|
+
```
|
|
90
|
+
2. **Slice leaves.** One per slice under each wave, native parent = its stub. Created
|
|
91
|
+
with the spec-role status and **no** `ready-for-agent` (a leaf is not buildable until its
|
|
92
|
+
wave is promoted — the ordering guard stays unambiguous). Body = the slice's
|
|
93
|
+
`## Slices` section carried forward per `SLICE-METADATA-FORMAT.md` (metadata block +
|
|
94
|
+
the outcome/placeholder skeleton, sharpened only at promotion). **Title carries the
|
|
95
|
+
navigation prefix** `Welle <N> / Slice <local-id> — <title>` — the local-id
|
|
96
|
+
(`1a`, `1b`, …) encodes the build order, so the sub-issue LIST is navigable by title
|
|
97
|
+
alone (same convention as `to-issues`' promoted children, `Welle N / Slice X — <outcome>`).
|
|
98
|
+
```bash
|
|
99
|
+
python3 scripts/board-sync.py create --title "Welle <N> / Slice <local-id> — <slice title>" --body-file <leaf.md> --status-role spec
|
|
100
|
+
```
|
|
101
|
+
3. **Sub-issue links.** Link each stub under the PRD and each leaf under its stub.
|
|
102
|
+
`link` is one-parent-checked + idempotent (a foreign parent is reported, never
|
|
103
|
+
silently re-parented) — which is exactly what makes the re-run in §5 safe.
|
|
104
|
+
```bash
|
|
105
|
+
python3 scripts/board-sync.py link --parent <prd#> --child <stub#>
|
|
106
|
+
python3 scripts/board-sync.py link --parent <stub#> --child <leaf#>
|
|
107
|
+
```
|
|
108
|
+
**Blocking edges — native.** For every leaf whose metadata `blocked_by` names
|
|
109
|
+
sibling slices (local-ids now resolved to issue numbers), set the edge natively —
|
|
110
|
+
native issue dependencies are the blocking SSOT; the helper also writes the
|
|
111
|
+
`## Blocked by` body mirror (idempotent, safe under the §5 re-run):
|
|
112
|
+
```bash
|
|
113
|
+
python3 scripts/board-sync.py dep-add --issue <blocked-leaf#> --blocked-by <blocker-leaf#>
|
|
114
|
+
```
|
|
115
|
+
4. **Batch-stamp Wave + Phase.** One `stamp-batch` over every stub and leaf. It
|
|
116
|
+
consumes a JSON list of `{issue, item_id, wave, phase}`; assemble it by resolving
|
|
117
|
+
each freshly-created issue's board **item id** from the project item list (the
|
|
118
|
+
same read the helper's `next-wave` performs — `gh project item-list <n> --owner
|
|
119
|
+
<owner> --limit 2000 --format json` (no `--limit` defaults to 30 — a silent
|
|
120
|
+
truncation dead-end on a real board), matching `content.number` → item `id`).
|
|
121
|
+
Missing `phase` in the profile is **skipped visibly**, never dropped silently.
|
|
122
|
+
```bash
|
|
123
|
+
python3 scripts/board-sync.py stamp-batch --items-file <stamps.json>
|
|
124
|
+
```
|
|
125
|
+
The counted line `N von M Feld-Stempel gesetzt` is the verification — there is no
|
|
126
|
+
extra read-back pass. Any failed alias prints an idempotent single-item repair
|
|
127
|
+
(`stamp-batch --issue … --item-id … --wave …`); re-run it, a field-set is idempotent.
|
|
128
|
+
5. **Wellenplan back-link sync.** Run `program-sync` once so the PRD's Wellenplan
|
|
129
|
+
`Issue` column links each freshly created stub (`#<stub#>`, matched via the
|
|
130
|
+
`Welle <N> —` title —; idempotent, fills-never-overwrites):
|
|
131
|
+
```bash
|
|
132
|
+
python3 scripts/board-sync.py program-sync <prd#>
|
|
133
|
+
```
|
|
134
|
+
6. **Counted completion report + program view link.** Report `X von Y` for each part
|
|
135
|
+
(stubs created, leaves created, issues adopted, field stamps set) and link the
|
|
136
|
+
program board view. Completeness is **counted, never claimed** — the numbers come
|
|
137
|
+
from the create outputs + the `stamp-batch` response, not from memory.
|
|
138
|
+
|
|
139
|
+
## 5. Adopt path — referenced existing issues
|
|
140
|
+
|
|
141
|
+
If a Wellenplan row references an **existing** issue (`#n`, e.g. one produced by
|
|
142
|
+
bottom-up backlog grooming), that issue is **ADOPTED**, not re-created — otherwise a
|
|
143
|
+
bottom-up → program transition rains duplicates. Adoption:
|
|
144
|
+
|
|
145
|
+
- **Board-sync + strip the buildable labels** in one call. `--bucket hitl` strips
|
|
146
|
+
`ready-for-agent` and `wave-stub` (a leaf is not buildable until its wave is
|
|
147
|
+
promoted) while the **body is kept** as the source content:
|
|
148
|
+
```bash
|
|
149
|
+
python3 scripts/board-sync.py add --issue <n> --status-role spec --bucket hitl
|
|
150
|
+
```
|
|
151
|
+
- **Re-parent under the stub** with `link` (one-parent-checked — a foreign parent is
|
|
152
|
+
reported, not overwritten). Resolve a reported conflict by hand: unlink the old
|
|
153
|
+
parent first — `python3 scripts/board-sync.py unlink --parent <old#> --child <n>`
|
|
154
|
+
— then re-run `link` under the intended stub.
|
|
155
|
+
- **Include it in the §4 batch-stamp** so it gets the same Wave/Phase as a fresh leaf.
|
|
156
|
+
|
|
157
|
+
Adoption normalizes workflow labels **immediately** (the strip above) so the
|
|
158
|
+
ordering guard stays clean; it never touches the issue's body.
|
|
159
|
+
|
|
160
|
+
## 6. Idempotent re-run + revision coherence
|
|
161
|
+
|
|
162
|
+
A re-run of to-waves on the same program is **delta-apply** and doubles as
|
|
163
|
+
**crash-recovery** for a publish that was interrupted mid-way.
|
|
164
|
+
|
|
165
|
+
- **Idempotency markers.** Every stub carries a stable
|
|
166
|
+
`<!-- program-stub-source: <prd-source-id>/w<N> -->` and every leaf a
|
|
167
|
+
`<!-- program-leaf-source: <prd-source-id>/<local-id> -->` (same spirit as the
|
|
168
|
+
bottom-up `wave-stub-source` marker; `<prd-source-id>` is the PRD's own source
|
|
169
|
+
slug). These never change across revisions — they are the identity for
|
|
170
|
+
search-before-create.
|
|
171
|
+
- **Delta apply.** Filter existing issues locally by their source marker
|
|
172
|
+
(`gh issue list --json number,body` + a local filter, no reliance on GitHub search —
|
|
173
|
+
it does not index HTML comments). For each planned stub/leaf: **match** → update in
|
|
174
|
+
place (never duplicate); **missing** → create; a live issue carrying a
|
|
175
|
+
`program-*-source` for this program that the current plan no longer references →
|
|
176
|
+
report as **orphaned** (do not auto-close — closing is the abort convention, §8).
|
|
177
|
+
Cross-check the native children (`children-of <prd#>` and each stub) against the
|
|
178
|
+
plan so both origins are covered.
|
|
179
|
+
- **Crash recovery.** Because create is search-before-create, `link` is idempotent,
|
|
180
|
+
and `stamp-batch` field-sets are idempotent, re-running the whole publish after an
|
|
181
|
+
abort resumes cleanly — already-created issues match, missing ones are created,
|
|
182
|
+
links/stamps re-apply harmlessly.
|
|
183
|
+
- **Revision coherence.** to-waves stamps `<!-- program-revision: rN -->` on every
|
|
184
|
+
stub. `validate-graph` checks this marker against the PRD's
|
|
185
|
+
current `plan_revision` — a **stale** stub (the wave plan was revised since) blocks
|
|
186
|
+
**loudly** instead of silently building from an old shape. On a plan-revision bump
|
|
187
|
+
(the escalation path, §8), the delta re-run **renews the `program-revision` marker
|
|
188
|
+
of every still-living stub that would otherwise fail the current PRD check** — read
|
|
189
|
+
this broadly: every stub whose marker is behind, not only the textually changed
|
|
190
|
+
rows. The renewal is a body edit via `gh issue edit <stub#> --body-file <updated>`
|
|
191
|
+
(the same sanctioned body-write `to-prd` Mode B uses). The mechanism that renews
|
|
192
|
+
coherence is the same one the revision broke — it self-repairs.
|
|
193
|
+
|
|
194
|
+
## 7. Program-grill agenda + the per-wave-start content pass
|
|
195
|
+
|
|
196
|
+
to-waves also carries the **program-grill agenda** as a reference chapter — the
|
|
197
|
+
checklist a program grill (upstream) should cover so the wave plan does not rest on
|
|
198
|
+
open switches:
|
|
199
|
+
|
|
200
|
+
- **Scope → Phases.** Break the outcome into phases (optional) and the Scope-Items
|
|
201
|
+
(stable IDs) each phase serves.
|
|
202
|
+
- **Gates from DoDs, in outcome language.** Every phase/wave gate is an
|
|
203
|
+
acceptance criterion phrased as a user-visible outcome, not a task.
|
|
204
|
+
- **Wave cut.** Each wave is an outcome slice (a tracer), never a layer slice — a
|
|
205
|
+
"backend wave" is an anti-pattern; an enabler wave names the half it cuts off and
|
|
206
|
+
the outcome wave that closes it.
|
|
207
|
+
- **Metadata.** Wave numbers, phases, covers-IDs, gate tags filled per the two
|
|
208
|
+
grammars.
|
|
209
|
+
- **Structure-bearing decisions are grill work, never a plan work-item.** A decision
|
|
210
|
+
that changes where a boundary falls is resolved **at the grill** — escalate a
|
|
211
|
+
single bounded choice to `decision-gate` — not deferred into the plan as an open
|
|
212
|
+
task.
|
|
213
|
+
|
|
214
|
+
**The per-wave-start content pass** is where slice content is sharpened — deliberately
|
|
215
|
+
**just-in-time (Late Binding)**, never ex ante on spec. When a wave is promoted:
|
|
216
|
+
`to-prd` (Mode B, into the wave stub) + `spec-self-critique` are **mandatory**, and
|
|
217
|
+
the depth ladder is **raised for a high-stakes wave** (a design-grill or a
|
|
218
|
+
`decision-gate` before slicing). This is what folds in any drift propagated since the
|
|
219
|
+
plan was first written.
|
|
220
|
+
|
|
221
|
+
## 8. Close protection, abort convention, escalation path
|
|
222
|
+
|
|
223
|
+
- **Never `closes` the Program-PRD or a wave anchor.** A slice PR uses `Part of
|
|
224
|
+
#<anchor>`; `closes` only ever targets a leaf. The PRD is closed **last, manually**,
|
|
225
|
+
when the program is done — never auto-closed by a PR.
|
|
226
|
+
- **Abort convention.** To abandon a program cleanly (no board zombies): close
|
|
227
|
+
**leaves first** (`superseded by program abort`), then their **stubs**, then the
|
|
228
|
+
**Program-PRD** last, manually — the order documented in the PROGRAM-PRD-FORMAT
|
|
229
|
+
Abbruch-Konvention.
|
|
230
|
+
- **Escalation path.** When a gate result flips the structure (a wave needs to
|
|
231
|
+
split/merge/reorder), **STOP** — do not patch it in a build slice. Revise the
|
|
232
|
+
Wellenplan **at the PRD** with the maintainer, **bump `plan_revision`**, and re-run
|
|
233
|
+
to-waves as a **delta** (which renews the `program-revision` markers per §6).
|
|
234
|
+
Append-only drift notes (to future stubs/leaves + the PRD) do **not** bump
|
|
235
|
+
`plan_revision`; only a structural wave-plan change does.
|
|
236
|
+
|
|
237
|
+
## 9. Live dashboard — program-sync
|
|
238
|
+
|
|
239
|
+
Between wave events the PRD's Wellenplan **Status** + **Issue** columns are
|
|
240
|
+
regenerated from the board (monotone, idempotent — Status never regresses, Issue
|
|
241
|
+
fills but never overwrites; hand-owned Name/Plan cells survive verbatim), and
|
|
242
|
+
mechanically completed **Phasen-Gates** are checked off (all waves of a phase ✅ →
|
|
243
|
+
`[x]` with an `— alle Wellen ✅ (<date>)` stamp). `wrapup` triggers the same
|
|
244
|
+
sync automatically on every slice merge whose wave anchor has a program parent
|
|
245
|
+
(upward propagation — the program table shows the event, not only the wave):
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
python3 scripts/board-sync.py program-sync <prd#> --dry-run # preview the diff first
|
|
249
|
+
python3 scripts/board-sync.py program-sync <prd#>
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## Audit block (visible output)
|
|
253
|
+
|
|
254
|
+
```
|
|
255
|
+
to-waves: prd=#<n> preview=<approved|rejected>
|
|
256
|
+
created=<stubs X von Y, leaves X von Y> adopted=<#a #b … | none>
|
|
257
|
+
stamped=<N von M Wave/Phase> phase=<stamped | skipped (profile lacks fields.phase)>
|
|
258
|
+
revision=r<N> renewed-markers=<count | none> orphaned=<#… | none>
|
|
259
|
+
graph=<ok | blocking: …> program-view=<url>
|
|
260
|
+
```
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# SLICE-METADATA-FORMAT — per-slice metadata block
|
|
2
|
+
|
|
3
|
+
The metadata block a **planned slice** carries inside a Program-PRD's
|
|
4
|
+
`## Slices` chapter (see `.claude/skills/to-prd/PROGRAM-PRD-FORMAT.md`), and the
|
|
5
|
+
same fields carried forward onto the real Slice **leaf issue** once `to-waves`
|
|
6
|
+
publishes it. Parsed pre-publish by `scripts/program_graph.py`
|
|
7
|
+
for `validate-graph`; the same grammar is what a published leaf keeps so drift
|
|
8
|
+
tooling (adopt-path, program-sync) reads one consistent shape whether the slice
|
|
9
|
+
is still a PRD sub-section or already a real GitHub issue.
|
|
10
|
+
|
|
11
|
+
## The five fields — grep-bare HTML comments
|
|
12
|
+
|
|
13
|
+
One fact per line, consistent with the existing `final-cut-depends-on`
|
|
14
|
+
convention (`scripts/execute-ready-check.py`'s marker table) — plain HTML
|
|
15
|
+
comments, never folded into prose, so a script can `grep`/regex them without
|
|
16
|
+
parsing Markdown semantics:
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
<!-- wave: 1 -->
|
|
20
|
+
<!-- phase: P1 -->
|
|
21
|
+
<!-- area: scripts -->
|
|
22
|
+
<!-- gate: — -->
|
|
23
|
+
<!-- blocked_by: none -->
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
| Field | Value | Meaning |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| `wave` | integer | The Welle number (from the Wellenplan's `Welle` column) this slice belongs to. |
|
|
29
|
+
| `phase` | a Phase id (`P1`, …) or `—` | Omit/`—` when the program doesn't use phases. |
|
|
30
|
+
| `area` | free text (e.g. `scripts`, `frontend`, `backend`) | A short human hint about where the slice lands — not machine-checked, purely orientation. |
|
|
31
|
+
| `gate` | `—` \| `🧭` \| `🔬` \| `📐` \| `📝` | Same Gate-Legende as `wave-anchor-template.md`. `—` = AFK-buildable; the other four mark a Gate-Slice (read-only, blocks its dependent build-slice). |
|
|
32
|
+
| `blocked_by` | `none` or comma-separated **local-ids** | Other slices (by local-id, e.g. `1a`, `2c`) that must land first. `none` (not an empty string) when there is no dependency. |
|
|
33
|
+
|
|
34
|
+
**Never add a sixth field without updating this file first** — `program_graph.py`'s
|
|
35
|
+
parser only recognizes exactly these five keys; an unrecognized field is silently
|
|
36
|
+
ignored (forward-compatible for prose additions), but a mistyped one of these
|
|
37
|
+
five (e.g. `blocks_by`) breaks that slice's graph edges invisibly.
|
|
38
|
+
|
|
39
|
+
## Local-id convention
|
|
40
|
+
|
|
41
|
+
The local-id (`1a`, `1b`, `2a`, …) is the slice's identity **before** it becomes
|
|
42
|
+
a real GitHub issue — `<wave-number><letter>`, letters assigned in the order the
|
|
43
|
+
slice appears under its wave. It is how the Wellenplan table's `Slices` column,
|
|
44
|
+
other slices' `blocked_by`, and this slice's own heading
|
|
45
|
+
(`#### 1a — <Title>`) all refer to the same slice unambiguously pre-publish.
|
|
46
|
+
Once `to-waves` publishes the slice as a real issue, the local-id is superseded
|
|
47
|
+
by the issue number everywhere `final-cut-depends-on`-style cross-references are
|
|
48
|
+
used — but the metadata block's five fields keep the same shape (only `wave` and
|
|
49
|
+
`phase` typically survive verbatim; `blocked_by` gets rewritten to `#<n>`
|
|
50
|
+
references by the publish step **and set as native issue-dependency edges**
|
|
51
|
+
(`dep-add`) — the blocking SSOT; the leaf's `## Blocked by` body section is
|
|
52
|
+
their machine-written mirror).
|
|
53
|
+
|
|
54
|
+
## Body skeleton
|
|
55
|
+
|
|
56
|
+
Below the metadata block, every slice section carries the same three-part
|
|
57
|
+
skeleton — filled in loosely during `to-waves`' planning pass, **finalized**
|
|
58
|
+
(sharpened into a full What-to-build + AC, matching a leaf issue's usual shape)
|
|
59
|
+
only at promotion time, same "Late Binding" principle as the rest of the
|
|
60
|
+
program-route mechanics (content quality is deliberately just-in-time, not
|
|
61
|
+
ex ante):
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
Outcome: <one sentence — the user-visible or structural result this slice delivers>
|
|
65
|
+
|
|
66
|
+
What to build: <placeholder — sharpened at promotion>
|
|
67
|
+
|
|
68
|
+
AC: <placeholder — sharpened at promotion>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
A slice section that still carries bare placeholders is normal *before*
|
|
72
|
+
promotion — `validate-graph`'s structural axes don't require sharpened prose,
|
|
73
|
+
only the five metadata fields and a resolvable heading. Content sharpening is a
|
|
74
|
+
`to-waves` promotion-time concern, not a `validate-graph` concern.
|