@event4u/agent-config 16.0.0 → 16.1.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/.augment-plugin/marketplace.json +3 -3
- package/.augment-plugin/plugin.json +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +297 -137
- package/CONTRIBUTING.md +9 -0
- package/README.md +2 -2
- package/dist/agent-src/commands/analyze/inbox.md +26 -0
- package/dist/agent-src/commands/analyze/roadmap-repos.md +27 -0
- package/dist/agent-src/commands/challenge-me/closure.md +178 -0
- package/dist/agent-src/commands/challenge-me.md +9 -2
- package/dist/agent-src/commands/council/default.md +25 -5
- package/dist/agent-src/commands/feature/plan.md +28 -1
- package/dist/agent-src/commands/feature/roadmap.md +28 -1
- package/dist/agent-src/commands/implement-ticket.md +27 -0
- package/dist/agent-src/commands/jira-ticket.md +27 -0
- package/dist/agent-src/commands/pr/create.md +29 -0
- package/dist/agent-src/commands/pr/merge.md +60 -9
- package/dist/agent-src/commands/roadmap/ai-council.md +7 -1
- package/dist/agent-src/commands/roadmap/create.md +74 -27
- package/dist/agent-src/commands/roadmap/materialize.md +27 -0
- package/dist/agent-src/commands/roadmap/process-full.md +123 -18
- package/dist/agent-src/commands/team.md +22 -0
- package/dist/agent-src/contexts/authority/scope-growth-ownership.md +80 -0
- package/dist/agent-src/contexts/communication/rules-auto/user-interaction-mechanics.md +47 -0
- package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +44 -3
- package/dist/agent-src/contexts/execution/autonomy-mechanics.md +15 -15
- package/dist/agent-src/contexts/execution/decision-closure-execution.md +93 -0
- package/dist/agent-src/contexts/execution/fix-loop-ladder.md +108 -0
- package/dist/agent-src/contexts/execution/plan-confidence-gate.md +4 -2
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +75 -6
- package/dist/agent-src/guidelines/agent-infra/active-remediation-mechanics.md +57 -0
- package/dist/agent-src/guidelines/agent-infra/evaluator-independence-mechanics.md +102 -0
- package/dist/agent-src/guidelines/design-fidelity-routing.md +29 -0
- package/dist/agent-src/rules/autonomous-execution.md +15 -8
- package/dist/agent-src/rules/delegation-policy.md +23 -45
- package/dist/agent-src/rules/design-fidelity.md +32 -37
- package/dist/agent-src/rules/evaluator-independence.md +43 -49
- package/dist/agent-src/rules/test-first.md +41 -0
- package/dist/agent-src/skills/accessibility-auditor/data/manifest.json +3 -3
- package/dist/agent-src/skills/ai-council/SKILL.md +11 -3
- package/dist/agent-src/skills/api-design/data/manifest.json +3 -3
- package/dist/agent-src/skills/database/data/manifest.json +4 -4
- package/dist/agent-src/skills/database/data/query-tuning.csv +3 -3
- package/dist/agent-src/skills/design-review/SKILL.md +50 -0
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +14 -4
- package/dist/agent-src/skills/experiment-loop/SKILL.md +31 -1
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +1 -1
- package/dist/agent-src/skills/storybook-workshop/SKILL.md +42 -3
- package/dist/agent-src/skills/threat-modeling/SKILL.md +9 -4
- package/dist/agent-src/skills/threat-modeling/data/manifest.json +4 -4
- package/dist/agent-src/skills/verify-repair-loop/SKILL.md +37 -3
- package/dist/agent-src/templates/agent-settings.md +1 -1
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +188 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +62 -2
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/test.ts +1 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +1 -0
- package/dist/cli-delegate/check_update_banner.js +40 -2
- package/dist/cli-delegate/chunk-4E2W63DA.js +335 -0
- package/dist/cli-delegate/chunk-5R7HOLAF.js +99 -0
- package/dist/cli-delegate/{chunk-IVBPRCQO.js → chunk-6KFEC3G7.js} +1 -1
- package/dist/cli-delegate/{chunk-2TAQ2K4V.js → chunk-6KM6ORRY.js} +55 -386
- package/dist/cli-delegate/{chunk-2XY7ILBT.js → chunk-FC75PGJE.js} +42 -2
- package/dist/cli-delegate/{chunk-GYC3VRYN.js → chunk-FXYUYU4N.js} +57 -13
- package/dist/cli-delegate/{chunk-55ACLDUE.js → chunk-GJCBB2UG.js} +168 -10
- package/dist/cli-delegate/{chunk-AK6HODNQ.js → chunk-HDVVGPQW.js} +873 -539
- package/dist/cli-delegate/{chunk-H32DGUJH.js → chunk-P6ZHP5W2.js} +1 -1
- package/dist/cli-delegate/{chunk-57PN4GYJ.js → chunk-RGNIWTEA.js} +1 -1
- package/dist/cli-delegate/chunk-ROYYTEZU.js +39 -0
- package/dist/cli-delegate/{chunk-3FKR64R5.js → chunk-UNCRJBT3.js} +31 -7
- package/dist/cli-delegate/{chunk-2DK2VJWG.js → chunk-WGXTVKCQ.js} +20 -6
- package/dist/cli-delegate/chunk-YDPILCOL.js +152 -0
- package/dist/cli-delegate/cmd_analyze_session.js +1 -1
- package/dist/cli-delegate/cmd_brand_status.js +1 -1
- package/dist/cli-delegate/cmd_conformance.js +90 -56
- package/dist/cli-delegate/cmd_doctor.js +7 -5
- package/dist/cli-delegate/cmd_explain.js +2 -2
- package/dist/cli-delegate/cmd_export.js +9 -7
- package/dist/cli-delegate/cmd_fleet.js +4 -2
- package/dist/cli-delegate/cmd_handoff.js +4 -4
- package/dist/cli-delegate/cmd_mcp_available.js +1 -1
- package/dist/cli-delegate/cmd_migrate.js +2 -2
- package/dist/cli-delegate/cmd_packs_active.js +2 -2
- package/dist/cli-delegate/cmd_preflight.js +4 -2
- package/dist/cli-delegate/cmd_prune.js +10 -8
- package/dist/cli-delegate/cmd_route_audit.js +2 -2
- package/dist/cli-delegate/cmd_route_explain.js +1 -1
- package/dist/cli-delegate/cmd_session_recycle.js +2 -2
- package/dist/cli-delegate/cmd_settings_get.js +28 -2
- package/dist/cli-delegate/cmd_settings_migrate.js +9 -7
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +10 -8
- package/dist/cli-delegate/cmd_uninstall.js +16 -13
- package/dist/cli-delegate/cmd_update.js +1 -1
- package/dist/cli-delegate/cmd_upgrade.js +1 -1
- package/dist/cli-delegate/cmd_validate.js +12 -10
- package/dist/cli-delegate/cmd_versions.js +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +85 -38
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +4 -4
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +10 -8
- package/dist/discovery/trust-report.md +3 -3
- package/dist/discovery/workspaces.json +8 -6
- package/dist/hooks/dispatch.js +1832 -1007
- package/dist/install/claudeRuleRewrite.js +14 -3
- package/dist/install/conflict.js +60 -10
- package/dist/install/conflictTracker.js +218 -0
- package/dist/install/fsPrimitives.js +54 -0
- package/dist/install/install.mjs +2007 -1481
- package/dist/install/manifestFiles.js +259 -0
- package/dist/install/preflight.js +14 -2
- package/dist/install/preserve.js +157 -0
- package/dist/install/recordedOwnership.js +132 -0
- package/dist/install/txlog.js +11 -2
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +398 -39
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/agent_settings.js +3 -2
- package/dist/scripts/_lib/fs_atomic.js +167 -0
- package/dist/scripts/_lib/installed_tools.js +460 -0
- package/dist/scripts/_lib/lean_projection_mode.js +3 -2
- package/dist/scripts/_lib/settings_renamed_keys.js +78 -0
- package/dist/server/routes/install.js +8 -0
- package/dist/server/routes/wizard.js +9 -3
- package/dist/server/schemas/settings.js +17 -5
- package/dist/shared/missionExecution.js +97 -0
- package/dist/ui/assets/{index-D0jaCRPM.js → index-DH1xc62v.js} +17 -17
- package/dist/ui/index.html +1 -1
- package/docs/MIGRATION.md +103 -0
- package/docs/contracts/settings-classes.md +26 -7
- package/docs/guidelines/agent-infra/active-remediation-mechanics.md +57 -0
- package/docs/guidelines/agent-infra/evaluator-independence-mechanics.md +102 -0
- package/docs/guidelines/design-fidelity-routing.md +29 -0
- package/package.json +1 -1
- package/src/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +62 -2
- package/src/agent-src/templates/scripts/work_engine/directives/backend/test.ts +1 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +1 -0
- package/src/config/agent-settings.template.yml +139 -27
- package/src/config/auto-rule-budget.json +16 -0
- package/src/config/ci-local-parity.yml +18 -5
- package/src/config/continuity-surface.json +21 -0
- package/src/config/gate-coverage.yml +146 -13
- package/src/config/gate-violation-baselines.json +6 -6
- package/src/config/hook-token-budget.json +2 -0
- package/src/config/loop-surfaces.yaml +215 -0
- package/src/config/platform-anchor.json +3 -2
- package/src/config/release-gate-locality.yml +11 -0
- package/src/config/routing-coverage-seed.json +18 -4
- package/src/config/rule-enforcement-baseline.json +0 -1
- package/src/install/claudeRuleRewrite.ts +16 -2
- package/src/install/conflict.ts +65 -9
- package/src/install/conflictTracker.ts +299 -0
- package/src/install/fsPrimitives.ts +54 -0
- package/src/install/manifestFiles.ts +312 -0
- package/src/install/preflight.ts +16 -2
- package/src/install/preserve.ts +205 -0
- package/src/install/recordedOwnership.ts +149 -0
- package/src/install/txlog.ts +11 -2
- package/src/install/types.ts +19 -4
- package/src/scripts/_cli/cmd_conformance.ts +88 -15
- package/src/scripts/_cli/cmd_doctor.ts +4 -3
- package/src/scripts/_cli/cmd_route_explain.ts +9 -2
- package/src/scripts/_cli/cmd_settings_get.ts +44 -0
- package/src/scripts/_cli/doctor_execution.ts +90 -0
- package/src/scripts/_lib/activation_payload.ts +247 -0
- package/src/scripts/_lib/agent_settings.ts +4 -2
- package/src/scripts/_lib/authority_path.ts +102 -0
- package/src/scripts/_lib/cascade_base.ts +94 -0
- package/src/scripts/_lib/changelog_eras.ts +7 -2
- package/src/scripts/_lib/continuation_ladder.ts +149 -2
- package/src/scripts/_lib/council_transport.ts +129 -0
- package/src/scripts/_lib/delivery_ready.ts +112 -0
- package/src/scripts/_lib/forge_protection.ts +267 -0
- package/src/scripts/_lib/hook_platform_keys.ts +27 -0
- package/src/scripts/_lib/json_python_parity.ts +127 -0
- package/src/scripts/_lib/lean_projection_mode.ts +14 -3
- package/src/scripts/_lib/loop_surfaces.ts +382 -0
- package/src/scripts/_lib/mission_record.ts +190 -0
- package/src/scripts/_lib/obligation_frequency.ts +217 -0
- package/src/scripts/_lib/obligations.ts +402 -0
- package/src/scripts/_lib/orchestration_record.ts +11 -20
- package/src/scripts/_lib/release_highlights.ts +199 -10
- package/src/scripts/_lib/release_holds.ts +493 -0
- package/src/scripts/_lib/release_migration_gate.ts +184 -0
- package/src/scripts/_lib/rides_along.ts +102 -0
- package/src/scripts/_lib/settings_renamed_keys.ts +82 -0
- package/src/scripts/_lib/test_delta.ts +166 -0
- package/src/scripts/_lib/test_provenance.ts +171 -0
- package/src/scripts/_lib/typed_op_grant.ts +246 -0
- package/src/scripts/_lib/typed_op_watch.ts +185 -0
- package/src/scripts/ai_council/config.ts +8 -11
- package/src/scripts/ai_council/fallback_config.ts +5 -3
- package/src/scripts/ai_council/ownership_classes.ts +118 -0
- package/src/scripts/ask_block_census.ts +285 -15
- package/src/scripts/check_enforcement_matrix.ts +624 -0
- package/src/scripts/check_gate_reachability.ts +173 -10
- package/src/scripts/check_generator_sync.ts +954 -0
- package/src/scripts/check_preamble_payload_budget.ts +75 -2
- package/src/scripts/check_release_highlights.ts +33 -1
- package/src/scripts/check_release_holds.ts +567 -0
- package/src/scripts/check_rule_projection_integrity.ts +22 -12
- package/src/scripts/check_test_delta.ts +294 -0
- package/src/scripts/check_test_weakening.ts +299 -0
- package/src/scripts/closure_scan.ts +333 -0
- package/src/scripts/compile_hook_manifest.ts +43 -3
- package/src/scripts/council_record_shape.ts +209 -0
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +88 -9
- package/src/scripts/hooks/concern_registry.ts +4 -0
- package/src/scripts/hooks/design_pass_hook.ts +128 -3
- package/src/scripts/hooks/evidence_independence.ts +96 -0
- package/src/scripts/hooks/memory_recall_hook.ts +540 -0
- package/src/scripts/hooks/obligation_settle_hook.ts +182 -0
- package/src/scripts/hooks/rule_inject_hook.ts +49 -1
- package/src/scripts/hooks/run_continuation_hook.ts +17 -20
- package/src/scripts/hooks_doctor.ts +85 -0
- package/src/scripts/hooks_status.ts +19 -0
- package/src/scripts/install.ts +106 -206
- package/src/scripts/janitor.ts +7 -0
- package/src/scripts/lint_decision_classes.ts +464 -0
- package/src/scripts/lint_hook_manifest.ts +11 -0
- package/src/scripts/lint_major_migration_sections.ts +450 -0
- package/src/scripts/lint_plan_risk_register.ts +47 -3
- package/src/scripts/lint_roadmap_blockers.ts +61 -0
- package/src/scripts/lint_roadmap_producers.ts +202 -0
- package/src/scripts/measure_rule_budget.ts +101 -5
- package/src/scripts/new_roadmap.ts +37 -0
- package/src/scripts/orchestration_record.ts +0 -5
- package/src/scripts/release.ts +14 -98
- package/src/scripts/release_drill.ts +267 -1
- package/src/scripts/release_publication.ts +51 -0
- package/src/scripts/report_enforcement_drift.ts +566 -0
- package/src/scripts/report_host_injection_effect.ts +3 -11
- package/src/scripts/report_standing_payload_by_host.ts +26 -152
- package/src/scripts/schemas/agent-settings.schema.json +23 -0
- package/src/scripts/schemas/command.schema.json +4 -0
- package/src/scripts/scope_growth.ts +219 -0
- package/src/scripts/trigger_eval_grandfather.json +0 -1
- package/src/scripts/ui_conformance_probe.ts +622 -0
- package/src/server/schemas/settings.ts +31 -7
- package/src/shared/missionExecution.ts +126 -0
- package/dist/cli-delegate/chunk-523HCFYO.js +0 -90
|
@@ -163,10 +163,20 @@ Read `components.json` for the registered style + base color, then read the `pac
|
|
|
163
163
|
### 4b. Prefer a live Storybook read over the hand-read inventory — when one is running
|
|
164
164
|
|
|
165
165
|
When the project carries `@storybook/addon-mcp` **and** a Storybook is running, query it
|
|
166
|
-
instead of reading files: `list
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
166
|
+
instead of reading files: `docs-list` for the inventory, then `docs-show` for the components
|
|
167
|
+
that matter. **The live read wins; the hand-read inventory of step 4 is the fallback and is
|
|
168
|
+
never removed** — an agent that cannot reach a running Storybook must still be able to
|
|
169
|
+
inventory the library. The channel disappearing is normal, not an error.
|
|
170
|
+
|
|
171
|
+
**The names are version-bound, and these are the current ones.** Own derivation, from a
|
|
172
|
+
throwaway `npm install` on 2026-09-13, not from any document: at `@storybook/addon-mcp@10.6.0`
|
|
173
|
+
the docs tools are registered by `storybook`'s own `createDocsToolset` under the method ids
|
|
174
|
+
`docs.list` / `docs.show` / `docs.showStory`, and `toMcpToolName` renders those as `docs-list`,
|
|
175
|
+
`docs-show` and `docs-show-story`. The older `list-all-documentation` / `get-documentation` were
|
|
176
|
+
the literal names at `@storybook/addon-mcp@0.7.0` (via `@storybook/mcp@0.8.0`); at 10.6.0 they
|
|
177
|
+
survive only as the tools' human-readable **titles**. There is no 10.5.x of the addon — it goes
|
|
178
|
+
0.7.0 → 10.6.0 — so a project on the current scaffold gets the `docs-*` names. If a live
|
|
179
|
+
`tools/list` disagrees, the live read wins over this paragraph.
|
|
170
180
|
|
|
171
181
|
**React-only while the toolset is in preview.** Storybook's own MCP FAQ (docs **10.5**,
|
|
172
182
|
`docs/ai/mcp/overview` § FAQ) states the documentation toolset supports React only during
|
|
@@ -91,7 +91,37 @@ twice, leaving the branch one iteration ahead of its own record.
|
|
|
91
91
|
1. **The register path**, and the iteration count actually run against the bound.
|
|
92
92
|
2. **A metric line**: baseline → final, and the number of keeps versus reverts.
|
|
93
93
|
3. **The exit condition that fired**, named — bound reached, or exit signal.
|
|
94
|
-
4. **
|
|
94
|
+
4. **A `run_terminal` value** — the exit in the vocabulary every other loop in
|
|
95
|
+
this tree reports in, so a reader can count this run's stop alongside the
|
|
96
|
+
continuation hook's and the self-fix lanes' without a per-surface
|
|
97
|
+
translation table.
|
|
98
|
+
|
|
99
|
+
| exit condition | `run_terminal` |
|
|
100
|
+
|---|---|
|
|
101
|
+
| `score >= target` — the run had a destination and reached it | `success` |
|
|
102
|
+
| `iterations_run >= max_iterations` — the declared bound | `exhausted` |
|
|
103
|
+
| `consecutive_reverts >= N` — the exit signal fired | `stagnated` |
|
|
104
|
+
| the evaluator was red on the unchanged tree, so no iteration ran | `clean-no-op` |
|
|
105
|
+
| the run stopped on a missing precondition (metric unreadable, verifier absent) | `blocked` |
|
|
106
|
+
|
|
107
|
+
The value set is `RunTerminalState` — `success`, `clean-no-op`, `blocked`,
|
|
108
|
+
`approval-required`, `exhausted`, `stagnated`, `premise-invalidated` —
|
|
109
|
+
declared once at `src/scripts/_lib/outcome_vocabularies.ts`
|
|
110
|
+
(`RUN_TERMINAL_STATES`) and described in
|
|
111
|
+
[`terminal-states`](../../agent-src/contexts/execution/terminal-states.md).
|
|
112
|
+
A new exit condition maps onto an existing member or it is not a terminal
|
|
113
|
+
state; never invent a value here.
|
|
114
|
+
|
|
115
|
+
`exhausted` and `stagnated` stay distinct on purpose. This skill's own pivot
|
|
116
|
+
ladder already treats them differently — a spent bound may deserve a larger
|
|
117
|
+
one, while consecutive reverts mean the hypothesis class is done and route to
|
|
118
|
+
the ladder instead. Reporting both as "stopped" throws away the part that
|
|
119
|
+
decides what happens next.
|
|
120
|
+
|
|
121
|
+
Reaching the bound is a normal exit, not a failure, and `exhausted` does not
|
|
122
|
+
say otherwise — it says where the run stopped, never whether it was worth
|
|
123
|
+
running. A published null is still a result.
|
|
124
|
+
5. **Every reverted iteration listed** with its reason. A revert is a result the
|
|
95
125
|
next run needs, not noise to summarise away.
|
|
96
126
|
|
|
97
127
|
## Gotcha
|
|
@@ -191,7 +191,7 @@ the owner can decide in one sitting: one option named and why, what the delay
|
|
|
191
191
|
costs, a command or path per option rather than prose, and an offer to walk
|
|
192
192
|
them through it. Ratcheted by `lint_roadmap_blockers`. Full shape:
|
|
193
193
|
[`templates/roadmaps.md` rule 20](../../agent-src/templates/roadmaps.md).
|
|
194
|
-
Omit it entirely when there is no such gate; run the § 4c gate-test first.
|
|
194
|
+
Omit it entirely when there is no such gate; run the § 4c gate-test first. A **hold** is the publication-side twin — a blocker stops execution, a hold stops publication; ask once whether an intermediate tree state must stay unpublished (default **no**; roadmap incompleteness never is one), walk `re-sequence → guard → hold`, and record the avoided outcome as well as the taken one, per [`templates/roadmaps.md` rule 28](../../agent-src/templates/roadmaps.md) and the § 5c self-check in [`/roadmap:create`](../../domains/product-basic/roadmap/create/command.md).
|
|
195
195
|
|
|
196
196
|
### 5c. Risk review (Gate R1) — after draft, before save
|
|
197
197
|
|
|
@@ -52,6 +52,43 @@ single prop's effect because every value is co-present. Split it, one axis per s
|
|
|
52
52
|
Stories render under the **same semantic tokens** as the app and the `.dark` class; a
|
|
53
53
|
hardcoded preview theme makes the workshop lie about what the component looks like in place.
|
|
54
54
|
|
|
55
|
+
### The five behavioral stories — assert a value, never an image
|
|
56
|
+
|
|
57
|
+
`Hover`, `Focus`, `Active`, `Keyboard` and `ReducedMotion` join the set above, and they
|
|
58
|
+
carry one extra rule: **each asserts a resolved computed style or a handler effect, never a
|
|
59
|
+
screenshot.** A component that owes a state checklist and proves it with a pixel diff has
|
|
60
|
+
not proved it — a screenshot is a resting frame, and none of these five is a resting frame.
|
|
61
|
+
|
|
62
|
+
| Story | Drive | Assert |
|
|
63
|
+
|---|---|---|
|
|
64
|
+
| `Hover` | `userEvent.hover(el)` | the resolved property the hover rule is supposed to change actually changed |
|
|
65
|
+
| `Focus` | focus the element | the `:focus` styles resolve as intended |
|
|
66
|
+
| `Keyboard` | `userEvent.tab()` until the element is active | a visible `:focus-visible` indicator resolves — programmatic focus does **not** set it in Chromium, so a `.focus()` call reports a real focus ring as absent |
|
|
67
|
+
| `Active` | press and hold | what pressing adds **on top of hover** — a pointer cannot press without hovering, so asserting against the resting style makes one removed hover rule fail two stories |
|
|
68
|
+
| `ReducedMotion` | emulate `prefers-reduced-motion: reduce` | what the surface presents *instead of* the motion, per [`accessibility-auditor`](../accessibility-auditor/SKILL.md) § 2 — not that the media block exists |
|
|
69
|
+
|
|
70
|
+
The `Active` and `Keyboard` rows are not style advice. Both are measured failure modes from
|
|
71
|
+
building the probe that backs this set, recorded here so the next author does not rediscover
|
|
72
|
+
them: the first produced a duplicate finding for a single defect, the second reports a focus
|
|
73
|
+
ring that is present as missing.
|
|
74
|
+
|
|
75
|
+
### Responsive rows — one row per declared breakpoint
|
|
76
|
+
|
|
77
|
+
Beside the state stories, each responsive component owes a row per declared breakpoint
|
|
78
|
+
(1440 / 768 / 375 / 320) asserting **the layout property that is supposed to change there** —
|
|
79
|
+
`flex-direction`, `grid-template-columns`, `display`. One row per breakpoint, not one per
|
|
80
|
+
property: a single media rule usually moves several properties at once, and one finding each
|
|
81
|
+
counts one defect several times.
|
|
82
|
+
|
|
83
|
+
**Where a workshop is absent, this set is still assertable.** These stories are a contract
|
|
84
|
+
about what is asserted, not about a particular runner — the `ui_conformance_probe` script
|
|
85
|
+
exercises the same five states and the same breakpoint rows against a file URL. It and its
|
|
86
|
+
sensitivity fixture live in the package repository and are **not** shipped to consumers,
|
|
87
|
+
which is why both are named rather than linked: a path to either resolves nowhere in an
|
|
88
|
+
install. The fixture is the evidence for the two sensitivity claims above — removing one
|
|
89
|
+
hover rule turns exactly the hover assertion red and nothing else, and removing one media
|
|
90
|
+
rule turns exactly the matching breakpoint row red.
|
|
91
|
+
|
|
55
92
|
## JSDoc `@summary` is required, and the reason is mechanical
|
|
56
93
|
|
|
57
94
|
The manifest an agent reads **truncates descriptions**. A component whose summary is a
|
|
@@ -81,7 +118,7 @@ files otherwise — and only then decide whether anything needs writing.
|
|
|
81
118
|
1. **Inspect the existing story set before authoring anything.** Read what the library
|
|
82
119
|
already has — via the MCP channel below when it is available, otherwise by reading the
|
|
83
120
|
story files — and check the component against it by name and by shape.
|
|
84
|
-
- **Source of truth:** the story files, or `list
|
|
121
|
+
- **Source of truth:** the story files, or `docs-list` over a running Storybook.
|
|
85
122
|
- **Verify:** the component you are about to write does not already exist under another name.
|
|
86
123
|
2. **One story per concept**, named from the state set above.
|
|
87
124
|
- **Verify:** no story name joins two axes with `And`.
|
|
@@ -142,10 +179,12 @@ up yet"*, so its presence is not evidence the channel works.
|
|
|
142
179
|
|
|
143
180
|
When the project has `@storybook/addon-mcp` **and** a running Storybook,
|
|
144
181
|
[`existing-ui-audit`](../existing-ui-audit/SKILL.md) prefers the live tools —
|
|
145
|
-
`list
|
|
182
|
+
`docs-list`, then `docs-show` for the components that matter — over the
|
|
146
183
|
hand-read inventory. **The live read wins; the file read is the fallback**, and the fallback
|
|
147
184
|
is never removed: an agent that cannot reach a running Storybook must still be able to
|
|
148
|
-
inventory the library.
|
|
185
|
+
inventory the library. The tool names are version-bound and were re-derived from a throwaway
|
|
186
|
+
installation on 2026-09-13 — [`existing-ui-audit`](../existing-ui-audit/SKILL.md) § 4b carries
|
|
187
|
+
the derivation and the version boundary; do not restate it here.
|
|
149
188
|
|
|
150
189
|
**React-only while in preview.** Storybook's own MCP FAQ (docs 10.5) states the documentation
|
|
151
190
|
toolset supports React only during preview, so Vue, Angular, and Web Components take the
|
|
@@ -25,8 +25,8 @@ triggers:
|
|
|
25
25
|
> "<surface description>"` returns the surface class, ATT&CK/CWE-cited
|
|
26
26
|
> threats, required controls, and negative tests, with confidence +
|
|
27
27
|
> evidence-gap. Propose grounded findings; the human confirms. Corpus:
|
|
28
|
-
> [`data/threats.csv`](data/threats.csv) (MITRE ATT&CK
|
|
29
|
-
> ASVS-derived, owner + cadence in the manifest).
|
|
28
|
+
> [`data/threats.csv`](data/threats.csv) (MITRE ATT&CK v19.x / OWASP
|
|
29
|
+
> ASVS 5.0.0-derived, owner + cadence in the manifest).
|
|
30
30
|
|
|
31
31
|
> You are a reviewer specialized in **pre-implementation threat analysis**.
|
|
32
32
|
> Your only job is to produce a compact threat model for a planned change —
|
|
@@ -215,8 +215,13 @@ run tests**.
|
|
|
215
215
|
*Threat Modeling: Designing for Security* (2014). Framing basis for the
|
|
216
216
|
Actors / Assets / Entry Points / Trust Boundaries / Abuse Cases rubric.
|
|
217
217
|
[learn.microsoft.com/en-us/security/engineering/threat-modeling-tool-threats](https://learn.microsoft.com/en-us/security/engineering/threat-modeling-tool-threats)
|
|
218
|
-
- **OWASP ASVS
|
|
219
|
-
Session Management (
|
|
218
|
+
- **OWASP ASVS v5.0.0** — Authorization (V8), Encoding and Sanitization (V1)
|
|
219
|
+
+ Validation and Business Logic (V2), Session Management (V7) — default
|
|
220
|
+
baseline for "Missing control" entries. Renumbered from 4.0.3's V4/V5/V3
|
|
221
|
+
per the standard's own 4.0→5.0 migration guide (`5.0/en/0x05-For-Users-Of-4.0.md`
|
|
222
|
+
in the ASVS repo) — 5.0.0 splits the old V5 Validation/Sanitization/Encoding
|
|
223
|
+
chapter into separate Encoding-and-Sanitization and Validation-and-Business-Logic
|
|
224
|
+
chapters, and drops direct CWE/NIST cross-mappings from the requirements.
|
|
220
225
|
[owasp.org/www-project-application-security-verification-standard/](https://owasp.org/www-project-application-security-verification-standard/)
|
|
221
226
|
- **OWASP Top 10 2021** — A01 Broken Access Control, A04 Insecure Design,
|
|
222
227
|
A05 Security Misconfiguration — cross-reference when naming abuse cases.
|
|
@@ -76,8 +76,8 @@
|
|
|
76
76
|
"owner": "package-maintainer",
|
|
77
77
|
"refresh_cadence": "quarterly",
|
|
78
78
|
"upstream": {
|
|
79
|
-
"repo": "derived: MITRE ATT&CK + CWE + OWASP API Top 10 / ASVS
|
|
80
|
-
"sha": "ATT&CK
|
|
81
|
-
"last_checked": "2026-
|
|
79
|
+
"repo": "derived: MITRE ATT&CK + CWE + OWASP API Top 10 / ASVS 5.0",
|
|
80
|
+
"sha": "re-derived 2026-09-27 against ATT&CK v19.x and ASVS 5.0.0: every ATT&CK id cited in threats.csv's Source Refs column (T1110, T1563, T1105, T1090, T1499, T1552, T1552.001, T1190, T1078.004) resolves in the current Enterprise matrix and none is deprecated or revoked \u2014 threats.csv itself carries no ASVS identifiers, so there is nothing to remap there. SKILL.md's References section cited ASVS 4.0.3's V3/V4/V5 by the old numbering; updated to 5.0.0's V7 Session Management, V8 Authorization, and V1 Encoding and Sanitization + V2 Validation and Business Logic, per the standard's own 4.0\u21925.0 migration guide",
|
|
81
|
+
"last_checked": "2026-09-18"
|
|
82
82
|
}
|
|
83
|
-
}
|
|
83
|
+
}
|
|
@@ -83,7 +83,15 @@ regressions are detectable. Pick the verdict commands per the project's
|
|
|
83
83
|
|
|
84
84
|
Each iteration is agent turns, never executing control-flow code:
|
|
85
85
|
|
|
86
|
-
1. **
|
|
86
|
+
1. **Read the failure, then revise** — before changing a line, inspect what the
|
|
87
|
+
previous run actually reported: which checks failed, the assertion text, and
|
|
88
|
+
whether this failure signature matches the last one. Analyze the existing
|
|
89
|
+
code path the failing check exercises rather than pattern-matching the error
|
|
90
|
+
string. A revision written without reading the failure is the blind retry
|
|
91
|
+
both the plateau rule below and
|
|
92
|
+
[`autonomous-execution`](../../rules/autonomous-execution.md) exist to stop —
|
|
93
|
+
and on attempt 1 there is no previous run, so this is the baseline green set
|
|
94
|
+
from step 1. Then make the smallest change toward the contract.
|
|
87
95
|
2. **Run** — execute the verdict commands; parse the **structured** result
|
|
88
96
|
(counts green/total, which checks failed). This is one tool call, read in
|
|
89
97
|
context.
|
|
@@ -183,6 +191,7 @@ verify-repair-loop
|
|
|
183
191
|
Contract: <one-line requirement> · threshold <X> · allow_regressions false
|
|
184
192
|
Attempts: <k>/<max> scores: [s1, s2, …] stop: threshold|plateau|cap|regression|reject
|
|
185
193
|
Verdict: DONE | DONE_WITH_CONCERNS | BLOCKED
|
|
194
|
+
run_terminal: success | blocked | exhausted | stagnated
|
|
186
195
|
Judge: <judge skill> → apply|revise|reject
|
|
187
196
|
Evidence: <green/total> · regressions: none | <named checks>
|
|
188
197
|
```
|
|
@@ -193,9 +202,34 @@ Required fields (ordered):
|
|
|
193
202
|
2. **Attempts** — `k/max`, the score history, and the exact stop reason
|
|
194
203
|
(`threshold` / `plateau` / `cap` / `regression` / `reject`).
|
|
195
204
|
3. **Verdict** — `DONE`, `DONE_WITH_CONCERNS`, or `BLOCKED`.
|
|
196
|
-
4. **
|
|
205
|
+
4. **run_terminal** — this loop's stop in the vocabulary every other loop in
|
|
206
|
+
this tree reports in. The verdict above is local to this skill; this field is
|
|
207
|
+
the one a reader can aggregate across the continuation hook, the self-fix
|
|
208
|
+
lanes and this loop without a per-surface translation table.
|
|
209
|
+
|
|
210
|
+
| stop reason | `run_terminal` | why |
|
|
211
|
+
|---|---|---|
|
|
212
|
+
| `threshold` (judge `apply`) | `success` | the contract is met |
|
|
213
|
+
| `cap` | `exhausted` | the attempt budget ran out — a bigger budget might help |
|
|
214
|
+
| `plateau` | `stagnated` | scores stopped moving — a bigger budget will not help |
|
|
215
|
+
| `regression` | `blocked` | a baseline-green check broke; the loop must not proceed |
|
|
216
|
+
| `reject` | `blocked` | the judge refused the work |
|
|
217
|
+
|
|
218
|
+
The value set is `RunTerminalState`, whose members are `success`,
|
|
219
|
+
`clean-no-op`, `blocked`, `approval-required`, `exhausted`, `stagnated` and
|
|
220
|
+
`premise-invalidated`. It is declared once, at
|
|
221
|
+
`src/scripts/_lib/outcome_vocabularies.ts` (`RUN_TERMINAL_STATES`), and
|
|
222
|
+
described in [`terminal-states`](../../agent-src/contexts/execution/terminal-states.md).
|
|
223
|
+
Never emit a value outside that set: a sixth stop reason maps onto an
|
|
224
|
+
existing member or it is not a terminal state.
|
|
225
|
+
|
|
226
|
+
`exhausted` and `stagnated` are deliberately distinct. Both mean "stopped
|
|
227
|
+
without a green", and they call for opposite responses — raise the budget
|
|
228
|
+
against the first, change approach against the second. Collapsing them loses
|
|
229
|
+
the only part of the stop a reader can act on.
|
|
230
|
+
5. **Judge** — the dispatched judge skill and its `apply` / `revise` /
|
|
197
231
|
`reject` verdict (omit only when the loop stopped before escalation).
|
|
198
|
-
|
|
232
|
+
6. **Evidence** — final `green/total` and any regressed checks by name.
|
|
199
233
|
|
|
200
234
|
## Examples
|
|
201
235
|
|
|
@@ -654,7 +654,7 @@ the canonical narrative lives in
|
|
|
654
654
|
| `commands.create_pr.api_paths` | glob list | `[]` | Optional globs pinning API-endpoint detection; empty = light heuristic, fail-open. |
|
|
655
655
|
| `verbosity.preview_artifacts` | `true`, `false` | `false` | Show generated commit messages, PR titles/bodies, branch names before acting. `false` = use generated content directly. See the token-frugality plate under `agents/roadmaps/` (Phase 2/3). |
|
|
656
656
|
| `verbosity.routine_confirmations` | `true`, `false` | `false` | Confirmation prompts for routine workflow steps when there is one obvious answer ("looks good — commit?"). Iron-Law gates (`commit-policy`, `scope-control` git-ops, `non-destructive-by-default`) ALWAYS ask regardless. |
|
|
657
|
-
| `verbosity.offer_council_in_delivery` | `true`, `false` | `false` | Offer "run AI Council on this?" inside delivery commands (`/feature-plan`, `/review-changes
|
|
657
|
+
| `verbosity.offer_council_in_delivery` | `true`, `false` | `false` | Offer "run AI Council on this?" inside delivery commands (`/feature-plan`, `/review-changes`). Council commands themselves are unaffected. `/roadmap:create` no longer reads it — under a mission the council is a step, resolved from `agent-config council:status`, never an offer. |
|
|
658
658
|
| `verbosity.post_action_reports` | `off`, `minimal`, `full` | `minimal` | Multi-line status / summary blocks after a successful action. `off` = no report; `minimal` = one-line confirmation; `full` = bullet list. |
|
|
659
659
|
| `verbosity.intent_announcements` | `true`, `false` | `false` | Intent announcements ("Let me check…", "Now I will…", "Found it") in skill bodies. `false` = act and emit the result. |
|
|
660
660
|
| `telegraph.speak` | `true`, `false` | `false` | Whether the telegraph-speak rule ships at all. `false` (default) = dormant: the projector omits the rule from `dist/router.json`, so its body never reaches a host. The rule body states its own grammar scope and carve-outs (numbered options, Iron-Law literals, code, paths), so this is the only lever. |
|
|
@@ -39,7 +39,7 @@ schema_version: 1
|
|
|
39
39
|
# CI guard: a release bump of `package.json` must update this value
|
|
40
40
|
# in lockstep — see scripts/check_template_pin_drift.ts (road-to-
|
|
41
41
|
# portable-runtime-and-update-check P3.3).
|
|
42
|
-
agent_config_version: "16.
|
|
42
|
+
agent_config_version: "16.1.0"
|
|
43
43
|
|
|
44
44
|
# --- Project identity ---
|
|
45
45
|
project:
|
|
@@ -64,6 +64,16 @@ that was never a judgement call.
|
|
|
64
64
|
"Target release: X.Y.Z", never plan git tags or deprecation dates. Release
|
|
65
65
|
and tag decisions belong to the user and are taken outside the roadmap.
|
|
66
66
|
This is enforced by [`scope-control`](../rules/scope-control.md#git-operations--permission-gated).
|
|
67
|
+
|
|
68
|
+
**What the prohibition does not reach — a state, not a schedule.** The five
|
|
69
|
+
sentences above are unchanged and stay the rule: a roadmap does not decide
|
|
70
|
+
*when* or *in which version* work ships. It MUST, however, declare any
|
|
71
|
+
intentionally unreleasable intermediate tree state, together with the
|
|
72
|
+
machine-verified condition that clears it, per rule 28. Naming a state that
|
|
73
|
+
must not be published is not a release decision — it is a fact about the tree
|
|
74
|
+
that the release path has no other way to learn, and today cannot learn: the
|
|
75
|
+
release entry points read no roadmap at all. Declaring the state is
|
|
76
|
+
mandatory; deciding what to do about it at a cut is still the operator's.
|
|
67
77
|
14. **No automatic branch switches mid-roadmap.** Roadmap work runs on the
|
|
68
78
|
branch the user is on. If a separate branch (spike, hotfix, experiment)
|
|
69
79
|
would be genuinely useful, the agent may propose it **once** while
|
|
@@ -231,6 +241,32 @@ that was never a judgement call.
|
|
|
231
241
|
edge source stays the single one already defined above; `relates:` never
|
|
232
242
|
becomes a second dependency source.
|
|
233
243
|
|
|
244
|
+
**Sibling block, same frontmatter — `delivery:`.** Optional, and unlike
|
|
245
|
+
`execution:` it describes what happens to the BRANCH rather than to the
|
|
246
|
+
run's interaction pattern:
|
|
247
|
+
|
|
248
|
+
```yaml
|
|
249
|
+
delivery:
|
|
250
|
+
pr_topology: stacked # single (default) | stacked
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
`pr_topology: stacked` declares a dependent series of pull requests. It is
|
|
254
|
+
a plan the owner writes before execution and is **never** chosen by the
|
|
255
|
+
agent and never asked about at roadmap creation — see the `delivery:` block
|
|
256
|
+
in `agent-settings.template.yml`, where all three keys are Class C for that
|
|
257
|
+
reason. A roadmap declaring `stacked` owes a `## PR plan` section naming
|
|
258
|
+
the series and the order; `single` owes nothing, which is why it is the
|
|
259
|
+
default.
|
|
260
|
+
|
|
261
|
+
**Not yet a live override, and this is the honest state rather than an
|
|
262
|
+
omission.** `load_agent_settings` has four layers and none of them is a
|
|
263
|
+
roadmap, so a `delivery:` block here is read by no code today. It is
|
|
264
|
+
documented now because the key it mirrors is Class C — the owner has to
|
|
265
|
+
have a place to write the plan that is not an agent-writable setting — and
|
|
266
|
+
the cascade layer that would read it is scheduled by ADR-268, not yet
|
|
267
|
+
built. Until it is, treat a `delivery:` block here as a note to the next
|
|
268
|
+
human reader rather than as configuration.
|
|
269
|
+
|
|
234
270
|
An explicit `relates: []` is a complete answer and the common one, but only
|
|
235
271
|
when it carries the probe's `scanned:` line as its justification:
|
|
236
272
|
|
|
@@ -301,6 +337,13 @@ that was never a judgement call.
|
|
|
301
337
|
step gated by a specific blocker may cross-reference it inline:
|
|
302
338
|
`- [ ] … <!-- blocked-by: <blocker-id> -->`.
|
|
303
339
|
|
|
340
|
+
**A blocker stops execution; a hold stops publication.** The two are not
|
|
341
|
+
interchangeable and never substitute for one another. A blocker says the work
|
|
342
|
+
cannot proceed and is cleared by a person; a release hold (rule 28) says the
|
|
343
|
+
work may proceed but its intermediate tree state must not ship, and is
|
|
344
|
+
cleared by a checkbox whose `verify:` a machine runs. A roadmap that is
|
|
345
|
+
merely unfinished has neither — incompleteness is not a release condition.
|
|
346
|
+
|
|
304
347
|
**A user-decision blocker's annotation records whether the question
|
|
305
348
|
was actually put.** Where the blocker's `Owner:` is the maintainer,
|
|
306
349
|
the user or the owner, the marker carries an `asked:` field —
|
|
@@ -400,6 +443,22 @@ that was never a judgement call.
|
|
|
400
443
|
on nothing until an author declares a class and there is no backlog
|
|
401
444
|
to grandfather.
|
|
402
445
|
|
|
446
|
+
**A judgement call is never parked here.** A blocker records a decision
|
|
447
|
+
the agent **correctly did not own**. A technical judgement call — two
|
|
448
|
+
valid architectures, a dependency trade-off, an unclear boundary with no
|
|
449
|
+
new product semantics — is not one of those: it routes back through the
|
|
450
|
+
closure pass and is resolved at the lowest rung that owns it (evidence,
|
|
451
|
+
convention, the agent, an independent session, the council, the team),
|
|
452
|
+
then recorded as a `## Decisions` row per rule 27. A technical decision
|
|
453
|
+
does not become owner-owned because it is hard (ADR-268 § 10).
|
|
454
|
+
|
|
455
|
+
An entry MAY declare `- **Ownership:** <class>`, and when it does the
|
|
456
|
+
class must be one of the three owner-owned ones — `product-owned`,
|
|
457
|
+
`business-owned`, `destructive-owned`. A technical class there is the
|
|
458
|
+
parked judgement call this retires, and `lint_roadmap_blockers` reds it.
|
|
459
|
+
The field is optional and HARD rather than ratcheted, on the same
|
|
460
|
+
no-backlog-to-grandfather ground as `Class:`.
|
|
461
|
+
|
|
403
462
|
**Legacy fallback.** A body-level `> Blocked until <condition>`
|
|
404
463
|
note (the follow-up-roadmap convention from rule 17) is parsed by
|
|
405
464
|
the dashboard generator as one implicit roadmap-level blocker
|
|
@@ -582,6 +641,126 @@ that was never a judgement call.
|
|
|
582
641
|
tracked estate; blocking is earned by tracked-scope evidence, not
|
|
583
642
|
assumed).
|
|
584
643
|
|
|
644
|
+
27. **A ready roadmap carries no unresolved decision — it carries a
|
|
645
|
+
`## Decisions` table.** A plan enters execution as an **execution
|
|
646
|
+
contract**: every foreseeable decision closed before the first step,
|
|
647
|
+
so a long run never meets a question planning could have closed.
|
|
648
|
+
|
|
649
|
+
The section is a six-column table, and the two vocabularies in it are
|
|
650
|
+
closed sets:
|
|
651
|
+
|
|
652
|
+
```markdown
|
|
653
|
+
## Decisions
|
|
654
|
+
|
|
655
|
+
| ID | ownership | resolved by | decision | evidence | revisit if |
|
|
656
|
+
|---|---|---|---|---|---|
|
|
657
|
+
| D1 | contested-technical | council:2026-09-13 | NDJSON on disk | streaming read at bounded RSS | the reader stops streaming |
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
`ownership` is one of the eight ownership classes — `deterministic`,
|
|
661
|
+
`reversible-technical`, `contested-technical`, `critical-technical`,
|
|
662
|
+
`product-owned`, `business-owned`, `destructive-owned`,
|
|
663
|
+
`spend-exhaustion`. The axis is **ownership, not impact**: a technical
|
|
664
|
+
decision does not become owner-owned because it is hard
|
|
665
|
+
(ADR-268 § 10). `resolved by` is one of `evidence`, `agent`,
|
|
666
|
+
`independent:<session or model>`, `council:<record>`, `team:<record>`,
|
|
667
|
+
`owner` — the prefixed forms carry their record, because a resolver
|
|
668
|
+
with no record is a claim rather than a resolution.
|
|
669
|
+
|
|
670
|
+
`revisit if` names the condition that reopens the row. Execution reads
|
|
671
|
+
the table **before any step**, and a closed decision is re-asked only
|
|
672
|
+
when its `revisit if` condition became true — not because a context
|
|
673
|
+
reset lost it, which is the repeat the ask census counts.
|
|
674
|
+
|
|
675
|
+
Enforced by `lint_decision_classes`: in a ready roadmap an unresolved
|
|
676
|
+
marker (`TBD`, *to be decided*, *decide later*, *open question*)
|
|
677
|
+
outside the section is a finding, and the same marker resolved into a
|
|
678
|
+
row is not. `## Blockers` is the other discharge — a five-field
|
|
679
|
+
structured blocker IS the record of a decision the agent correctly did
|
|
680
|
+
not own, so an open item there is not an unclosed one.
|
|
681
|
+
|
|
682
|
+
The section is owed where there is a decision to record. A plan that
|
|
683
|
+
closed everything inline carries no table and no marker, and is
|
|
684
|
+
complete; an empty table written to satisfy a template records
|
|
685
|
+
nothing, exactly as rule 25 says of a perfunctory pre-mortem.
|
|
686
|
+
|
|
687
|
+
28. **Release holds — declare an unreleasable intermediate state, or there is
|
|
688
|
+
not one.** A roadmap whose intermediate tree state must not be published
|
|
689
|
+
declares that state in a `## Release holds` section. Nothing else in the
|
|
690
|
+
repository can express it, and the release path reads no roadmap today, so
|
|
691
|
+
an undeclared unreleasable state is invisible to every release boundary.
|
|
692
|
+
|
|
693
|
+
**Non-goal, stated first because it is the failure mode closest to hand:
|
|
694
|
+
roadmap *incompleteness* is never a release condition.** An unfinished
|
|
695
|
+
roadmap does not block a release, has never blocked one, and must not start
|
|
696
|
+
to. A hold is a positive declaration about a named tree state, never a side
|
|
697
|
+
effect of open checkboxes.
|
|
698
|
+
|
|
699
|
+
**Authoring order — `re-sequence → guard → hold`, in that order.** A hold is
|
|
700
|
+
the last resort, not the first tool:
|
|
701
|
+
|
|
702
|
+
1. **Re-sequence.** Can the phases be cut so that no intermediate state is
|
|
703
|
+
broken? A continuous shape needs no hold and is always preferred.
|
|
704
|
+
2. **Guard.** Can the half-built surface be hidden behind a flag, an unwired
|
|
705
|
+
entry point, or a default that keeps it inert? A guarded state is
|
|
706
|
+
publishable and needs no hold.
|
|
707
|
+
3. **Hold.** Only when neither works. Every hold entry therefore carries a
|
|
708
|
+
mandatory `Why not a guard:` field naming the concrete reason the guard
|
|
709
|
+
rung failed. A hold entry without it is malformed and reddens CI.
|
|
710
|
+
|
|
711
|
+
**Entry shape** (one entry per hold, inside `## Release holds`):
|
|
712
|
+
|
|
713
|
+
```markdown
|
|
714
|
+
## Release holds
|
|
715
|
+
|
|
716
|
+
### hold: <kebab-id>
|
|
717
|
+
- **Channel:** all <!-- all | latest -->
|
|
718
|
+
- **Opened by:** <phase.step> <!-- the checkbox whose [x] opens the window -->
|
|
719
|
+
- **Cleared by:** <phase.step> <!-- the checkbox whose [x] closes it -->
|
|
720
|
+
- **State:** {the one sentence naming what is broken in the tree while open.}
|
|
721
|
+
- **Why not a guard:** {why rung 2 failed, concretely.}
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
**Marker grammar.** Both named steps carry an inline marker so the binding is
|
|
725
|
+
readable from the checkbox and not only from the section:
|
|
726
|
+
`- [ ] … <!-- opens-hold: <hold-id> -->` and
|
|
727
|
+
`- [ ] … <!-- clears-hold: <hold-id> -->`. The clearing step MUST carry a
|
|
728
|
+
`verify:` field (rule 23) — a hold cleared by an unverified flip is a hold
|
|
729
|
+
cleared by assertion.
|
|
730
|
+
|
|
731
|
+
**Channel vocabulary.** `all` (the default, and what an omitted `Channel:`
|
|
732
|
+
parses to) refuses every cut. `latest` refuses a stable `X.Y.Z` cut and
|
|
733
|
+
permits a `-next.N` prerelease, for a state safe to publish to an opt-in
|
|
734
|
+
channel but not to the default one. There is no third value and no override:
|
|
735
|
+
a plain `X.Y.Z` cut is never silently converted to a prerelease, and the
|
|
736
|
+
choice between finishing the clearing step, cutting `-next.N`, and using a
|
|
737
|
+
release line stays the operator's.
|
|
738
|
+
|
|
739
|
+
**State table.** A hold is in exactly one of four states, and only the first
|
|
740
|
+
is publishable:
|
|
741
|
+
|
|
742
|
+
| State | How it is reached | Release boundary |
|
|
743
|
+
|---|---|---|
|
|
744
|
+
| `unopened` | the opening checkbox is not `[x]` | permits |
|
|
745
|
+
| `open` | opener `[x]`, clearer not `[x]` | **refuses**, per `Channel:` |
|
|
746
|
+
| `cleared` | both `[x]` | permits |
|
|
747
|
+
| `not-evaluable` | the declaration is malformed, the file unreadable, or the evaluator errored or timed out | **refuses**, always, on every channel |
|
|
748
|
+
|
|
749
|
+
`not-evaluable` refusing is the load-bearing row: there is no path on which
|
|
750
|
+
"could not evaluate" reads as safe. A malformed declaration additionally
|
|
751
|
+
reddens normal CI, so a broken hold cannot fail open by being unparseable.
|
|
752
|
+
|
|
753
|
+
**Per-folder lifecycle.** A window does not disappear by moving the file.
|
|
754
|
+
A roadmap with an open window may not be moved to `archive/` or `skipped/` —
|
|
755
|
+
the move is refused naming the hold id. It may be moved to `later/`, and the
|
|
756
|
+
open window is then named in the `entry_condition.what` part; it still lists
|
|
757
|
+
and still refuses. Deletion is a known residual, not a mitigation: rule 12
|
|
758
|
+
already forbids it and no gate can see a file that is gone.
|
|
759
|
+
|
|
760
|
+
**No versions inside a hold entry.** Rule 13's prohibition applies inside
|
|
761
|
+
`## Release holds` exactly as it does everywhere else. A hold names a *state*
|
|
762
|
+
and its clearing *checkbox*; it never names a version, a tag, or a date.
|
|
763
|
+
|
|
585
764
|
---
|
|
586
765
|
|
|
587
766
|
## Quality Gates (remote CI by default)
|
|
@@ -672,6 +851,15 @@ complexity: lightweight
|
|
|
672
851
|
- [ ] {Observable, testable criterion}
|
|
673
852
|
- [ ] All quality gates pass (PHPStan, Rector, tests)
|
|
674
853
|
|
|
854
|
+
<!-- ## Decisions — INCLUDE when the closure pass closed a decision this
|
|
855
|
+
plan would otherwise have met mid-run (rule 27). OMIT entirely when
|
|
856
|
+
nothing was open: an empty table records nothing.
|
|
857
|
+
## Decisions
|
|
858
|
+
|
|
859
|
+
| ID | ownership | resolved by | decision | evidence | revisit if |
|
|
860
|
+
|---|---|---|---|---|---|
|
|
861
|
+
| D1 | {ownership class} | {resolver} | {what was decided} | {file:line, record, probe} | {condition that reopens it} | -->
|
|
862
|
+
|
|
675
863
|
<!-- ## Blockers — INCLUDE ONLY when a gate exists that only the user /
|
|
676
864
|
a maintainer can clear (decision, external dependency, evidence
|
|
677
865
|
threshold, soak window). OMIT entirely when there are none — see
|
|
@@ -78,6 +78,41 @@ export const VOLATILE_KEYS: ReadonlyArray<string> = [
|
|
|
78
78
|
/** Why the loop stopped, or that it has budget left. */
|
|
79
79
|
export type SelfFixKind = 'retry' | 'exhausted' | 'no_progress';
|
|
80
80
|
|
|
81
|
+
/**
|
|
82
|
+
* `SelfFixKind` in the vocabulary a reader can aggregate across surfaces.
|
|
83
|
+
*
|
|
84
|
+
* `Outcome.PARTIAL` says the loop stopped without a green; it cannot say
|
|
85
|
+
* whether the budget ran out or the target stopped moving, and those want
|
|
86
|
+
* different responses — a bigger budget against the first, a different
|
|
87
|
+
* approach against the second. Until now the distinction left this module only
|
|
88
|
+
* inside a free-text `message`, so the continuation hook's stops were
|
|
89
|
+
* countable and this loop's were not.
|
|
90
|
+
*
|
|
91
|
+
* The two values are members of `RunTerminalState`, whose authoritative
|
|
92
|
+
* declaration is `src/scripts/_lib/outcome_vocabularies.ts:RUN_TERMINAL_STATES`
|
|
93
|
+
* and whose prose home is `contexts/execution/terminal-states.md`. They are
|
|
94
|
+
* written as literals rather than imported because this file is a TEMPLATE:
|
|
95
|
+
* it ships into consumer projects that have no `src/scripts/_lib` to import
|
|
96
|
+
* from, and reaching across that boundary would break every install. It is a
|
|
97
|
+
* two-member projection across a packaging boundary, not a second vocabulary —
|
|
98
|
+
* nothing here may add a member the registry does not have.
|
|
99
|
+
*/
|
|
100
|
+
export const RUN_TERMINAL_BY_KIND: Readonly<Record<Exclude<SelfFixKind, 'retry'>, string>> = {
|
|
101
|
+
exhausted: 'exhausted',
|
|
102
|
+
no_progress: 'stagnated',
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* The run-terminal value for a decision, or `null` while the loop is still live.
|
|
107
|
+
*
|
|
108
|
+
* `retry` has no terminal by construction — the loop has not stopped — and the
|
|
109
|
+
* null is returned rather than defaulted so a caller cannot accidentally stamp
|
|
110
|
+
* a terminal value onto a run that is still going.
|
|
111
|
+
*/
|
|
112
|
+
export function run_terminal_for(kind: SelfFixKind): string | null {
|
|
113
|
+
return kind === 'retry' ? null : RUN_TERMINAL_BY_KIND[kind];
|
|
114
|
+
}
|
|
115
|
+
|
|
81
116
|
/** Verdict of {@link decide} — pure, so the caller owns every mutation. */
|
|
82
117
|
export interface SelfFixDecision {
|
|
83
118
|
kind: SelfFixKind;
|
|
@@ -147,6 +182,27 @@ export function record_attempt(state: DeliveryState, lane: string, signature: st
|
|
|
147
182
|
state.self_fix = container;
|
|
148
183
|
}
|
|
149
184
|
|
|
185
|
+
/**
|
|
186
|
+
* Stamp the lane's run-terminal value onto `state.self_fix`.
|
|
187
|
+
*
|
|
188
|
+
* Written into the state the module already owns and the dispatcher already
|
|
189
|
+
* persists, rather than onto `StepResult` — `StepResult` carries `outcome`,
|
|
190
|
+
* `questions` and `message` and is shared by every directive in the engine, so
|
|
191
|
+
* widening it for one loop's stop reason would be a change to all of them.
|
|
192
|
+
*
|
|
193
|
+
* A `retry` decision writes nothing: the loop has not stopped, and a terminal
|
|
194
|
+
* value recorded mid-loop would be read as one by anything aggregating the
|
|
195
|
+
* field.
|
|
196
|
+
*/
|
|
197
|
+
export function record_run_terminal(state: DeliveryState, lane: string, decision: SelfFixDecision): void {
|
|
198
|
+
const run_terminal = run_terminal_for(decision.kind);
|
|
199
|
+
if (run_terminal === null) return;
|
|
200
|
+
const container = _pyTruthy(state.self_fix) ? (state.self_fix as Record<string, Any>) : {};
|
|
201
|
+
const lane_state = _lane_state(state, lane);
|
|
202
|
+
container[lane] = { ...lane_state, run_terminal };
|
|
203
|
+
state.self_fix = container;
|
|
204
|
+
}
|
|
205
|
+
|
|
150
206
|
/** DoD entries the agent has not recorded as proven. Never inferred. */
|
|
151
207
|
export function unmet_dod(state: DeliveryState): Array<Record<string, Any>> {
|
|
152
208
|
const dod = (state.ticket ?? {})['dod'];
|
|
@@ -213,8 +269,11 @@ export function partial_exit(args: {
|
|
|
213
269
|
decision: SelfFixDecision;
|
|
214
270
|
unmet: Array<Record<string, Any>>;
|
|
215
271
|
rerun_directive: string;
|
|
272
|
+
/** Written the run-terminal value onto, when the caller has the state in hand. */
|
|
273
|
+
state?: DeliveryState;
|
|
216
274
|
}): StepResult {
|
|
217
|
-
const { lane, ticket_id, verdict, decision, unmet, rerun_directive } = args;
|
|
275
|
+
const { lane, ticket_id, verdict, decision, unmet, rerun_directive, state } = args;
|
|
276
|
+
if (state !== undefined) record_run_terminal(state, lane, decision);
|
|
218
277
|
const reason =
|
|
219
278
|
decision.kind === 'no_progress'
|
|
220
279
|
? `two consecutive attempts produced an identical \`${lane}\` verdict, ` +
|
|
@@ -244,7 +303,8 @@ export function partial_exit(args: {
|
|
|
244
303
|
],
|
|
245
304
|
message:
|
|
246
305
|
`Ticket ${ticket_id} ${lane} verdict is \`${String(verdict)}\` after ` +
|
|
247
|
-
`${decision.attempts} self-fix attempt(s) (${decision.kind}); exiting PARTIAL
|
|
306
|
+
`${decision.attempts} self-fix attempt(s) (${decision.kind}); exiting PARTIAL ` +
|
|
307
|
+
`(run_terminal: ${String(run_terminal_for(decision.kind))}).`,
|
|
248
308
|
});
|
|
249
309
|
}
|
|
250
310
|
|