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.
- package/.agents/agents/acceptance-critic.md +129 -0
- package/.agents/agents/retro.md +42 -0
- package/.agents/agents/story-worker.md +162 -0
- package/.agents/docs/configuration.md +7 -1
- package/.agents/docs/execution-reference.md +27 -2
- package/.agents/instructions.md +43 -33
- package/.agents/personas/engineer.md +26 -112
- package/.agents/personas/security-engineer.md +1 -2
- package/.agents/rules/git-conventions-reference.md +225 -0
- package/.agents/rules/git-conventions.md +25 -200
- package/.agents/rules/security-baseline.md +5 -0
- package/.agents/rules/testing-standards.md +106 -13
- package/.agents/schemas/agentrc.schema.json +31 -1
- package/.agents/schemas/lifecycle/slice.end.schema.json +21 -0
- package/.agents/schemas/lifecycle/slice.heartbeat.schema.json +20 -0
- package/.agents/schemas/lifecycle/slice.start.schema.json +17 -0
- package/.agents/scripts/acceptance-eval.js +62 -18
- package/.agents/scripts/agents-bootstrap-github.js +1 -1
- package/.agents/scripts/bookkeeping-reconcile.js +117 -0
- package/.agents/scripts/check-context-budget.js +62 -5
- package/.agents/scripts/diagnose-friction.js +0 -6
- package/.agents/scripts/epic-deliver-prepare.js +272 -10
- package/.agents/scripts/lib/bootstrap/project-bootstrap.js +56 -18
- package/.agents/scripts/lib/close-validation/gates.js +159 -21
- package/.agents/scripts/lib/config/acceptance-eval.js +52 -5
- package/.agents/scripts/lib/config/delivery-routing.js +87 -0
- package/.agents/scripts/lib/config/explain.js +2 -0
- package/.agents/scripts/lib/config-resolver.js +1 -1
- package/.agents/scripts/lib/config-settings-schema-delivery.js +37 -3
- package/.agents/scripts/lib/config-settings-schema-quality.js +9 -0
- package/.agents/scripts/lib/doc-tiers.js +37 -2
- package/.agents/scripts/lib/observability/active-story-env.js +111 -2
- package/.agents/scripts/lib/observability/hook-heartbeat.js +219 -0
- package/.agents/scripts/lib/observability/tool-trace-hook.js +15 -4
- package/.agents/scripts/lib/orchestration/acceptance-clusters.js +111 -0
- package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +32 -4
- package/.agents/scripts/lib/orchestration/bookkeeping-outbox.js +270 -0
- package/.agents/scripts/lib/orchestration/ceremony-routing.js +141 -0
- package/.agents/scripts/lib/orchestration/context-hydration-engine.js +3 -124
- package/.agents/scripts/lib/orchestration/deliver-route.js +173 -0
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/authoring-context.js +1 -1
- package/.agents/scripts/lib/orchestration/epic-run-state-store.js +233 -0
- package/.agents/scripts/lib/orchestration/file-assumptions.js +68 -7
- package/.agents/scripts/lib/orchestration/lifecycle/emit-slice-lifecycle.js +270 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +83 -2
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/checkpoint-pointer-writer.js +6 -0
- package/.agents/scripts/lib/orchestration/plan-context.js +189 -3
- package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +3 -2
- package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +99 -0
- package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +38 -1
- package/.agents/scripts/lib/orchestration/plan-persist/summary.js +16 -1
- package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +1 -0
- package/.agents/scripts/lib/orchestration/story-close/pre-merge-validation.js +1 -0
- package/.agents/scripts/lib/orchestration/ticket-validator.js +19 -2
- package/.agents/scripts/lib/provider-factory.js +1 -1
- package/.agents/scripts/lib/templates/decomposer-prompts.js +1 -1
- package/.agents/scripts/plan-context.js +28 -10
- package/.agents/scripts/post-structured-comment.js +38 -0
- package/.agents/scripts/slice-phase.js +361 -0
- package/.agents/scripts/sync-claude-agents.js +165 -0
- package/.agents/scripts/update-ticket-state.js +31 -0
- package/.agents/scripts/wave-tick.js +138 -9
- package/.agents/skills/core/api-and-interface-design/SKILL.md +5 -3
- package/.agents/skills/core/code-review-and-quality/SKILL.md +63 -7
- package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +1 -1
- package/.agents/skills/core/epic-plan-consolidate/SKILL.md +5 -5
- package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +8 -8
- package/.agents/skills/core/epic-plan-premortem/SKILL.md +4 -4
- package/.agents/skills/core/epic-plan-spec-author/SKILL.md +26 -56
- package/.agents/skills/core/gates-and-baselines/SKILL.md +149 -0
- package/.agents/skills/core/idea-refinement/SKILL.md +2 -8
- package/.agents/skills/core/qa-coverage-mapping/SKILL.md +7 -7
- package/.agents/skills/skills.index.json +11 -381
- package/.agents/workflows/deliver.md +47 -4
- package/.agents/workflows/helpers/acceptance-self-eval.md +38 -13
- package/.agents/workflows/helpers/deliver-epic-reference.md +18 -5
- package/.agents/workflows/helpers/deliver-epic-single.md +331 -0
- package/.agents/workflows/helpers/deliver-epic.md +51 -8
- package/.agents/workflows/helpers/deliver-stories.md +15 -5
- package/.agents/workflows/helpers/epic-deliver-story.md +12 -3
- package/.agents/workflows/helpers/mandrel-sync-config.md +1 -1
- package/.agents/workflows/helpers/plan-epic-reference.md +19 -8
- package/.agents/workflows/helpers/plan-epic.md +95 -27
- package/.agents/workflows/helpers/scope-triage-gate.md +9 -0
- package/.agents/workflows/mandrel-update.md +1 -1
- package/.agents/workflows/plan.md +16 -4
- package/docs/CHANGELOG.md +23 -0
- package/lib/cli/registry.js +95 -0
- package/package.json +4 -2
- package/.agents/personas/engineer-mobile.md +0 -120
- package/.agents/personas/engineer-web.md +0 -111
- package/.agents/personas/product.md +0 -94
- package/.agents/personas/refactorer.md +0 -113
- package/.agents/personas/sre.md +0 -86
- package/.agents/personas/ux-designer.md +0 -95
- package/.agents/scripts/epic-plan-decompose.js +0 -54
- package/.agents/scripts/epic-plan-spec.js +0 -64
- package/.agents/scripts/lib/orchestration/skill-capsule-loader.js +0 -109
- package/.agents/scripts/plan-critics.js +0 -227
- package/.agents/skills/core/baseline-refresh/SKILL.md +0 -181
- package/.agents/skills/core/ci-cd-and-automation/SKILL.md +0 -274
- package/.agents/skills/core/ci-cd-and-automation/examples.md +0 -211
- package/.agents/skills/core/code-simplification/SKILL.md +0 -389
- package/.agents/skills/core/context-engineering/SKILL.md +0 -309
- package/.agents/skills/core/context-engineering/examples.md +0 -58
- package/.agents/skills/core/deprecation-and-migration/SKILL.md +0 -250
- package/.agents/skills/core/frontend-ui-engineering/SKILL.md +0 -357
- package/.agents/skills/core/hydrate-context/SKILL.md +0 -123
- package/.agents/skills/core/idea-refinement/examples.md +0 -437
- package/.agents/skills/core/idea-refinement/frameworks.md +0 -135
- package/.agents/skills/core/incremental-implementation/SKILL.md +0 -271
- package/.agents/skills/core/introducing-a-baseline-gate/SKILL.md +0 -213
- package/.agents/skills/core/knowledge-transfer/SKILL.md +0 -180
- package/.agents/skills/core/mutation-survivor-remediation/SKILL.md +0 -117
- package/.agents/skills/core/performance-optimization/SKILL.md +0 -314
- package/.agents/skills/core/planning-and-task-breakdown/SKILL.md +0 -277
- package/.agents/skills/core/property-based-testing/SKILL.md +0 -148
- package/.agents/skills/core/refactoring-discipline/SKILL.md +0 -111
- package/.agents/skills/core/shipping-and-launch/SKILL.md +0 -328
- package/.agents/skills/core/spec-driven-development/SKILL.md +0 -252
- package/.agents/skills/core/test-driven-development/SKILL.md +0 -475
- package/.agents/skills/core/using-agent-skills/SKILL.md +0 -232
- package/.agents/skills/stack/architecture/monorepo-path-strategist/SKILL.md +0 -31
- package/.agents/skills/stack/architecture/structured-output-zod/SKILL.md +0 -51
- package/.agents/skills/stack/architecture/subagent-orchestration/SKILL.md +0 -76
- package/.agents/skills/stack/backend/cloudflare-hono-architect/SKILL.md +0 -31
- package/.agents/skills/stack/backend/cloudflare-hono-architect/examples/route-template.ts +0 -33
- package/.agents/skills/stack/backend/cloudflare-queue-manager/SKILL.md +0 -31
- package/.agents/skills/stack/backend/cloudflare-workers/SKILL.md +0 -51
- package/.agents/skills/stack/backend/highlevel-crm/SKILL.md +0 -54
- package/.agents/skills/stack/backend/sqlite-drizzle-expert/SKILL.md +0 -29
- package/.agents/skills/stack/backend/sqlite-drizzle-expert/examples/schema-template.ts +0 -30
- package/.agents/skills/stack/backend/stripe-integration/SKILL.md +0 -57
- package/.agents/skills/stack/backend/stripe-integration/scripts/listen-stripe.sh +0 -9
- package/.agents/skills/stack/backend/turso-sqlite/SKILL.md +0 -48
- package/.agents/skills/stack/frontend/astro/SKILL.md +0 -62
- package/.agents/skills/stack/frontend/astro-react-island-strategist/SKILL.md +0 -30
- package/.agents/skills/stack/frontend/expo-react-native-developer/SKILL.md +0 -29
- package/.agents/skills/stack/frontend/google-analytics-v4/SKILL.md +0 -50
- package/.agents/skills/stack/frontend/tailwind-v4/SKILL.md +0 -58
- package/.agents/skills/stack/frontend/ui-accessibility-engineer/SKILL.md +0 -34
- package/.agents/skills/stack/qa/audit-accessibility/SKILL.md +0 -51
- package/.agents/skills/stack/qa/lighthouse-baseline/SKILL.md +0 -199
- package/.agents/skills/stack/security/backend-security-patterns/SKILL.md +0 -68
|
@@ -1,119 +1,33 @@
|
|
|
1
|
-
# Role:
|
|
1
|
+
# Role: Software Engineer (default)
|
|
2
2
|
|
|
3
|
-
|
|
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
|
-
|
|
6
|
-
|
|
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
|
-
|
|
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**
|
|
60
|
-
|
|
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,
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
- **The latitude
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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`.
|
|
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
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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` —
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
-
|
|
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
|
|