mandrel 1.92.0 → 1.94.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.
Files changed (144) hide show
  1. package/.agents/agents/acceptance-critic.md +129 -0
  2. package/.agents/agents/retro.md +42 -0
  3. package/.agents/agents/story-worker.md +162 -0
  4. package/.agents/docs/configuration.md +7 -1
  5. package/.agents/docs/execution-reference.md +27 -2
  6. package/.agents/instructions.md +43 -33
  7. package/.agents/personas/engineer.md +26 -112
  8. package/.agents/personas/security-engineer.md +1 -2
  9. package/.agents/rules/git-conventions-reference.md +225 -0
  10. package/.agents/rules/git-conventions.md +25 -200
  11. package/.agents/rules/security-baseline.md +5 -0
  12. package/.agents/rules/testing-standards.md +106 -13
  13. package/.agents/schemas/agentrc.schema.json +31 -1
  14. package/.agents/schemas/lifecycle/slice.end.schema.json +21 -0
  15. package/.agents/schemas/lifecycle/slice.heartbeat.schema.json +20 -0
  16. package/.agents/schemas/lifecycle/slice.start.schema.json +17 -0
  17. package/.agents/scripts/acceptance-eval.js +62 -18
  18. package/.agents/scripts/agents-bootstrap-github.js +1 -1
  19. package/.agents/scripts/bookkeeping-reconcile.js +117 -0
  20. package/.agents/scripts/check-context-budget.js +62 -5
  21. package/.agents/scripts/diagnose-friction.js +0 -6
  22. package/.agents/scripts/epic-deliver-prepare.js +272 -10
  23. package/.agents/scripts/lib/bootstrap/project-bootstrap.js +56 -18
  24. package/.agents/scripts/lib/close-validation/gates.js +159 -21
  25. package/.agents/scripts/lib/config/acceptance-eval.js +52 -5
  26. package/.agents/scripts/lib/config/delivery-routing.js +87 -0
  27. package/.agents/scripts/lib/config/explain.js +2 -0
  28. package/.agents/scripts/lib/config-resolver.js +1 -1
  29. package/.agents/scripts/lib/config-settings-schema-delivery.js +37 -3
  30. package/.agents/scripts/lib/config-settings-schema-quality.js +9 -0
  31. package/.agents/scripts/lib/doc-tiers.js +37 -2
  32. package/.agents/scripts/lib/observability/active-story-env.js +111 -2
  33. package/.agents/scripts/lib/observability/hook-heartbeat.js +219 -0
  34. package/.agents/scripts/lib/observability/tool-trace-hook.js +15 -4
  35. package/.agents/scripts/lib/orchestration/acceptance-clusters.js +111 -0
  36. package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +32 -4
  37. package/.agents/scripts/lib/orchestration/bookkeeping-outbox.js +270 -0
  38. package/.agents/scripts/lib/orchestration/ceremony-routing.js +141 -0
  39. package/.agents/scripts/lib/orchestration/context-hydration-engine.js +3 -124
  40. package/.agents/scripts/lib/orchestration/deliver-route.js +173 -0
  41. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/authoring-context.js +1 -1
  42. package/.agents/scripts/lib/orchestration/epic-run-state-store.js +233 -0
  43. package/.agents/scripts/lib/orchestration/file-assumptions.js +68 -7
  44. package/.agents/scripts/lib/orchestration/lifecycle/emit-slice-lifecycle.js +270 -0
  45. package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +83 -2
  46. package/.agents/scripts/lib/orchestration/lifecycle/listeners/checkpoint-pointer-writer.js +6 -0
  47. package/.agents/scripts/lib/orchestration/plan-context.js +189 -3
  48. package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +3 -2
  49. package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +99 -0
  50. package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +38 -1
  51. package/.agents/scripts/lib/orchestration/plan-persist/summary.js +16 -1
  52. package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +1 -0
  53. package/.agents/scripts/lib/orchestration/story-close/pre-merge-validation.js +1 -0
  54. package/.agents/scripts/lib/orchestration/ticket-validator.js +19 -2
  55. package/.agents/scripts/lib/provider-factory.js +1 -1
  56. package/.agents/scripts/lib/templates/decomposer-prompts.js +1 -1
  57. package/.agents/scripts/plan-context.js +28 -10
  58. package/.agents/scripts/post-structured-comment.js +38 -0
  59. package/.agents/scripts/slice-phase.js +361 -0
  60. package/.agents/scripts/sync-claude-agents.js +165 -0
  61. package/.agents/scripts/update-ticket-state.js +31 -0
  62. package/.agents/scripts/wave-tick.js +138 -9
  63. package/.agents/skills/core/api-and-interface-design/SKILL.md +5 -3
  64. package/.agents/skills/core/code-review-and-quality/SKILL.md +63 -7
  65. package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +1 -1
  66. package/.agents/skills/core/epic-plan-consolidate/SKILL.md +5 -5
  67. package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +8 -8
  68. package/.agents/skills/core/epic-plan-premortem/SKILL.md +4 -4
  69. package/.agents/skills/core/epic-plan-spec-author/SKILL.md +26 -56
  70. package/.agents/skills/core/gates-and-baselines/SKILL.md +149 -0
  71. package/.agents/skills/core/idea-refinement/SKILL.md +2 -8
  72. package/.agents/skills/core/qa-coverage-mapping/SKILL.md +7 -7
  73. package/.agents/skills/skills.index.json +11 -381
  74. package/.agents/workflows/deliver.md +47 -4
  75. package/.agents/workflows/helpers/acceptance-self-eval.md +38 -13
  76. package/.agents/workflows/helpers/deliver-epic-reference.md +18 -5
  77. package/.agents/workflows/helpers/deliver-epic-single.md +331 -0
  78. package/.agents/workflows/helpers/deliver-epic.md +51 -8
  79. package/.agents/workflows/helpers/deliver-stories.md +15 -5
  80. package/.agents/workflows/helpers/epic-deliver-story.md +12 -3
  81. package/.agents/workflows/helpers/mandrel-sync-config.md +1 -1
  82. package/.agents/workflows/helpers/plan-epic-reference.md +19 -8
  83. package/.agents/workflows/helpers/plan-epic.md +95 -27
  84. package/.agents/workflows/helpers/scope-triage-gate.md +9 -0
  85. package/.agents/workflows/mandrel-update.md +1 -1
  86. package/.agents/workflows/plan.md +16 -4
  87. package/docs/CHANGELOG.md +23 -0
  88. package/lib/cli/registry.js +95 -0
  89. package/package.json +4 -2
  90. package/.agents/personas/engineer-mobile.md +0 -120
  91. package/.agents/personas/engineer-web.md +0 -111
  92. package/.agents/personas/product.md +0 -94
  93. package/.agents/personas/refactorer.md +0 -113
  94. package/.agents/personas/sre.md +0 -86
  95. package/.agents/personas/ux-designer.md +0 -95
  96. package/.agents/scripts/epic-plan-decompose.js +0 -54
  97. package/.agents/scripts/epic-plan-spec.js +0 -64
  98. package/.agents/scripts/lib/orchestration/skill-capsule-loader.js +0 -109
  99. package/.agents/scripts/plan-critics.js +0 -227
  100. package/.agents/skills/core/baseline-refresh/SKILL.md +0 -181
  101. package/.agents/skills/core/ci-cd-and-automation/SKILL.md +0 -274
  102. package/.agents/skills/core/ci-cd-and-automation/examples.md +0 -211
  103. package/.agents/skills/core/code-simplification/SKILL.md +0 -389
  104. package/.agents/skills/core/context-engineering/SKILL.md +0 -309
  105. package/.agents/skills/core/context-engineering/examples.md +0 -58
  106. package/.agents/skills/core/deprecation-and-migration/SKILL.md +0 -250
  107. package/.agents/skills/core/frontend-ui-engineering/SKILL.md +0 -357
  108. package/.agents/skills/core/hydrate-context/SKILL.md +0 -123
  109. package/.agents/skills/core/idea-refinement/examples.md +0 -437
  110. package/.agents/skills/core/idea-refinement/frameworks.md +0 -135
  111. package/.agents/skills/core/incremental-implementation/SKILL.md +0 -271
  112. package/.agents/skills/core/introducing-a-baseline-gate/SKILL.md +0 -213
  113. package/.agents/skills/core/knowledge-transfer/SKILL.md +0 -180
  114. package/.agents/skills/core/mutation-survivor-remediation/SKILL.md +0 -117
  115. package/.agents/skills/core/performance-optimization/SKILL.md +0 -314
  116. package/.agents/skills/core/planning-and-task-breakdown/SKILL.md +0 -277
  117. package/.agents/skills/core/property-based-testing/SKILL.md +0 -148
  118. package/.agents/skills/core/refactoring-discipline/SKILL.md +0 -111
  119. package/.agents/skills/core/shipping-and-launch/SKILL.md +0 -328
  120. package/.agents/skills/core/spec-driven-development/SKILL.md +0 -252
  121. package/.agents/skills/core/test-driven-development/SKILL.md +0 -475
  122. package/.agents/skills/core/using-agent-skills/SKILL.md +0 -232
  123. package/.agents/skills/stack/architecture/monorepo-path-strategist/SKILL.md +0 -31
  124. package/.agents/skills/stack/architecture/structured-output-zod/SKILL.md +0 -51
  125. package/.agents/skills/stack/architecture/subagent-orchestration/SKILL.md +0 -76
  126. package/.agents/skills/stack/backend/cloudflare-hono-architect/SKILL.md +0 -31
  127. package/.agents/skills/stack/backend/cloudflare-hono-architect/examples/route-template.ts +0 -33
  128. package/.agents/skills/stack/backend/cloudflare-queue-manager/SKILL.md +0 -31
  129. package/.agents/skills/stack/backend/cloudflare-workers/SKILL.md +0 -51
  130. package/.agents/skills/stack/backend/highlevel-crm/SKILL.md +0 -54
  131. package/.agents/skills/stack/backend/sqlite-drizzle-expert/SKILL.md +0 -29
  132. package/.agents/skills/stack/backend/sqlite-drizzle-expert/examples/schema-template.ts +0 -30
  133. package/.agents/skills/stack/backend/stripe-integration/SKILL.md +0 -57
  134. package/.agents/skills/stack/backend/stripe-integration/scripts/listen-stripe.sh +0 -9
  135. package/.agents/skills/stack/backend/turso-sqlite/SKILL.md +0 -48
  136. package/.agents/skills/stack/frontend/astro/SKILL.md +0 -62
  137. package/.agents/skills/stack/frontend/astro-react-island-strategist/SKILL.md +0 -30
  138. package/.agents/skills/stack/frontend/expo-react-native-developer/SKILL.md +0 -29
  139. package/.agents/skills/stack/frontend/google-analytics-v4/SKILL.md +0 -50
  140. package/.agents/skills/stack/frontend/tailwind-v4/SKILL.md +0 -58
  141. package/.agents/skills/stack/frontend/ui-accessibility-engineer/SKILL.md +0 -34
  142. package/.agents/skills/stack/qa/audit-accessibility/SKILL.md +0 -51
  143. package/.agents/skills/stack/qa/lighthouse-baseline/SKILL.md +0 -199
  144. package/.agents/skills/stack/security/backend-security-patterns/SKILL.md +0 -68
@@ -1,119 +1,33 @@
1
- # Role: Senior Software Engineer (General)
1
+ # Role: Software Engineer (default)
2
2
 
3
- ## 1. Primary Objective
3
+ You are the builder. You turn a Story's binding contract into clean, tested,
4
+ type-safe code. This is the default persona; it covers backend, shared
5
+ libraries, and cross-cutting work.
4
6
 
5
- You are the builder. Your goal is to write clean, efficient, and bulletproof
6
- code that executes the plans designed by the Architect. You value **type
7
- safety**, **testability**, and **readability**.
7
+ **Golden rule:** never guess. When the Story's acceptance is silent on a
8
+ business rule, stop and ask rather than invent one.
8
9
 
9
- **Golden Rule:** Never guess. If a requirement is missing from the Architect's
10
- plan, stop and ask. Do not invent business logic.
11
-
12
- > **Note:** For platform-specific frontend work, prefer the dedicated
13
- > `engineer-web.md` or `engineer-mobile.md` personas. This general persona is
14
- > best suited for backend implementation, shared libraries, and cross-cutting
15
- > concerns that are not scoped to a single platform.
16
-
17
- ## 2. Interaction Protocol
18
-
19
- 1. **Read Context:** Before writing a single line, read the parent Epic
20
- body — the single planning document, including its `## User Stories`
21
- section and the folded Tech Spec sections (`## Delivery Slicing`
22
- onward; Story #4324 retired the separate Tech Spec ticket) — plus the
23
- docs digest (digest-first with pull-on-demand; see
24
- [`.agents/instructions.md` § 3](../instructions.md) — there is no
25
- read-every-`project.docsContextFiles`-file mandate).
26
- 2. **Workspace Awareness:** Identify if you are working in a monorepo or a
27
- standard repo. Ensure all commands (installing packages, running scripts) are
28
- executed in the correct workspace/directory. Check `package.json` or the
29
- workspace root configuration to determine the correct scope.
30
- 3. **Implementation:** Write the code in small, logical chunks (atomic steps).
31
- 4. **Verification:** Immediately write/run a test or verification script to
32
- ensure the code works.
33
- 5. **Cleanup:** Remove debug logs and comments that only explain _what_ code
34
- does (keep comments that explain _why_).
35
-
36
- ## 3. Coding Standards
37
-
38
- ### A. Type Safety & Validation
39
-
40
- - **Strict Typing:** Always utilize the strictest settings of the project's
41
- language (e.g., `strict: true` in TypeScript). Avoid `any` or untyped
42
- variables.
43
- - **Interfaces:** Export interfaces/types for all props and data models.
44
- - **Validation:** Use the project's established schema validation library for
45
- all API inputs and external data parsing.
46
-
47
- ### B. Function Design
48
-
49
- - **Single Responsibility:** A function should do one thing. If it's too long,
50
- refactor.
51
- - **Pure Functions:** Prefer pure functions (output depends only on input) to
52
- make testing easier.
53
- - **Early Returns:** Use guard clauses to handle errors early and reduce
54
- nesting.
55
-
56
- ### C. Implementation Latitude (Logged Deviation)
10
+ ## Implementation Latitude (logged deviation)
57
11
 
58
12
  A Story's `changes[]` and `references[]` are an **advisory implementation
59
- sketch** the author's best prediction of the file footprint, not a binding
60
- instruction. Its `acceptance[]` and `verify[]` arrays are the **binding
61
- contract** and the only definition of "done."
13
+ sketch** of the file footprint. Its `acceptance[]` and `verify[]` arrays are the
14
+ **binding contract** and the only definition of done.
62
15
 
63
16
  - **You MAY deviate from the suggested approach** when the real codebase
64
- diverges from the sketch — touch a different file, choose a different
65
- internal seam, fold or split the predicted edits — **provided you record
66
- the rationale**. Note the deviation and the reason in your commit body (or
67
- the Story's progress comment), e.g. `the sketched helper already exists in
68
- lib/x.js, so I extended it rather than creating lib/y.js`. This converts
69
- silent drift into a logged signal a reviewer can audit.
70
- - **The latitude is bounded and never overrides the inviolable layer.** It
71
- applies to the **implementation approach only**. It does **not** license
72
- deviating from `acceptance[]` / `verify[]` (you MUST still satisfy every
73
- acceptance item and run every verify command to green), and it does **not**
74
- license relaxing any `rules/security-baseline.md` MUST or any other
75
- inviolable rule. When in doubt, the binding contract and the security
76
- baseline win — per the precedence ordering in
77
- [`.agents/instructions.md` § 1.K](../instructions.md).
78
- - **Unlogged deviation is the anti-pattern.** Reshaping the footprint without
79
- recording why is the silent drift this latitude exists to surface. If you
80
- cannot state the reason in a sentence, re-examine whether the deviation is
81
- warranted.
82
-
83
- ## 4. Testing & Verification
84
-
85
- 1. **Test-Driven:** Write tests for utilities, logic helpers, and API routes
86
- using the project's configured testing framework.
87
- 2. **Self-Correction:** If you run a command and it fails, **read the error**,
88
- analyze it, and fix it automatically.
89
- 3. **Verification Before Done:** Never mark a task complete without proving it
90
- works.
91
-
92
- ## 5. File Management & Safety
93
-
94
- - **Filename Comment:** Always start code blocks with the file path (e.g.,
95
- `// src/lib/utils.ts`).
96
- - **Create/Edit:** You are authorized to create new files and edit existing
97
- ones.
98
- - **Delete:** **NEVER** delete a file without explicit user confirmation.
99
- - **Imports:** Respect the project's import alias conventions (e.g.,
100
- `@/components/`).
101
-
102
- ## 6. Scope Boundaries
103
-
104
- **This persona does NOT:**
105
-
106
- - Design system architecture or write technical specifications.
107
- - Write PRDs, user stories, or make product scoping decisions.
108
- - Design UX flows, component states, or visual hierarchy.
109
- - Manage CI/CD pipelines, infrastructure, or deployment configuration.
110
- - Write or execute E2E test plans (use `qa-engineer.md` for that).
111
-
112
- **Automatic Referral Protocol:** If you are asked to perform a task that falls
113
- outside the responsibilities defined in this file, **do not attempt it**.
114
- Instead:
115
-
116
- 1. Briefly state which part of the request is outside your scope.
117
- 2. Read the `.agents/personas/` directory to identify the correct persona.
118
- 3. Automatically adopt that persona's instructions for the out-of-scope portion
119
- of the work and continue execution seamlessly.
17
+ diverges from the sketch — touch a different file, pick a different seam, fold
18
+ or split the predicted edits — **provided you record the rationale** in the
19
+ commit body or the Story's progress comment (e.g. "the sketched helper already
20
+ exists in `lib/x.js`, so I extended it rather than creating `lib/y.js`").
21
+ Logged deviation turns silent drift into a signal a reviewer can audit;
22
+ unlogged reshaping is the anti-pattern this latitude exists to surface.
23
+ - **The latitude applies to the implementation approach only.** It does **not**
24
+ license deviating from `acceptance[]` / `verify[]` (satisfy every item and run
25
+ every verify command to green), and it does **not** license relaxing a
26
+ `rules/security-baseline.md` MUST. When in doubt the binding contract and the
27
+ security baseline win (precedence: `.agents/instructions.md` § 1.K).
28
+
29
+ ## Working rhythm
30
+
31
+ Write in small atomic steps and prove each one with a test before moving on.
32
+ When a command fails, read the error and fix it rather than working around it.
33
+ Never mark a task done without running its `verify[]` commands to green.
@@ -13,8 +13,7 @@ all third-party services will be compromised. Design every system to fail
13
13
  securely.
14
14
 
15
15
  > **Note:** For CI/CD pipeline security gates and secret scanning automation,
16
- > coordinate with `devops-engineer.md`. For production incident response and
17
- > secret rotation, coordinate with `sre.md`.
16
+ > coordinate with `devops-engineer.md`.
18
17
 
19
18
  ## 2. Interaction Protocol
20
19
 
@@ -0,0 +1,225 @@
1
+ # Git Conventions — Reference (on-demand)
2
+
3
+ **This rule applies when** you are reasoning about a git-history mechanic that
4
+ the always-on core [`git-conventions.md`](git-conventions.md) deliberately
5
+ summarizes: authoring a **contract change** (config/schema/lifecycle/label/API
6
+ shape), triaging a **push-hook false-negative**, resolving **shared-checkout
7
+ merge contention**, satisfying the **documentation-freshness gate**, or routing
8
+ a retrospective signal via a **`meta::*` label**. The core carries the
9
+ per-commit MUSTs; this file carries the detail behind them. Nothing here
10
+ relaxes a core MUST — read it when the matching work is in play.
11
+
12
+ ## Contract Cutovers — No Shim Layer
13
+
14
+ Mandrel ships as the `mandrel` npm package, whose consumers pin an
15
+ exact lockfile version; they opt into breaks at upgrade time. Operator policy
16
+ for any contract change (config shape, baseline shape, schema, lifecycle
17
+ payload, ticket label, dispatch artifact, public API of a script) is
18
+ therefore:
19
+
20
+ 1. **Hard cutovers only.** Contract changes ship as a single in-tree
21
+ migration of every producer and consumer. There is no parallel
22
+ old-shape support code, no read-side tolerance branch, and no
23
+ feature flag that toggles between the two shapes.
24
+ 2. **The PR diff IS the migration.** A consumer upgrading to a release
25
+ with the change adopts the new shape by upgrading the
26
+ `mandrel` package (`mandrel update`). The PR that lands on
27
+ `main` already moved every internal call site; consumers move on the
28
+ same beat by upgrading.
29
+ 3. **No deprecation ledger, no version-windowed sunsets.** The framework
30
+ does not track "to be removed in vX.Y" entries or run two shapes side
31
+ by side for a release window. If a shape changes, the old shape is
32
+ deleted in the same PR.
33
+
34
+ The codifying decision is **Epic #2646** (the "Hard-Cutover Cleanup Epic"),
35
+ which deleted the existing compatibility shim layer across
36
+ `config-resolver.js`, `lib/config/*.js`, `lib/baselines/`,
37
+ `wave-session.js`, `IExecutionAdapter` / `ManualDispatchAdapter`, lifecycle
38
+ emit shims, and duplicate progress/comment writers in one pass. The
39
+ per-finding closing references (audit Findings #10, #11, #13, #17) live in
40
+ the merged PRs and the Epic #2646 history; the standing forward-looking
41
+ audit lives at [`docs/roadmap.md`](../../docs/roadmap.md) (Part 1 — Model-Evolution Audit).
42
+
43
+ Practical guidance when authoring a contract change:
44
+
45
+ - If you are tempted to add a "legacy shape" branch in a parser or
46
+ resolver, **don't** — update every call site instead, and delete the
47
+ old shape in the same PR.
48
+ - If you cannot land every call site in a single PR (e.g. a
49
+ cross-repository change), the contract change is too large for one
50
+ hard cutover. Split the contract itself, not the rollout.
51
+ - Schema versions remain useful as **identifiers** (so a future consumer
52
+ can detect "I cannot read this artifact"); they are **not** an
53
+ invitation to keep multiple readers alive in the same release.
54
+
55
+ ## Push Validation — the known false-negative signature
56
+
57
+ The core rule is: **never bypass hooks** (`--no-verify`, `--no-gpg-sign`, or
58
+ other hook-skipping flags) unless the operator explicitly authorizes it, and
59
+ if a hook fails, investigate the underlying cause. One recognized exception
60
+ signature is worth naming:
61
+
62
+ - **Known false-negative signature**: a `pre-push`/`pre-commit` failure
63
+ whose message is a _zero-match_ error (e.g. Biome's
64
+ `No files were processed in the specified paths`) rather than a
65
+ reported violation, combined with an agent CWD under a harness-managed
66
+ worktree path a consumer's lint config ignores (e.g.
67
+ `.claude/worktrees/<name>/` against a `files.includes` glob like
68
+ `"!**/.claude"`), is a **consumer-tooling gap**, not a real lint
69
+ failure. It does not authorize `--no-verify`. See
70
+ [`worktree-lifecycle.md` § Harness-worktree ⇄ consumer-lint-ignore interaction](../workflows/helpers/worktree-lifecycle.md#harness-worktree-consumer-lint-ignore-interaction-story-152)
71
+ for the recognition signature and the sanctioned consumer-side fix
72
+ (`--no-errors-on-unmatched` or equivalent) before escalating via
73
+ `agent::blocked`.
74
+
75
+ ## Local checkout hygiene — full mechanics
76
+
77
+ **Invariant (stated in the core): the delivering flow owns tidying the local
78
+ checkout — reaping its own merged refs and fast-forwarding the base branch.
79
+ `/git-cleanup` is a recovery tool, not a routine chore.** The mechanics behind
80
+ that invariant:
81
+
82
+ Every flow that lands work — `/deliver` (Epic and standalone-Story paths),
83
+ `/git-deliver` — is responsible for leaving the local checkout tidy without
84
+ operator intervention:
85
+
86
+ - **Fast-forwarding the base branch is owned by the flow.** The standalone
87
+ multi-Story path fast-forwards `main` itself in its summary phase (via
88
+ `git-cleanup.js --fast-forward-main --execute --yes`); the Epic path
89
+ fast-forwards `epic/<id>` / `main` on its merge-and-reap beat. No workflow
90
+ ends by telling the operator to "run `/git-cleanup` afterwards to catch up".
91
+ - **Reaping merged local refs is owned by the flow's next boot.** `/plan` and
92
+ `/git-deliver` open with a **protected boot sweep**
93
+ (`boot-sweep.js`) that fast-forwards `main`, prunes stale remote-tracking
94
+ refs, and reaps every local branch whose PR is already merged — skipping any
95
+ candidate with unpushed work, a dirty worktree, or a still-open parent
96
+ ticket. A branch a flow leaves behind (e.g. a `/git-deliver` feature branch
97
+ whose PR merges out of band) is therefore reaped automatically at the next
98
+ workflow boot, not left for the operator to sweep by hand. `boot-sweep.js`
99
+ defaults its `--include` glob to `story-*` — a bare invocation only sweeps
100
+ Story branches; `/plan` and `/git-deliver` widen the scope to their own
101
+ branch namespaces (`epic/*`, `feat/*`, `fix/*`, `chore/*`, `docs/*`,
102
+ `refactor/*`) by passing `--include` explicitly at their boot call site.
103
+ A branch the planner detects only via the weaker content-equivalence
104
+ signal (`detectedBy: 'content-merged'`, Story #4395's
105
+ `git merge-tree --write-tree` probe — content already landed in the base
106
+ branch by another route, such as a squash-merged Epic PR, with no merged
107
+ PR or git ancestry of its own) is **never** reaped by the boot sweep: it
108
+ is report-only, surfaced under `contentMerged` in the result envelope and
109
+ a routing hint in the summary line (Story #4396), so the operator can
110
+ send it to `/git-cleanup` for a confirmed, eyeballed reap.
111
+ - **`/git-cleanup` is recovery, not routine.** Run it by hand only to recover
112
+ an unusual state the automated hygiene does not cover — triaging stashes,
113
+ reaping across non-standard branch namespaces, or `--remote` pruning after a
114
+ force-push diverged a tip. It is **not** the expected way to keep `main`
115
+ current or to clear merged branches after a normal delivery; the delivering
116
+ flows already own that. If you find yourself reaching for `/git-cleanup`
117
+ after every routine `/deliver` or `/git-deliver` run, that is a signal the
118
+ owning flow's hygiene step regressed — fix the flow, do not codify the manual
119
+ sweep.
120
+
121
+ ### Shared-checkout contention (Story #4460)
122
+
123
+ `story-close.js`'s merge phase runs `git checkout <epic-branch>` directly in
124
+ the **shared main repo checkout** (`close-inputs.js` resolves `mainCwd` to
125
+ `PROJECT_ROOT`), not an isolated worktree. `lib/epic-merge-lock.js` guards
126
+ that checkout with a **per-Epic** filesystem lock
127
+ (`epic-<epicId>.merge.lock`) so two `story-close.js` runs for the **same**
128
+ Epic serialize against each other — but nothing stops a **different**
129
+ Epic's concurrently-running `story-close.js` from treating the same shared
130
+ checkout as scratch space at the same time.
131
+
132
+ - **Recognition signature**: a `git checkout`/`git switch` failure during
133
+ the merge phase whose message is `error: Your local changes ... would be
134
+ overwritten by checkout`, where the shared checkout is parked on a
135
+ **different** epic's branch (e.g. `epic/4405`) than the one the current
136
+ `story-close.js` run is trying to merge (e.g. `epic/4425`), with
137
+ uncommitted edits that belong to that other Epic's delivery. This was
138
+ observed live during Epic #4425 delivery (Stories #4427/#4428) colliding
139
+ with a concurrently-running Epic #4405 session, and had to be worked
140
+ around by hand via `git stash push -u`.
141
+ - **The fix — `assertSharedCheckoutAvailable`**
142
+ (`lib/orchestration/story-close/shared-checkout-guard.js`), called from
143
+ `runFinalizeMerge` in `lib/orchestration/story-close/merge-runner.js`
144
+ immediately before the merge-phase `git checkout <epicBranch>`. It
145
+ **composes with, not replaces,** the per-Epic lock:
146
+ - It first checks the shared common `.git/` dir for a **foreign**
147
+ (different-epic) `epic-*.merge.lock` file whose recorded PID is still
148
+ alive (`findForeignActiveEpicLock` in `lib/epic-merge-lock.js`). If
149
+ found, the merge phase fails fast with a diagnostic naming the holding
150
+ epic id, its lock-file path, and its PID/acquired-at timestamp —
151
+ instead of surfacing the raw git checkout error.
152
+ - It then checks whether the shared checkout is simply dirty (via `git
153
+ status --porcelain`), regardless of whose branch is checked out, and
154
+ reports the dirty file list plus the currently-checked-out branch in
155
+ the failure diagnostic.
156
+ - It never inspects the **caller's own** epic-id lock namespace, so
157
+ same-epic concurrent `story-close.js` runs continue to serialize
158
+ solely through `withEpicMergeLock` (the existing per-Epic lock) before
159
+ this guard ever executes — this guard only ever refuses on a truly
160
+ _foreign_ epic's live lock or unrelated dirt.
161
+ - **Not fixed by this guard**: the guard reports the contention early and
162
+ actionably; it does not redesign the merge phase to use an isolated
163
+ worktree, and it does not change `restoreStartingBranch`'s existing
164
+ dirty-tree refusal behavior (`phases/branch-restore.js`) — both remain
165
+ out of scope. Resolution of an actual collision is still manual: wait for
166
+ the other Epic's story-close run to finish, or — only once you have
167
+ independently confirmed that process is no longer running — remove the
168
+ stale lock file and resolve the dirty tree by hand (stash/commit/reset;
169
+ never `git reset --hard` or `git checkout --force`).
170
+
171
+ ## Documentation Freshness Gate
172
+
173
+ The `validate-docs-freshness.js` gate (run during `/deliver`) asks a
174
+ falsifiable question of every doc in `delivery.docsFreshness.paths` +
175
+ `project.docsContextFiles`: **was this doc actually updated for the Epic?**
176
+ A doc passes on either of two conditions, but they are not
177
+ interchangeable:
178
+
179
+ - **Living docs are satisfied by being rewritten, not annotated.** For
180
+ any non-changelog doc (architecture, decisions, README, guides, …) the
181
+ gate passes **only** when an Epic-referencing commit touched the file —
182
+ a commit whose message references `#<epicId>` and changes the doc.
183
+ Rewrite the doc as part of the Epic's work; do not sprinkle `#<epicId>`
184
+ into its prose to satisfy the check. An appended `#<epicId>` annotation
185
+ alone **fails** the gate for these files, and the failure message names
186
+ the file and the rewrite-not-append contract.
187
+ - **`#<epicId>` body annotations pass only for changelog files.** A
188
+ changelog-class file (basename matches `/changelog/i`, e.g.
189
+ `docs/CHANGELOG.md`) may pass on a body annotation, because an appended
190
+ release note keyed to the Epic is the legitimate, expected update there.
191
+ This is the single sanctioned annotation path; every other doc must use
192
+ the rewrite path above.
193
+
194
+ This restriction exists to remove the perverse incentive by which the
195
+ gate would otherwise reward manufacturing fake provenance — appending
196
+ Epic-ID history into living docs purely to clear the check.
197
+
198
+ ## Meta Labels (Retrospective Signal Routing)
199
+
200
+ Two `meta::*` labels route retrospective signals into durable substrates so
201
+ the `/plan` Phase 0 fetcher (see
202
+ [`prior-feedback-fetcher.js`](../scripts/lib/feedback-loop/prior-feedback-fetcher.js))
203
+ can surface open feedback issues to the planner. Both labels live in
204
+ [`label-constants.js`](../scripts/lib/label-constants.js) under the
205
+ `META_LABELS` export — reference them by symbol from scripts rather than
206
+ hard-coding the string.
207
+
208
+ ### `meta::framework-gap`
209
+
210
+ Apply this label to a GitHub issue that surfaces a defect, missing
211
+ capability, or weak ergonomic in the **framework itself** (anything under
212
+ `.agents/` or the dispatcher engine). Typical sources: a retrospective that
213
+ identifies a workflow that does not yet exist, a hook that should fire but
214
+ does not, or a script-level usability problem that should be solved
215
+ upstream rather than worked around in a consumer project.
216
+
217
+ ### `meta::consumer-improvement`
218
+
219
+ Apply this label to a GitHub issue that surfaces an improvement that lives
220
+ in a **consumer project** (workflow tweaks, ergonomic asks, doc polish, or
221
+ project-local automation). The work is scoped to the consumer's
222
+ `.agents/`-driven layer or the consumer's own codebase, not to upstream
223
+ framework changes. Issues that span both axes should carry both labels —
224
+ `fetchPriorFeedback` dedupes by issue number so a dual-labeled issue
225
+ appears exactly once in the planner context.
@@ -1,7 +1,16 @@
1
1
  # Git & Version Control Conventions
2
2
 
3
3
  This rule applies globally to all repository changes to maintain a clean git
4
- history.
4
+ history. It is the **always-on core**: branch shapes, the Conventional-Commit
5
+ subject contract, issue references, and the non-negotiable push/hygiene MUSTs.
6
+
7
+ Deeper mechanics — the hard-cutover contract policy, the push-hook
8
+ false-negative signature, shared-checkout merge contention, the
9
+ documentation-freshness gate, and the `meta::*` retrospective-routing labels —
10
+ live in the on-demand
11
+ [`git-conventions-reference.md`](git-conventions-reference.md). Read that file
12
+ **before** doing the matching work; the core below is sufficient for every
13
+ routine commit, branch, and PR.
5
14
 
6
15
  ## Canonical Branching (v5 Orchestration)
7
16
 
@@ -44,49 +53,6 @@ creation via `story-init.js`; agents commit on the active Story branch only.
44
53
  titles edited in the GitHub UI; author the PR title in conventional form
45
54
  so the squash commit on `main` parses cleanly for release-please.
46
55
 
47
- ## Contract Cutovers — No Shim Layer
48
-
49
- Mandrel ships as the `mandrel` npm package, whose consumers pin an
50
- exact lockfile version; they opt into breaks at upgrade time. Operator policy
51
- for any contract change (config shape, baseline shape, schema, lifecycle
52
- payload, ticket label, dispatch artifact, public API of a script) is
53
- therefore:
54
-
55
- 1. **Hard cutovers only.** Contract changes ship as a single in-tree
56
- migration of every producer and consumer. There is no parallel
57
- old-shape support code, no read-side tolerance branch, and no
58
- feature flag that toggles between the two shapes.
59
- 2. **The PR diff IS the migration.** A consumer upgrading to a release
60
- with the change adopts the new shape by upgrading the
61
- `mandrel` package (`mandrel update`). The PR that lands on
62
- `main` already moved every internal call site; consumers move on the
63
- same beat by upgrading.
64
- 3. **No deprecation ledger, no version-windowed sunsets.** The framework
65
- does not track "to be removed in vX.Y" entries or run two shapes side
66
- by side for a release window. If a shape changes, the old shape is
67
- deleted in the same PR.
68
-
69
- The codifying decision is **Epic #2646** (the "Hard-Cutover Cleanup Epic"),
70
- which deleted the existing compatibility shim layer across
71
- `config-resolver.js`, `lib/config/*.js`, `lib/baselines/`,
72
- `wave-session.js`, `IExecutionAdapter` / `ManualDispatchAdapter`, lifecycle
73
- emit shims, and duplicate progress/comment writers in one pass. The
74
- per-finding closing references (audit Findings #10, #11, #13, #17) live in
75
- the merged PRs and the Epic #2646 history; the standing forward-looking
76
- audit lives at [`docs/roadmap.md`](../../docs/roadmap.md) (Part 1 — Model-Evolution Audit).
77
-
78
- Practical guidance when authoring a contract change:
79
-
80
- - If you are tempted to add a "legacy shape" branch in a parser or
81
- resolver, **don't** — update every call site instead, and delete the
82
- old shape in the same PR.
83
- - If you cannot land every call site in a single PR (e.g. a
84
- cross-repository change), the contract change is too large for one
85
- hard cutover. Split the contract itself, not the rollout.
86
- - Schema versions remain useful as **identifiers** (so a future consumer
87
- can detect "I cannot read this artifact"); they are **not** an
88
- invitation to keep multiple readers alive in the same release.
89
-
90
56
  ## Push Validation & Reliability
91
57
 
92
58
  To prevent "silent" push failures (e.g., hidden by multi-command chains or
@@ -106,19 +72,12 @@ rejected by `pre-push` hooks):
106
72
  contained more than the linting fix.
107
73
  4. **Never bypass hooks**: Do not use `--no-verify`, `--no-gpg-sign`, or
108
74
  other hook-skipping flags unless the operator explicitly authorizes it.
109
- If a hook fails, investigate the underlying cause.
110
- - **Known false-negative signature**: a `pre-push`/`pre-commit` failure
111
- whose message is a _zero-match_ error (e.g. Biome's
112
- `No files were processed in the specified paths`) rather than a
113
- reported violation, combined with an agent CWD under a harness-managed
114
- worktree path a consumer's lint config ignores (e.g.
115
- `.claude/worktrees/<name>/` against a `files.includes` glob like
116
- `"!**/.claude"`), is a **consumer-tooling gap**, not a real lint
117
- failure. It does not authorize `--no-verify`. See
118
- [`worktree-lifecycle.md` § Harness-worktree ⇄ consumer-lint-ignore interaction](../workflows/helpers/worktree-lifecycle.md#harness-worktree-consumer-lint-ignore-interaction-story-152)
119
- for the recognition signature and the sanctioned consumer-side fix
120
- (`--no-errors-on-unmatched` or equivalent) before escalating via
121
- `agent::blocked`.
75
+ If a hook fails, investigate the underlying cause. One recognized
76
+ exception a Biome _zero-match_ failure under a harness-managed
77
+ worktree path the consumer's lint config ignores — is a consumer-tooling
78
+ gap, **not** authorization to skip the hook; its recognition signature
79
+ and sanctioned fix live in
80
+ [`git-conventions-reference.md` § Push Validation](git-conventions-reference.md).
122
81
 
123
82
  ## Local checkout hygiene
124
83
 
@@ -127,149 +86,15 @@ own merged refs and fast-forwarding the base branch. `/git-cleanup` is a
127
86
  recovery tool, not a routine chore.**
128
87
 
129
88
  Every flow that lands work — `/deliver` (Epic and standalone-Story paths),
130
- `/git-deliver` — is responsible for leaving the local checkout tidy without
131
- operator intervention:
132
-
133
- - **Fast-forwarding the base branch is owned by the flow.** The standalone
134
- multi-Story path fast-forwards `main` itself in its summary phase (via
135
- `git-cleanup.js --fast-forward-main --execute --yes`); the Epic path
136
- fast-forwards `epic/<id>` / `main` on its merge-and-reap beat. No workflow
137
- ends by telling the operator to "run `/git-cleanup` afterwards to catch up".
138
- - **Reaping merged local refs is owned by the flow's next boot.** `/plan` and
139
- `/git-deliver` open with a **protected boot sweep**
140
- (`boot-sweep.js`) that fast-forwards `main`, prunes stale remote-tracking
141
- refs, and reaps every local branch whose PR is already merged — skipping any
142
- candidate with unpushed work, a dirty worktree, or a still-open parent
143
- ticket. A branch a flow leaves behind (e.g. a `/git-deliver` feature branch
144
- whose PR merges out of band) is therefore reaped automatically at the next
145
- workflow boot, not left for the operator to sweep by hand. `boot-sweep.js`
146
- defaults its `--include` glob to `story-*` — a bare invocation only sweeps
147
- Story branches; `/plan` and `/git-deliver` widen the scope to their own
148
- branch namespaces (`epic/*`, `feat/*`, `fix/*`, `chore/*`, `docs/*`,
149
- `refactor/*`) by passing `--include` explicitly at their boot call site.
150
- A branch the planner detects only via the weaker content-equivalence
151
- signal (`detectedBy: 'content-merged'`, Story #4395's
152
- `git merge-tree --write-tree` probe — content already landed in the base
153
- branch by another route, such as a squash-merged Epic PR, with no merged
154
- PR or git ancestry of its own) is **never** reaped by the boot sweep: it
155
- is report-only, surfaced under `contentMerged` in the result envelope and
156
- a routing hint in the summary line (Story #4396), so the operator can
157
- send it to `/git-cleanup` for a confirmed, eyeballed reap.
158
- - **`/git-cleanup` is recovery, not routine.** Run it by hand only to recover
159
- an unusual state the automated hygiene does not cover — triaging stashes,
160
- reaping across non-standard branch namespaces, or `--remote` pruning after a
161
- force-push diverged a tip. It is **not** the expected way to keep `main`
162
- current or to clear merged branches after a normal delivery; the delivering
163
- flows already own that. If you find yourself reaching for `/git-cleanup`
164
- after every routine `/deliver` or `/git-deliver` run, that is a signal the
165
- owning flow's hygiene step regressed — fix the flow, do not codify the manual
166
- sweep.
167
-
168
- ### Shared-checkout contention (Story #4460)
169
-
170
- `story-close.js`'s merge phase runs `git checkout <epic-branch>` directly in
171
- the **shared main repo checkout** (`close-inputs.js` resolves `mainCwd` to
172
- `PROJECT_ROOT`), not an isolated worktree. `lib/epic-merge-lock.js` guards
173
- that checkout with a **per-Epic** filesystem lock
174
- (`epic-<epicId>.merge.lock`) so two `story-close.js` runs for the **same**
175
- Epic serialize against each other — but nothing stops a **different**
176
- Epic's concurrently-running `story-close.js` from treating the same shared
177
- checkout as scratch space at the same time.
178
-
179
- - **Recognition signature**: a `git checkout`/`git switch` failure during
180
- the merge phase whose message is `error: Your local changes ... would be
181
- overwritten by checkout`, where the shared checkout is parked on a
182
- **different** epic's branch (e.g. `epic/4405`) than the one the current
183
- `story-close.js` run is trying to merge (e.g. `epic/4425`), with
184
- uncommitted edits that belong to that other Epic's delivery. This was
185
- observed live during Epic #4425 delivery (Stories #4427/#4428) colliding
186
- with a concurrently-running Epic #4405 session, and had to be worked
187
- around by hand via `git stash push -u`.
188
- - **The fix — `assertSharedCheckoutAvailable`**
189
- (`lib/orchestration/story-close/shared-checkout-guard.js`), called from
190
- `runFinalizeMerge` in `lib/orchestration/story-close/merge-runner.js`
191
- immediately before the merge-phase `git checkout <epicBranch>`. It
192
- **composes with, not replaces,** the per-Epic lock:
193
- - It first checks the shared common `.git/` dir for a **foreign**
194
- (different-epic) `epic-*.merge.lock` file whose recorded PID is still
195
- alive (`findForeignActiveEpicLock` in `lib/epic-merge-lock.js`). If
196
- found, the merge phase fails fast with a diagnostic naming the holding
197
- epic id, its lock-file path, and its PID/acquired-at timestamp —
198
- instead of surfacing the raw git checkout error.
199
- - It then checks whether the shared checkout is simply dirty (via `git
200
- status --porcelain`), regardless of whose branch is checked out, and
201
- reports the dirty file list plus the currently-checked-out branch in
202
- the failure diagnostic.
203
- - It never inspects the **caller's own** epic-id lock namespace, so
204
- same-epic concurrent `story-close.js` runs continue to serialize
205
- solely through `withEpicMergeLock` (the existing per-Epic lock) before
206
- this guard ever executes — this guard only ever refuses on a truly
207
- _foreign_ epic's live lock or unrelated dirt.
208
- - **Not fixed by this guard**: the guard reports the contention early and
209
- actionably; it does not redesign the merge phase to use an isolated
210
- worktree, and it does not change `restoreStartingBranch`'s existing
211
- dirty-tree refusal behavior (`phases/branch-restore.js`) — both remain
212
- out of scope. Resolution of an actual collision is still manual: wait for
213
- the other Epic's story-close run to finish, or — only once you have
214
- independently confirmed that process is no longer running — remove the
215
- stale lock file and resolve the dirty tree by hand (stash/commit/reset;
216
- never `git reset --hard` or `git checkout --force`).
217
-
218
- ## Documentation Freshness Gate
219
-
220
- The `validate-docs-freshness.js` gate (run during `/deliver`) asks a
221
- falsifiable question of every doc in `delivery.docsFreshness.paths` +
222
- `project.docsContextFiles`: **was this doc actually updated for the Epic?**
223
- A doc passes on either of two conditions, but they are not
224
- interchangeable:
225
-
226
- - **Living docs are satisfied by being rewritten, not annotated.** For
227
- any non-changelog doc (architecture, decisions, README, guides, …) the
228
- gate passes **only** when an Epic-referencing commit touched the file —
229
- a commit whose message references `#<epicId>` and changes the doc.
230
- Rewrite the doc as part of the Epic's work; do not sprinkle `#<epicId>`
231
- into its prose to satisfy the check. An appended `#<epicId>` annotation
232
- alone **fails** the gate for these files, and the failure message names
233
- the file and the rewrite-not-append contract.
234
- - **`#<epicId>` body annotations pass only for changelog files.** A
235
- changelog-class file (basename matches `/changelog/i`, e.g.
236
- `docs/CHANGELOG.md`) may pass on a body annotation, because an appended
237
- release note keyed to the Epic is the legitimate, expected update there.
238
- This is the single sanctioned annotation path; every other doc must use
239
- the rewrite path above.
240
-
241
- This restriction exists to remove the perverse incentive by which the
242
- gate would otherwise reward manufacturing fake provenance — appending
243
- Epic-ID history into living docs purely to clear the check.
244
-
245
- ## Meta Labels (Retrospective Signal Routing)
246
-
247
- Two `meta::*` labels route retrospective signals into durable substrates so
248
- the `/plan` Phase 0 fetcher (see
249
- [`prior-feedback-fetcher.js`](../scripts/lib/feedback-loop/prior-feedback-fetcher.js))
250
- can surface open feedback issues to the planner. Both labels live in
251
- [`label-constants.js`](../scripts/lib/label-constants.js) under the
252
- `META_LABELS` export — reference them by symbol from scripts rather than
253
- hard-coding the string.
254
-
255
- ### `meta::framework-gap`
256
-
257
- Apply this label to a GitHub issue that surfaces a defect, missing
258
- capability, or weak ergonomic in the **framework itself** (anything under
259
- `.agents/` or the dispatcher engine). Typical sources: a retrospective that
260
- identifies a workflow that does not yet exist, a hook that should fire but
261
- does not, or a script-level usability problem that should be solved
262
- upstream rather than worked around in a consumer project.
263
-
264
- ### `meta::consumer-improvement`
265
-
266
- Apply this label to a GitHub issue that surfaces an improvement that lives
267
- in a **consumer project** (workflow tweaks, ergonomic asks, doc polish, or
268
- project-local automation). The work is scoped to the consumer's
269
- `.agents/`-driven layer or the consumer's own codebase, not to upstream
270
- framework changes. Issues that span both axes should carry both labels —
271
- `fetchPriorFeedback` dedupes by issue number so a dual-labeled issue
272
- appears exactly once in the planner context.
89
+ `/git-deliver` — leaves the local checkout tidy without operator
90
+ intervention: it fast-forwards the base branch itself, and reaps its own
91
+ merged local refs on the next workflow boot (the `boot-sweep.js` protected
92
+ sweep). Do **not** end a workflow by telling the operator to run
93
+ `/git-cleanup` to catch up; `/git-cleanup` is for recovering an unusual state
94
+ the automated hygiene does not cover. The boot-sweep scope rules, the
95
+ content-merged report-only case, and the shared-checkout merge-contention
96
+ guard are detailed in
97
+ [`git-conventions-reference.md` § Local checkout hygiene](git-conventions-reference.md).
273
98
 
274
99
  ## Pull Requests
275
100