mandrel 1.88.0 → 1.89.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/README.md +18 -13
- package/.agents/audit-checklists/architecture.md +24 -0
- package/.agents/audit-checklists/clean-code.md +24 -0
- package/.agents/audit-checklists/dependencies.md +14 -0
- package/.agents/audit-checklists/devops.md +17 -0
- package/.agents/audit-checklists/documentation.md +22 -0
- package/.agents/audit-checklists/lighthouse.md +15 -0
- package/.agents/audit-checklists/navigability.md +14 -0
- package/.agents/audit-checklists/performance.md +22 -0
- package/.agents/audit-checklists/privacy.md +21 -0
- package/.agents/audit-checklists/quality.md +18 -0
- package/.agents/audit-checklists/security.md +22 -0
- package/.agents/audit-checklists/seo.md +16 -0
- package/.agents/audit-checklists/sre.md +24 -0
- package/.agents/audit-checklists/ux-ui.md +21 -0
- package/.agents/docs/SDLC.md +62 -27
- package/.agents/docs/configuration.md +4 -4
- package/.agents/instructions.md +51 -21
- package/.agents/personas/architect.md +10 -7
- package/.agents/personas/engineer.md +4 -3
- package/.agents/personas/project-manager.md +5 -2
- package/.agents/personas/refactorer.md +5 -3
- package/.agents/rules/git-conventions.md +77 -0
- package/.agents/schemas/agentrc.schema.json +6 -6
- package/.agents/schemas/audit-rules.json +16 -2
- package/.agents/schemas/audit-rules.schema.json +7 -6
- package/.agents/schemas/lifecycle/merge.unlanded.schema.json +38 -0
- package/.agents/schemas/signal-event.schema.json +28 -13
- package/.agents/scripts/acceptance-spec-reconciler.js +6 -4
- package/.agents/scripts/check-context-budget.js +320 -0
- package/.agents/scripts/diagnose-friction.js +4 -4
- package/.agents/scripts/epic-audit-prepare.js +30 -2
- package/.agents/scripts/epic-audit-recheck.js +46 -13
- package/.agents/scripts/epic-deliver-prepare.js +80 -8
- package/.agents/scripts/epic-plan-spec.js +4 -8
- package/.agents/scripts/generate-lens-checklists.js +180 -0
- package/.agents/scripts/lib/audit-suite/checklist-threading.js +300 -0
- package/.agents/scripts/lib/audit-suite/findings.js +27 -0
- package/.agents/scripts/lib/audit-suite/index.js +9 -0
- package/.agents/scripts/lib/audit-suite/lens-checklist.js +212 -0
- package/.agents/scripts/lib/audit-suite/selector.js +136 -5
- package/.agents/scripts/lib/checks/loop-health.js +340 -0
- package/.agents/scripts/lib/cli-args.js +8 -0
- package/.agents/scripts/lib/config/runners.js +13 -5
- package/.agents/scripts/lib/config/temp-paths.js +24 -0
- package/.agents/scripts/lib/config-settings-schema-delivery.js +21 -8
- package/.agents/scripts/lib/doc-tiers.js +291 -0
- package/.agents/scripts/lib/epic-body-sections.js +5 -2
- package/.agents/scripts/lib/epic-merge-lock.js +83 -0
- package/.agents/scripts/lib/epic-plan-clarity.js +3 -1
- package/.agents/scripts/lib/feedback-loop/audit-results-graduator.js +47 -15
- package/.agents/scripts/lib/feedback-loop/graduator-core.js +395 -86
- package/.agents/scripts/lib/feedback-loop/memory-freshness.js +299 -72
- package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +438 -0
- package/.agents/scripts/lib/gates/friction.js +15 -5
- package/.agents/scripts/lib/observability/perf-aggregator.js +30 -104
- package/.agents/scripts/lib/observability/perf-report-readers.js +1 -1
- package/.agents/scripts/lib/observability/signal-validator.js +204 -0
- package/.agents/scripts/lib/observability/signals-writer.js +157 -54
- package/.agents/scripts/lib/observability/tool-trace-hook.js +42 -4
- package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +1 -1
- package/.agents/scripts/lib/orchestration/code-review.js +74 -4
- package/.agents/scripts/lib/orchestration/consolidation-precondition.js +213 -0
- package/.agents/scripts/lib/orchestration/doc-reader.js +4 -96
- package/.agents/scripts/lib/orchestration/docs-digest.js +34 -0
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/authoring-context.js +56 -19
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +22 -0
- package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-unlanded.js +188 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +6 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +69 -8
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +11 -2
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +47 -61
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +39 -3
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/label-transitioner.js +144 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/merge-watcher.js +258 -14
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +6 -0
- package/.agents/scripts/lib/orchestration/merge-block-class.js +218 -0
- package/.agents/scripts/lib/orchestration/plan-review-routing.js +1 -1
- package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +3 -3
- package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +63 -34
- package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +167 -52
- package/.agents/scripts/lib/orchestration/retro/phases/post-and-mirror.js +49 -2
- package/.agents/scripts/lib/orchestration/retro-proposals.js +12 -55
- package/.agents/scripts/lib/orchestration/retro-runner.js +9 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +8 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +419 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +35 -2
- package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +353 -69
- package/.agents/scripts/lib/orchestration/single-story-close/runner.js +66 -4
- package/.agents/scripts/lib/orchestration/spec-section-validator.js +60 -9
- package/.agents/scripts/lib/orchestration/story-close/auto-refresh-runner.js +7 -5
- package/.agents/scripts/lib/orchestration/story-close/merge-runner.js +24 -2
- package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +167 -8
- package/.agents/scripts/lib/orchestration/story-close/shared-checkout-guard.js +163 -0
- package/.agents/scripts/lib/orchestration/ticketing/reads.js +20 -9
- package/.agents/scripts/lib/planning-corpus.js +306 -0
- package/.agents/scripts/lib/signals/detectors/common.js +10 -10
- package/.agents/scripts/lib/signals/detectors/index.js +4 -4
- package/.agents/scripts/lib/signals/detectors/retry.js +19 -18
- package/.agents/scripts/lib/signals/detectors/rework.js +1 -1
- package/.agents/scripts/lib/signals/schema.js +56 -81
- package/.agents/scripts/lib/signals/span-tree.js +6 -5
- package/.agents/scripts/lib/story-plan.js +3 -0
- package/.agents/scripts/lib/wave-runner/tick.js +10 -2
- package/.agents/scripts/lifecycle-emit.js +39 -8
- package/.agents/scripts/providers/github/issues.js +12 -1
- package/.agents/scripts/resolve-doc-tiers.js +83 -0
- package/.agents/scripts/retro-run.js +51 -0
- package/.agents/scripts/signals-view.js +1 -1
- package/.agents/scripts/single-story-close.js +20 -1
- package/.agents/scripts/standalone-feedback-rollup.js +188 -0
- package/.agents/scripts/story-close.js +48 -0
- package/.agents/scripts/story-plan.js +51 -12
- package/.agents/scripts/validate-docs-freshness.js +69 -15
- package/.agents/skills/core/documentation-and-adrs/SKILL.md +58 -0
- package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +5 -3
- package/.agents/skills/core/epic-plan-spec-author/SKILL.md +20 -7
- package/.agents/skills/core/scope-triage/SKILL.md +61 -0
- package/.agents/skills/skills.index.json +3 -3
- package/.agents/workflows/audit-documentation.md +82 -2
- package/.agents/workflows/helpers/code-review.md +116 -43
- package/.agents/workflows/helpers/deliver-epic.md +123 -54
- package/.agents/workflows/helpers/deliver-stories.md +26 -0
- package/.agents/workflows/helpers/epic-audit.md +116 -366
- package/.agents/workflows/helpers/epic-deliver-story.md +14 -0
- package/.agents/workflows/helpers/epic-plan-decompose.md +18 -200
- package/.agents/workflows/helpers/epic-plan-spec.md +18 -180
- package/.agents/workflows/helpers/plan-epic.md +141 -105
- package/.agents/workflows/helpers/plan-story.md +32 -0
- package/.agents/workflows/helpers/single-story-deliver.md +43 -0
- package/.agents/workflows/loops/nightly-audit.md +9 -7
- package/docs/CHANGELOG.md +22 -0
- package/lib/cli/doctor.js +44 -0
- package/package.json +4 -3
- package/.agents/scripts/epic-plan-spec-validate.js +0 -111
- package/.agents/scripts/lib/feedback-loop/code-review-graduator.js +0 -224
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/prompts.js +0 -58
- package/.agents/scripts/lib/signals/detectors/hotspot.js +0 -292
|
@@ -17,10 +17,12 @@ Before permitting any code generation, you must enforce this workflow:
|
|
|
17
17
|
1. **Interrogate Context:** Read the Epic body — including its `## User
|
|
18
18
|
Stories` section and the folded Tech Spec sections (`## Delivery
|
|
19
19
|
Slicing` onward; Story #4324 retired the separate Tech Spec ticket) —
|
|
20
|
-
plus
|
|
21
|
-
`
|
|
22
|
-
`
|
|
23
|
-
|
|
20
|
+
plus the project's docs digest (digest-first with pull-on-demand for
|
|
21
|
+
`architecture.md`, `data-dictionary.md`, and the rest of
|
|
22
|
+
`project.docsContextFiles`; see
|
|
23
|
+
[`.agents/instructions.md` § 3](../instructions.md) — there is no
|
|
24
|
+
read-every-file mandate). Ask clarifying questions about scale, budget,
|
|
25
|
+
or edge cases.
|
|
24
26
|
2. **Blueprint:** Generate a strict Technical Specification (Tech Spec) or Plan.
|
|
25
27
|
3. **Validate:** Explicitly verify that your proposed changes do not violate
|
|
26
28
|
existing database constraints or architectural boundaries.
|
|
@@ -54,9 +56,10 @@ Before permitting any code generation, you must enforce this workflow:
|
|
|
54
56
|
|
|
55
57
|
- **Friction Analysis:** During the retro phase (Phase 5 of
|
|
56
58
|
`/deliver`, driven by `lib/orchestration/retro-runner.js`), you
|
|
57
|
-
MUST analyze the
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
MUST analyze the aggregated friction signals — the `kind: friction`
|
|
60
|
+
records on the per-Epic/per-Story `signals.ndjson` streams, rolled up by
|
|
61
|
+
the retro's perf-aggregator — to identify systemic bottlenecks, repetitive
|
|
62
|
+
tool failures, or prompt ambiguities.
|
|
60
63
|
- **Actionable Optimization:** You are responsible for generating "agent-ready"
|
|
61
64
|
recommendations. These must be formatted as specific markdown instructions or
|
|
62
65
|
skill snippets that can be immediately reviewed and applied to
|
|
@@ -19,9 +19,10 @@ plan, stop and ask. Do not invent business logic.
|
|
|
19
19
|
1. **Read Context:** Before writing a single line, read the parent Epic
|
|
20
20
|
body — the single planning document, including its `## User Stories`
|
|
21
21
|
section and the folded Tech Spec sections (`## Delivery Slicing`
|
|
22
|
-
onward; Story #4324 retired the separate Tech Spec ticket) — plus
|
|
23
|
-
|
|
24
|
-
|
|
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).
|
|
25
26
|
2. **Workspace Awareness:** Identify if you are working in a monorepo or a
|
|
26
27
|
standard repo. Ensure all commands (installing packages, running scripts) are
|
|
27
28
|
executed in the correct workspace/directory. Check `package.json` or the
|
|
@@ -20,8 +20,11 @@ SQL, or UI components — stop immediately.
|
|
|
20
20
|
1. **Gather Context:** Read the parent Epic body — including its
|
|
21
21
|
`## User Stories` section and the folded Tech Spec sections
|
|
22
22
|
(`## Delivery Slicing` onward; Story #4324 retired the separate Tech
|
|
23
|
-
Spec ticket) — plus
|
|
24
|
-
|
|
23
|
+
Spec ticket) — plus the project's docs digest (digest-first with
|
|
24
|
+
pull-on-demand for `architecture.md`, the data dictionary, and the rest
|
|
25
|
+
of `project.docsContextFiles`; see
|
|
26
|
+
[`.agents/instructions.md` § 3](../instructions.md) — there is no
|
|
27
|
+
read-every-file mandate).
|
|
25
28
|
2. **Decompose:** Break the Epic into **Stories** that carry their own
|
|
26
29
|
inline acceptance criteria and verification steps. Aim for roughly
|
|
27
30
|
five acceptance bullets per Story as a soft atomicity heuristic; if
|
|
@@ -24,9 +24,11 @@ red tests green by "refactoring".
|
|
|
24
24
|
|
|
25
25
|
1. **Read Context:** Before touching anything, confirm the suite is green
|
|
26
26
|
and the quality gates currently pass. Read the parent Epic body —
|
|
27
|
-
including its folded Tech Spec sections (Story #4324) — plus
|
|
28
|
-
|
|
29
|
-
`project.docsContextFiles
|
|
27
|
+
including its folded Tech Spec sections (Story #4324) — plus the
|
|
28
|
+
project's docs digest (digest-first with pull-on-demand across
|
|
29
|
+
`project.docsContextFiles`; see
|
|
30
|
+
[`.agents/instructions.md` § 3](../instructions.md) — there is no
|
|
31
|
+
read-every-file mandate) so you know the conventions the code must keep
|
|
30
32
|
matching.
|
|
31
33
|
2. **Establish the baseline:** Capture the current CRAP and maintainability
|
|
32
34
|
numbers (e.g. `node .agents/scripts/check-baselines.js`) and the set of
|
|
@@ -165,6 +165,83 @@ operator intervention:
|
|
|
165
165
|
owning flow's hygiene step regressed — fix the flow, do not codify the manual
|
|
166
166
|
sweep.
|
|
167
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
|
+
|
|
168
245
|
## Meta Labels (Retrospective Signal Routing)
|
|
169
246
|
|
|
170
247
|
Two `meta::*` labels route retrospective signals into durable substrates so
|
|
@@ -546,8 +546,8 @@
|
|
|
546
546
|
"autoFixSeverity": {
|
|
547
547
|
"type": "string",
|
|
548
548
|
"enum": ["high", "medium"],
|
|
549
|
-
"default": "
|
|
550
|
-
"description": "Severity threshold for on-branch remediation
|
|
549
|
+
"default": "high",
|
|
550
|
+
"description": "Severity threshold for on-branch remediation of the Epic-close lens findings walked inside the /deliver Phase 5 code-review pass (Story #4412 folded the former Phase 4 lens walk into that single cumulative-diff pass). `high` (default) routes only 🔴 Critical / 🟠 High lens findings into the host-LLM remediation loop while 🟡 Medium and 🟢 Suggestion findings graduate to follow-up issues (🟡 Medium concerns are already remediated shift-left at the write-time and Story-scope tiers); `medium` opts back into routing 🔴/🟠/🟡 (Mediums batched per lens). Hard cutover — no back-compat flag."
|
|
551
551
|
}
|
|
552
552
|
},
|
|
553
553
|
"additionalProperties": false
|
|
@@ -1493,15 +1493,15 @@
|
|
|
1493
1493
|
"feedbackLoop": {
|
|
1494
1494
|
"type": "object",
|
|
1495
1495
|
"properties": {
|
|
1496
|
-
"
|
|
1496
|
+
"auditResultsAutoFile": {
|
|
1497
1497
|
"type": "boolean",
|
|
1498
1498
|
"default": true,
|
|
1499
|
-
"description": "When true (default), the Epic finalize listener auto-files non-blocking
|
|
1499
|
+
"description": "When true (default), the Epic finalize listener auto-files non-blocking audit-results findings as follow-up issues routed by source classification. Set to false to suppress auto-filing; findings remain accessible in the structured comments on the Epic."
|
|
1500
1500
|
},
|
|
1501
|
-
"
|
|
1501
|
+
"retroProposals": {
|
|
1502
1502
|
"type": "boolean",
|
|
1503
1503
|
"default": true,
|
|
1504
|
-
"description": "When true (default), the
|
|
1504
|
+
"description": "When true (default), the retro auto-files its actionable routed proposals as meta::<framework-gap|consumer-improvement> + friction::<category> issues via the graduator pre-parsed-findings seam, and the rendered retro sections list the filed issue numbers instead of paste-ready gh command stanzas. Set to false to fall back to the command stanzas."
|
|
1505
1505
|
}
|
|
1506
1506
|
},
|
|
1507
1507
|
"additionalProperties": false
|
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
"version": 1,
|
|
3
3
|
"audits": {
|
|
4
4
|
"audit-clean-code": {
|
|
5
|
-
"triggers": { "gates": ["gate1", "gate3"], "
|
|
5
|
+
"triggers": { "gates": ["gate1", "gate3"], "filePatterns": ["**/*"] },
|
|
6
|
+
"scope": "local",
|
|
6
7
|
"substitutionKeys": []
|
|
7
8
|
},
|
|
8
9
|
"audit-architecture": {
|
|
9
|
-
"triggers": { "gates": ["gate1", "gate3"]
|
|
10
|
+
"triggers": { "gates": ["gate1", "gate3"] },
|
|
11
|
+
"scope": "cumulative",
|
|
10
12
|
"substitutionKeys": []
|
|
11
13
|
},
|
|
12
14
|
"audit-security": {
|
|
@@ -22,6 +24,7 @@
|
|
|
22
24
|
],
|
|
23
25
|
"filePatterns": ["**/*.lock", "**/auth/*.js", "**/crypto/*.js"]
|
|
24
26
|
},
|
|
27
|
+
"scope": "local",
|
|
25
28
|
"substitutionKeys": []
|
|
26
29
|
},
|
|
27
30
|
"audit-privacy": {
|
|
@@ -30,6 +33,7 @@
|
|
|
30
33
|
"keywords": ["privacy", "pii", "gdpr", "cookie", "tracking"],
|
|
31
34
|
"filePatterns": ["**/user-profile/**/*.js"]
|
|
32
35
|
},
|
|
36
|
+
"scope": "local",
|
|
33
37
|
"substitutionKeys": []
|
|
34
38
|
},
|
|
35
39
|
"audit-lighthouse": {
|
|
@@ -54,6 +58,7 @@
|
|
|
54
58
|
"**/frontend/**/*.js"
|
|
55
59
|
]
|
|
56
60
|
},
|
|
61
|
+
"scope": "local",
|
|
57
62
|
"substitutionKeys": []
|
|
58
63
|
},
|
|
59
64
|
"audit-devops": {
|
|
@@ -67,10 +72,12 @@
|
|
|
67
72
|
"**/*.tf"
|
|
68
73
|
]
|
|
69
74
|
},
|
|
75
|
+
"scope": "cumulative",
|
|
70
76
|
"substitutionKeys": []
|
|
71
77
|
},
|
|
72
78
|
"audit-sre": {
|
|
73
79
|
"triggers": { "gates": ["gate4"] },
|
|
80
|
+
"scope": "global",
|
|
74
81
|
"substitutionKeys": []
|
|
75
82
|
},
|
|
76
83
|
"audit-documentation": {
|
|
@@ -91,6 +98,7 @@
|
|
|
91
98
|
".agents/workflows/**"
|
|
92
99
|
]
|
|
93
100
|
},
|
|
101
|
+
"scope": "cumulative",
|
|
94
102
|
"substitutionKeys": []
|
|
95
103
|
},
|
|
96
104
|
"audit-dependencies": {
|
|
@@ -112,6 +120,7 @@
|
|
|
112
120
|
"**/yarn.lock"
|
|
113
121
|
]
|
|
114
122
|
},
|
|
123
|
+
"scope": "cumulative",
|
|
115
124
|
"substitutionKeys": []
|
|
116
125
|
},
|
|
117
126
|
"audit-performance": {
|
|
@@ -120,6 +129,7 @@
|
|
|
120
129
|
"keywords": ["performance", "n+1", "hot path", "latency", "throughput"],
|
|
121
130
|
"filePatterns": [".agents/scripts/**", "src/**/*.{ts,js}"]
|
|
122
131
|
},
|
|
132
|
+
"scope": "local",
|
|
123
133
|
"substitutionKeys": []
|
|
124
134
|
},
|
|
125
135
|
"audit-quality": {
|
|
@@ -128,6 +138,7 @@
|
|
|
128
138
|
"keywords": ["test", "coverage", "flaky", "assertion"],
|
|
129
139
|
"filePatterns": ["tests/**", "**/*.test.{ts,js}", "**/*.spec.{ts,js}"]
|
|
130
140
|
},
|
|
141
|
+
"scope": "local",
|
|
131
142
|
"substitutionKeys": []
|
|
132
143
|
},
|
|
133
144
|
"audit-seo": {
|
|
@@ -136,6 +147,7 @@
|
|
|
136
147
|
"keywords": ["seo", "meta", "structured data", "schema.org", "sitemap"],
|
|
137
148
|
"filePatterns": ["**/*.html", "**/sitemap*", "**/robots.txt"]
|
|
138
149
|
},
|
|
150
|
+
"scope": "local",
|
|
139
151
|
"substitutionKeys": []
|
|
140
152
|
},
|
|
141
153
|
"audit-ux-ui": {
|
|
@@ -148,6 +160,7 @@
|
|
|
148
160
|
"**/*.css"
|
|
149
161
|
]
|
|
150
162
|
},
|
|
163
|
+
"scope": "local",
|
|
151
164
|
"substitutionKeys": []
|
|
152
165
|
},
|
|
153
166
|
"audit-navigability": {
|
|
@@ -160,6 +173,7 @@
|
|
|
160
173
|
"route tree"
|
|
161
174
|
]
|
|
162
175
|
},
|
|
176
|
+
"scope": "global",
|
|
163
177
|
"substitutionKeys": []
|
|
164
178
|
}
|
|
165
179
|
}
|
|
@@ -24,10 +24,15 @@
|
|
|
24
24
|
"definitions": {
|
|
25
25
|
"auditEntry": {
|
|
26
26
|
"type": "object",
|
|
27
|
-
"required": ["triggers"],
|
|
27
|
+
"required": ["triggers", "scope"],
|
|
28
28
|
"additionalProperties": false,
|
|
29
29
|
"properties": {
|
|
30
30
|
"triggers": { "$ref": "#/definitions/triggers" },
|
|
31
|
+
"scope": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"enum": ["local", "cumulative", "global"],
|
|
34
|
+
"description": "Concern-ownership tier declaring the widest scope at which this lens's concern becomes decidable. `local` — decidable from a single Story's diff (verified at write-time + Story-scope review). `cumulative` — only decidable across the Epic's combined diff (verified at Epic close). `global` — evaluates a whole-product property regardless of the diff (verified at Epic close; exempt from change-set narrowing). All tier routing derives from this one field via resolveLensTier()."
|
|
35
|
+
},
|
|
31
36
|
"substitutionKeys": {
|
|
32
37
|
"type": "array",
|
|
33
38
|
"description": "Substitution keys this audit accepts via run-audit-suite --substitution. Empty array means no caller-supplied keys are allowed.",
|
|
@@ -38,7 +43,7 @@
|
|
|
38
43
|
},
|
|
39
44
|
"triggers": {
|
|
40
45
|
"type": "object",
|
|
41
|
-
"description": "Selection criteria for whether this audit runs against a given ticket / changeset.
|
|
46
|
+
"description": "Selection criteria for whether this audit runs against a given ticket / changeset. `gates` must be set for select-audits.js to ever pick the audit; keyword / file-pattern matches then narrow selection within a matched gate.",
|
|
42
47
|
"additionalProperties": false,
|
|
43
48
|
"properties": {
|
|
44
49
|
"gates": {
|
|
@@ -47,10 +52,6 @@
|
|
|
47
52
|
"uniqueItems": true,
|
|
48
53
|
"description": "Quality-gate identifiers (gate1..gateN) that include this audit."
|
|
49
54
|
},
|
|
50
|
-
"alwaysRun": {
|
|
51
|
-
"type": "boolean",
|
|
52
|
-
"description": "If true, the audit is always selected regardless of keyword / file-pattern matches."
|
|
53
|
-
},
|
|
54
55
|
"keywords": {
|
|
55
56
|
"type": "array",
|
|
56
57
|
"items": { "type": "string", "minLength": 1 },
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://github.com/dsj1984/mandrel/blob/main/.agents/schemas/lifecycle/merge.unlanded.schema.json",
|
|
4
|
+
"title": "merge.unlanded",
|
|
5
|
+
"description": "Emitted whenever a headless delivery run (the epic-path finalize flow or the standalone single-story-close flow) finishes its work without a confirmed merge, so a work-complete-but-unmerged terminal state is precisely attributable from the lifecycle ledger instead of diffing origin/main after the fact (Epic #4425). scope distinguishes the epic-path (ticketId = epicId) from the standalone story-path (ticketId = storyId); blockClass is produced by the shared classifier in merge-block-class.js.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": [
|
|
8
|
+
"event",
|
|
9
|
+
"scope",
|
|
10
|
+
"ticketId",
|
|
11
|
+
"prNumber",
|
|
12
|
+
"blockClass",
|
|
13
|
+
"reason",
|
|
14
|
+
"elapsedSeconds"
|
|
15
|
+
],
|
|
16
|
+
"properties": {
|
|
17
|
+
"event": { "type": "string", "const": "merge.unlanded" },
|
|
18
|
+
"scope": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"enum": ["epic", "story"]
|
|
21
|
+
},
|
|
22
|
+
"ticketId": { "type": "integer", "minimum": 1 },
|
|
23
|
+
"prNumber": { "type": "integer", "minimum": 1 },
|
|
24
|
+
"blockClass": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"enum": [
|
|
27
|
+
"checks-pending-timeout",
|
|
28
|
+
"branch-protection-human-required",
|
|
29
|
+
"arm-failure",
|
|
30
|
+
"api-race-other"
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
"reason": { "type": "string", "minLength": 1 },
|
|
34
|
+
"elapsedSeconds": { "type": "number", "minimum": 0 },
|
|
35
|
+
"timestamp": { "type": "string", "format": "date-time" }
|
|
36
|
+
},
|
|
37
|
+
"additionalProperties": false
|
|
38
|
+
}
|
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
3
|
"$id": "https://github.com/dsj1984/mandrel/blob/main/.agents/schemas/signal-event.schema.json",
|
|
4
4
|
"title": "SignalEvent",
|
|
5
|
-
"description": "One NDJSON line emitted by the signals writer (Epic #1030). Runtime events live in append-only NDJSON on local disk under temp/epic-<eid>/stories/story-<sid>/signals.ndjson; tickets carry only summaries (story-perf-summary, epic-perf-report). `kind: trace` is the raw tool-call trace; the named kinds are derived signals.",
|
|
5
|
+
"description": "One NDJSON line emitted by the signals writer (Epic #1030; canonical envelope cutover Epic #4406 / Story #4413). Runtime events live in append-only NDJSON on local disk under temp/epic-<eid>/stories/story-<sid>/signals.ndjson (per-Story) and temp/epic-<eid>/signals.ndjson (Epic-level wave lifecycle); tickets carry only summaries (story-perf-summary, epic-perf-report). `kind: trace` is the raw tool-call trace; the named kinds are derived signals. This is the ONLY shape — the legacy `timestamp` / `epic` aliases and the `source: { tool }` provenance object were deleted in the same PR that moved every writer (no read-side compatibility branch).",
|
|
6
6
|
"type": "object",
|
|
7
|
-
"additionalProperties":
|
|
8
|
-
"required": ["
|
|
7
|
+
"additionalProperties": true,
|
|
8
|
+
"required": ["kind", "ts"],
|
|
9
9
|
"properties": {
|
|
10
10
|
"ts": {
|
|
11
11
|
"type": "string",
|
|
12
12
|
"format": "date-time",
|
|
13
|
-
"description": "Event timestamp in ISO-8601 UTC."
|
|
13
|
+
"description": "Event timestamp in ISO-8601 UTC. The single canonical timestamp key — the legacy `timestamp` alias is gone."
|
|
14
14
|
},
|
|
15
15
|
"kind": {
|
|
16
16
|
"type": "string",
|
|
@@ -22,28 +22,43 @@
|
|
|
22
22
|
"idle",
|
|
23
23
|
"retry",
|
|
24
24
|
"acceptance-eval",
|
|
25
|
-
"trace"
|
|
25
|
+
"trace",
|
|
26
|
+
"wave-start",
|
|
27
|
+
"wave-end",
|
|
28
|
+
"wave-complete",
|
|
29
|
+
"state-transition",
|
|
30
|
+
"notification.emitted"
|
|
26
31
|
]
|
|
27
32
|
},
|
|
28
33
|
"source": {
|
|
34
|
+
"type": "string",
|
|
35
|
+
"enum": ["framework", "consumer"],
|
|
36
|
+
"description": "Framework/consumer classification injected by `tagSignalSource` (signals-writer.js) for records appended via appendSignal/appendEpicSignal. Reserved exclusively for this classifier tag — the originating tool/surface lives in `emitter`."
|
|
37
|
+
},
|
|
38
|
+
"emitter": {
|
|
29
39
|
"type": "object",
|
|
30
|
-
"additionalProperties":
|
|
31
|
-
"required": ["tool"],
|
|
40
|
+
"additionalProperties": true,
|
|
32
41
|
"properties": {
|
|
33
42
|
"tool": {
|
|
34
43
|
"type": "string",
|
|
35
44
|
"minLength": 1,
|
|
36
45
|
"description": "Originating tool or surface (Bash, Edit, Write, Read, Grep, Glob, or a script name for derived signals)."
|
|
37
46
|
},
|
|
38
|
-
"
|
|
47
|
+
"command": {
|
|
39
48
|
"type": "string",
|
|
40
|
-
"
|
|
41
|
-
"description": "Script that emitted the signal, when applicable (e.g. diagnose-friction.js)."
|
|
49
|
+
"description": "Command line the signal blames, when applicable (e.g. the failed command captured by diagnose-friction.js)."
|
|
42
50
|
}
|
|
43
|
-
}
|
|
51
|
+
},
|
|
52
|
+
"description": "Provenance of the record — the tool/script that produced it. Replaces the pre-cutover `source: { tool }` object; `source` now carries only the framework/consumer classification."
|
|
44
53
|
},
|
|
45
54
|
"epicId": { "type": ["integer", "null"], "minimum": 1 },
|
|
46
|
-
"storyId": { "type": "integer", "minimum": 1 },
|
|
55
|
+
"storyId": { "type": ["integer", "null"], "minimum": 1 },
|
|
56
|
+
"taskId": { "type": ["integer", "null"], "minimum": 1 },
|
|
57
|
+
"category": {
|
|
58
|
+
"type": "string",
|
|
59
|
+
"minLength": 1,
|
|
60
|
+
"description": "Top-level friction category (e.g. Execution Error, baseline-refresh-regression). Read directly by perf-aggregator frictionByCategory and the retro routed-proposal extraction — never nested under details."
|
|
61
|
+
},
|
|
47
62
|
"phase": {
|
|
48
63
|
"type": ["string", "null"],
|
|
49
64
|
"minLength": 1,
|
|
@@ -51,7 +66,7 @@
|
|
|
51
66
|
},
|
|
52
67
|
"details": {
|
|
53
68
|
"type": "object",
|
|
54
|
-
"description": "Kind-specific payload. Free-form for forward compatibility; common keys include
|
|
69
|
+
"description": "Kind-specific payload — always an object, never a bare string. Free-form for forward compatibility; common keys include errorPreview, command, commandHash, targetHash, editCount, failureCount, exitCode, elapsedMs.",
|
|
55
70
|
"additionalProperties": true
|
|
56
71
|
}
|
|
57
72
|
}
|
|
@@ -87,10 +87,12 @@ Options:
|
|
|
87
87
|
/**
|
|
88
88
|
* Pure: parse stable AC IDs (AC-<n>) out of an acceptance-table section.
|
|
89
89
|
* AC authoring style is "Acceptance Table — Markdown table whose first
|
|
90
|
-
* column is the AC ID" — see
|
|
91
|
-
* epic-plan-spec
|
|
92
|
-
*
|
|
93
|
-
*
|
|
90
|
+
* column is the AC ID" — see the Acceptance Spec system prompt in the
|
|
91
|
+
* `epic-plan-spec-author` skill body
|
|
92
|
+
* (`.agents/skills/core/epic-plan-spec-author/SKILL.md`), the sole home for
|
|
93
|
+
* that prompt. We scan the entire section with a permissive regex because
|
|
94
|
+
* operators are free to format the content however they wish around the
|
|
95
|
+
* canonical table.
|
|
94
96
|
*
|
|
95
97
|
* Returns IDs **in document order**, deduplicated, normalised to
|
|
96
98
|
* upper-case (`AC-7`, not `ac-7`).
|