@event4u/agent-config 9.34.0 → 9.36.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/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +64 -77
- package/CONTRIBUTING.md +23 -14
- package/dist/agent-src/commands/analyze/reference-repo.md +135 -42
- package/dist/agent-src/commands/roadmap/next.md +37 -5
- package/dist/agent-src/contexts/augment-infrastructure.md +1 -1
- package/dist/agent-src/rules/design-review-after-ui-write.md +53 -6
- package/dist/agent-src/rules/improve-before-implement.md +1 -1
- package/dist/agent-src/rules/ui-audit-gate.md +35 -0
- package/dist/agent-src/scripts/roadmap_gates.ts +119 -4
- package/dist/agent-src/skills/design-system-capture/SKILL.md +2 -2
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +1 -1
- package/dist/agent-src/skills/fe-design/SKILL.md +84 -12
- package/dist/agent-src/skills/fe-design/evals/triggers.json +11 -3
- package/dist/agent-src/skills/prediction-pool-optimizer/SKILL.md +5 -5
- package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +1 -1
- package/dist/agent-src/skills/skill-writing/SKILL.md +24 -0
- package/dist/agent-src/skills/subagent-orchestration/prompts/README.md +29 -0
- package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +25 -0
- package/dist/agent-src/templates/AGENTS.md +1 -1
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/scripts/memory_lookup.ts +1 -2
- package/dist/agent-src/templates/scripts/memory_signal.ts +2 -4
- package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/decision_gate.ts +35 -5
- package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/staged_confirmation.ts +252 -0
- package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/staged_confirmation_store.ts +307 -0
- package/dist/cli/registry.js +2 -2
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli-delegate/{chunk-YPAWXXXR.js → chunk-55RI5UXK.js} +17 -0
- package/dist/cli-delegate/{chunk-UVKNIJH2.js → chunk-JP53LNVT.js} +12 -0
- package/dist/cli-delegate/{chunk-736JCWLM.js → chunk-M2DPGFZ4.js} +10 -0
- package/dist/cli-delegate/{chunk-MA4GFWDY.js → chunk-NR7HSN3P.js} +2 -2
- package/dist/cli-delegate/{chunk-REMEZSVP.js → chunk-SFGARMAB.js} +13 -3
- package/dist/cli-delegate/{chunk-DS6BLDMG.js → chunk-U7CMAIOC.js} +7 -2
- package/dist/cli-delegate/cmd_conformance.js +4 -4
- package/dist/cli-delegate/cmd_doctor.js +3 -3
- package/dist/cli-delegate/cmd_export.js +3 -3
- package/dist/cli-delegate/cmd_handoff.js +1 -1
- package/dist/cli-delegate/cmd_migrate.js +1 -1
- package/dist/cli-delegate/cmd_prune.js +3 -3
- package/dist/cli-delegate/cmd_refresh.js +1 -1
- package/dist/cli-delegate/cmd_session_recycle.js +8 -1
- package/dist/cli-delegate/cmd_settings_migrate.js +3 -3
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +3 -3
- package/dist/cli-delegate/cmd_uninstall.js +3 -3
- package/dist/cli-delegate/cmd_upgrade.js +1 -1
- package/dist/cli-delegate/cmd_validate.js +3 -3
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +14 -14
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +1 -1
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +2 -2
- package/dist/discovery/trust-report.md +1 -1
- package/dist/discovery/workspaces.json +2 -2
- package/dist/hooks/dispatch.js +789 -401
- package/dist/install/install.mjs +21 -4
- package/dist/mcp/registry-manifest.json +2 -2
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +99 -7
- package/dist/router.json +1 -1
- package/dist/server/schemas/settings.js +6 -0
- package/dist/server/schemas/settings.js.map +1 -1
- package/docs/contracts/settings-classes.md +5 -2
- package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +46 -4
- package/package.json +2 -2
- package/src/agent-src/scripts/roadmap_gates.ts +119 -4
- package/src/agent-src/templates/AGENTS.md +1 -1
- package/src/agent-src/templates/scripts/memory_lookup.ts +1 -2
- package/src/agent-src/templates/scripts/memory_signal.ts +2 -4
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/decision_gate.ts +35 -5
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/staged_confirmation.ts +252 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/staged_confirmation_store.ts +307 -0
- package/src/config/agent-settings.template.yml +43 -2
- package/src/config/gate-coverage.yml +12 -0
- package/src/config/quorum-attendance-budget.json +10 -2
- package/src/scripts/_cli/cmd_doctor.ts +32 -0
- package/src/scripts/_cli/cmd_migrate.ts +26 -3
- package/src/scripts/_cli/cmd_refresh.ts +29 -0
- package/src/scripts/_cli/cmd_session_recycle.ts +40 -2
- package/src/scripts/_dispatch.bash +6 -2
- package/src/scripts/_lib/hook_settings.ts +79 -0
- package/src/scripts/_lib/session_register.ts +67 -1
- package/src/scripts/_lib/ui_surface.ts +97 -0
- package/src/scripts/ai_council/config.ts +60 -0
- package/src/scripts/ai_council/events_log.ts +103 -4
- package/src/scripts/ai_council/quorum.ts +83 -6
- package/src/scripts/capture_skill_catalogue.ts +483 -0
- package/src/scripts/council_cli.ts +36 -1
- package/src/scripts/hook_manifest.yaml +18 -3
- package/src/scripts/hooks/concern_registry.ts +2 -0
- package/src/scripts/hooks/design_slop_hook.ts +1 -1
- package/src/scripts/hooks/turn_end_gate_hook.ts +172 -11
- package/src/scripts/hooks/ui_route_nudge_hook.ts +250 -0
- package/src/scripts/lint_framework_leakage.ts +195 -28
- package/src/scripts/lint_framework_leakage_allowlist.json +94 -86
- package/src/scripts/lint_roadmap_complexity.ts +60 -0
- package/src/scripts/lint_rule_skill_pack_reach.ts +263 -0
- package/src/scripts/memory_lookup.ts +1 -2
- package/src/scripts/report_consultation_rate.ts +358 -0
- package/src/scripts/report_skill_activation.ts +5 -1
- package/src/scripts/schemas/command.schema.json +4 -0
- package/src/scripts/schemas/skill.schema.json +4 -0
- package/src/scripts/session_register_hook.ts +238 -18
- package/src/scripts/sessions_cli.ts +377 -12
- package/src/server/schemas/settings.ts +12 -0
- /package/dist/agent-src/skills/design-system-capture/{reference → references}/design-system-json.md +0 -0
- /package/dist/agent-src/skills/prediction-pool-optimizer/{reference → references}/ev-fixtures.md +0 -0
- /package/dist/agent-src/skills/prediction-pool-optimizer/{reference → references}/odds-and-bonus.md +0 -0
- /package/dist/agent-src/skills/react-shadcn-ui/{reference → references}/registry.md +0 -0
|
@@ -6,6 +6,14 @@ description: "UI written or changed — review it against the design contract be
|
|
|
6
6
|
triggers:
|
|
7
7
|
- path_prefix: "resources/views/"
|
|
8
8
|
- path_prefix: "resources/js/"
|
|
9
|
+
- path_prefix: "components/"
|
|
10
|
+
- path_prefix: "src/components/"
|
|
11
|
+
- path_prefix: "pages/"
|
|
12
|
+
- file_pattern: "*.vue"
|
|
13
|
+
- file_pattern: "*.svelte"
|
|
14
|
+
- file_pattern: "*.tsx"
|
|
15
|
+
- file_pattern: "*.jsx"
|
|
16
|
+
- file_pattern: "*.blade.php"
|
|
9
17
|
- keyword: "component"
|
|
10
18
|
- keyword: "design token"
|
|
11
19
|
routes_to:
|
|
@@ -20,6 +28,14 @@ collision_ok:
|
|
|
20
28
|
"design token": "same surface, opposite side: ui-audit-gate inventories tokens before the write, this reviews what the write emitted"
|
|
21
29
|
"resources/views/": "both halves of one UI loop fire on the same path — audit before, review after; neither substitutes for the other"
|
|
22
30
|
"resources/js/": "both halves of one UI loop fire on the same path — audit before, review after; neither substitutes for the other"
|
|
31
|
+
"components/": "both halves of one UI loop fire on the same path — audit before, review after; neither substitutes for the other"
|
|
32
|
+
"src/components/": "both halves of one UI loop fire on the same path — audit before, review after; neither substitutes for the other"
|
|
33
|
+
"pages/": "both halves of one UI loop fire on the same path — audit before, review after; neither substitutes for the other"
|
|
34
|
+
"*.vue": "one component file, two obligations: inventory before the write, review after it"
|
|
35
|
+
"*.svelte": "one component file, two obligations: inventory before the write, review after it"
|
|
36
|
+
"*.tsx": "one component file, two obligations: inventory before the write, review after it"
|
|
37
|
+
"*.jsx": "one component file, two obligations: inventory before the write, review after it"
|
|
38
|
+
"*.blade.php": "one template file, two obligations: inventory before the write, review after it"
|
|
23
39
|
# obligation: line 39
|
|
24
40
|
obligation_frequency: "per-edit"
|
|
25
41
|
---
|
|
@@ -87,18 +103,49 @@ enforcement. So this rule ships `enforced_by: none`, the same honesty boundary
|
|
|
87
103
|
for their own obligations, rather than pretending a satisfiable-by-assertion
|
|
88
104
|
condition is a gate.
|
|
89
105
|
|
|
106
|
+
**A runtime carrier now exists, and it does not change that.** The
|
|
107
|
+
`ui-route-nudge` PreToolUse concern emits one warning on a UI write with no
|
|
108
|
+
design consultation latched this session.
|
|
109
|
+
|
|
110
|
+
It runs **parallel** to this rule rather than consuming it. Nothing in the tree
|
|
111
|
+
reads this frontmatter at session time; the concern decides what counts as a UI
|
|
112
|
+
surface from `src/scripts/_lib/ui_surface.ts`, and the `keyword:` triggers here
|
|
113
|
+
still have no runtime consumer. A test — not a code path — keeps the two from
|
|
114
|
+
drifting: `ui_rule_triggers.test.ts` asserts every `file_pattern` declared here
|
|
115
|
+
is accepted by that predicate.
|
|
116
|
+
|
|
117
|
+
Warn-only, capped at two nudges per session, default-OFF, bound only on hosts
|
|
118
|
+
carrying a `pre_tool_use` slot. A nudge that can be ignored is not enforcement,
|
|
119
|
+
so `enforced_by:` stays `none` — it moves the day a mechanism can refuse, not
|
|
120
|
+
the day a reminder appears. `agent-config hooks:status` answers whether the
|
|
121
|
+
concern is bound on the host you are actually on.
|
|
122
|
+
|
|
90
123
|
What that leaves, and it is the useful part: the write side now has a named
|
|
91
124
|
obligation and a route to the skill that discharges it, where before it had
|
|
92
125
|
neither. Full enforcement needs the work-engine `review`/`polish` gates (which
|
|
93
126
|
already act on `a11y_violation` and `token_violation` findings) or pack-scoped
|
|
94
127
|
rule projection — a maintainer decision, never an automated one.
|
|
95
128
|
|
|
96
|
-
One asymmetry worth stating: `design-review`
|
|
97
|
-
this rule is scoped to `frontend-design`. The
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
129
|
+
One asymmetry worth stating, in the direction it actually runs: `design-review`
|
|
130
|
+
lives in `engineering-base` while this rule is scoped to `frontend-design`. The
|
|
131
|
+
route still resolves — a rule may name a skill from another pack.
|
|
132
|
+
|
|
133
|
+
The case this paragraph used to describe — `frontend-design` installed without
|
|
134
|
+
`engineering-base`, so the obligation arrives without the skill — **cannot
|
|
135
|
+
occur**: `frontend-design` declares `requires: [engineering-base]`, and the
|
|
136
|
+
resolver expands that graph transitively. The real gap is the reverse and was
|
|
137
|
+
undocumented: an **`engineering-base`-only** install (a plain `laravel` or
|
|
138
|
+
`react` consumer, since both only *suggest* `frontend-design`) carries
|
|
139
|
+
`existing-ui-audit`, `design-review` and `fe-design` while carrying **no rule
|
|
140
|
+
that routes to them**. It bites only where pack-scoped rule projection is
|
|
141
|
+
active — `rules.packs` ships inactive, so a default install still receives both
|
|
142
|
+
rules — which makes it a latent defect rather than a live one, and exactly the
|
|
143
|
+
kind that surfaces the day the projection axis is switched on.
|
|
144
|
+
|
|
145
|
+
`lint_rule_skill_pack_reach` is the invariant that keeps this honest: no rule
|
|
146
|
+
may route to a skill a pack-legal install of that rule's packs cannot receive.
|
|
147
|
+
`accessibility-auditor` remains a second route for the independent reason that
|
|
148
|
+
the a11y half of the review should not depend on the pairing at all.
|
|
102
149
|
|
|
103
150
|
## Failure modes
|
|
104
151
|
|
|
@@ -44,7 +44,7 @@ Before implementing:
|
|
|
44
44
|
|
|
45
45
|
## Demand gate — should this exist? (build / defer)
|
|
46
46
|
|
|
47
|
-
On a "build me an app / add this feature" ask, ONE reflexive pre-check before the three checks: **who asked · what breaks if unbuilt · what's the evidence?**
|
|
47
|
+
On a "build me an app / add this feature" ask, ONE reflexive pre-check before the three checks: **who asked · what breaks if unbuilt · what's the evidence?** **Read the addressee first** — `project.audience` (`agent-config settings:get project.audience`, absent → `public`): the demand hierarchy measures **market** demand and is meaningless where no market is intended, so at `self` the check is inert and the work is classified `L-self` → **build**. With a market: recommend **build** at a real retention/activation blocker (evidence, not anxiety); else **defer/validate**, naming the missing evidence. Never gate a roadmap on a user population the project is not meant to have. Advisory — "just build it" proceeds immediately; no network lookup. Hierarchy + build/defer table: guideline § 8-pre.
|
|
48
48
|
|
|
49
49
|
## The solution-size ladder — stop at the first rung that works
|
|
50
50
|
|
|
@@ -6,6 +6,14 @@ description: "Writing/editing UI — components, screens, layouts, design tokens
|
|
|
6
6
|
triggers:
|
|
7
7
|
- path_prefix: "resources/views/"
|
|
8
8
|
- path_prefix: "resources/js/"
|
|
9
|
+
- path_prefix: "components/"
|
|
10
|
+
- path_prefix: "src/components/"
|
|
11
|
+
- path_prefix: "pages/"
|
|
12
|
+
- file_pattern: "*.vue"
|
|
13
|
+
- file_pattern: "*.svelte"
|
|
14
|
+
- file_pattern: "*.tsx"
|
|
15
|
+
- file_pattern: "*.jsx"
|
|
16
|
+
- file_pattern: "*.blade.php"
|
|
9
17
|
- keyword: "component"
|
|
10
18
|
- keyword: "design token"
|
|
11
19
|
routes_to:
|
|
@@ -21,6 +29,14 @@ collision_ok:
|
|
|
21
29
|
"design token": "same surface, opposite side: this inventories tokens before the write, design-review-after-ui-write reviews what the write emitted"
|
|
22
30
|
"resources/views/": "both halves of one UI loop fire on the same path — audit before, review after; neither substitutes for the other"
|
|
23
31
|
"resources/js/": "both halves of one UI loop fire on the same path — audit before, review after; neither substitutes for the other"
|
|
32
|
+
"components/": "both halves of one UI loop fire on the same path — audit before, review after; neither substitutes for the other"
|
|
33
|
+
"src/components/": "both halves of one UI loop fire on the same path — audit before, review after; neither substitutes for the other"
|
|
34
|
+
"pages/": "both halves of one UI loop fire on the same path — audit before, review after; neither substitutes for the other"
|
|
35
|
+
"*.vue": "one component file, two obligations: inventory before the write, review after it"
|
|
36
|
+
"*.svelte": "one component file, two obligations: inventory before the write, review after it"
|
|
37
|
+
"*.tsx": "one component file, two obligations: inventory before the write, review after it"
|
|
38
|
+
"*.jsx": "one component file, two obligations: inventory before the write, review after it"
|
|
39
|
+
"*.blade.php": "one template file, two obligations: inventory before the write, review after it"
|
|
24
40
|
# obligation: line 39
|
|
25
41
|
obligation_frequency: "per-edit"
|
|
26
42
|
---
|
|
@@ -91,6 +107,25 @@ Full enforcement requires the dispatcher (or the `frontend-design` pack once
|
|
|
91
107
|
pack-scoped rule projection is enabled; that flip is a maintainer decision,
|
|
92
108
|
never an automated one).
|
|
93
109
|
|
|
110
|
+
**A runtime carrier now exists, and it does not change the verdict.** The
|
|
111
|
+
`ui-route-nudge` PreToolUse concern warns once on a UI write with no design
|
|
112
|
+
consultation latched this session.
|
|
113
|
+
|
|
114
|
+
It is a **parallel** mechanism, not a consumer of the triggers above — the
|
|
115
|
+
distinction matters and the earlier wording here got it wrong. The concern
|
|
116
|
+
decides "is this a UI surface" from `src/scripts/_lib/ui_surface.ts`; nothing
|
|
117
|
+
in the tree parses this frontmatter at session time, so the `keyword:` triggers
|
|
118
|
+
still have no runtime consumer at all, and the two sets can drift. What holds
|
|
119
|
+
them together is a test, not a dependency: `ui_rule_triggers.test.ts` asserts
|
|
120
|
+
every `file_pattern` declared here is accepted by that predicate. The predicate
|
|
121
|
+
is deliberately wider (it also covers `.css`, `.scss`, `.astro`), because a
|
|
122
|
+
measurement denominator and a routing trigger are not the same population.
|
|
123
|
+
|
|
124
|
+
Warn-only, capped at two per session, default-OFF, bound only where a
|
|
125
|
+
`pre_tool_use` slot exists. A reminder that can be ignored is not a gate, so
|
|
126
|
+
`enforced_by:` stays `none`. Run `agent-config hooks:status` for the host you
|
|
127
|
+
are on rather than trusting this sentence.
|
|
128
|
+
|
|
94
129
|
## Failure modes
|
|
95
130
|
|
|
96
131
|
- Writing the component first and "thinking about reuse later".
|
|
@@ -46,6 +46,13 @@
|
|
|
46
46
|
* ./agent-config gates --all # every open blocker, grouped by owner
|
|
47
47
|
* ./agent-config gates --json # machine-readable
|
|
48
48
|
* ./agent-config gates --reply # reply-close form; empty when none
|
|
49
|
+
* ./agent-config gates --pending # staged actions awaiting confirmation
|
|
50
|
+
*
|
|
51
|
+
* `--pending` reads a different source — the staged-confirmation store, not the
|
|
52
|
+
* roadmap tree — and stays out of `--reply` on purpose. ADR-222 fixes the
|
|
53
|
+
* reply-close form at exactly ONE decision rendered in full; folding a second
|
|
54
|
+
* source into it would silently change which decision "the one" is, and that
|
|
55
|
+
* contract is not this step's to move.
|
|
49
56
|
*/
|
|
50
57
|
|
|
51
58
|
import * as path from 'node:path';
|
|
@@ -58,6 +65,8 @@ import {
|
|
|
58
65
|
blocker_needs_user as needsUser,
|
|
59
66
|
type Blocker,
|
|
60
67
|
} from './update_roadmap_progress.js';
|
|
68
|
+
import { listPending } from '../templates/scripts/work_engine/hooks/builtin/staged_confirmation_store.js';
|
|
69
|
+
import type { StagedAction } from '../templates/scripts/work_engine/hooks/builtin/staged_confirmation.js';
|
|
61
70
|
|
|
62
71
|
const _HERE = fileURLToPath(import.meta.url);
|
|
63
72
|
|
|
@@ -327,6 +336,89 @@ function renderJson(entries: readonly Entry[], all: boolean): string {
|
|
|
327
336
|
);
|
|
328
337
|
}
|
|
329
338
|
|
|
339
|
+
/**
|
|
340
|
+
* `--pending`: staged actions awaiting a human confirmation.
|
|
341
|
+
*
|
|
342
|
+
* A second source under the same verb, and the reason it belongs here rather
|
|
343
|
+
* than in a new command is the verb's own definition — "open decisions that
|
|
344
|
+
* need you, as actions". A staged irreversible action IS one, and the most
|
|
345
|
+
* literal kind: the roadmap blockers above are decisions a human owes a plan,
|
|
346
|
+
* this is a decision a human owes an action that is already loaded and waiting.
|
|
347
|
+
*
|
|
348
|
+
* Expired stages are counted, never listed as actionable. An expired stage
|
|
349
|
+
* cannot execute (`stageStatus` derives that from the clock, not from a sweep
|
|
350
|
+
* having run), so rendering it beside a live one would put two rows in front of
|
|
351
|
+
* the reader where only one is a decision.
|
|
352
|
+
*/
|
|
353
|
+
function renderPending(root: string, now: number): string {
|
|
354
|
+
const rows = listPending(root, now);
|
|
355
|
+
const live = rows.filter((r) => r.status === 'pending');
|
|
356
|
+
const expired = rows.filter((r) => r.status === 'expired');
|
|
357
|
+
const lines: string[] = [];
|
|
358
|
+
|
|
359
|
+
if (live.length === 0) {
|
|
360
|
+
lines.push(
|
|
361
|
+
expired.length === 0
|
|
362
|
+
? 'No staged actions awaiting confirmation.'
|
|
363
|
+
: `Nothing awaits your confirmation. ${expired.length} stage` +
|
|
364
|
+
`${expired.length !== 1 ? 's' : ''} expired unconfirmed — the action never fired.`,
|
|
365
|
+
);
|
|
366
|
+
return lines.join('\n') + '\n';
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
lines.push(
|
|
370
|
+
`${live.length} staged action${live.length !== 1 ? 's' : ''} await` +
|
|
371
|
+
`${live.length === 1 ? 's' : ''} your confirmation` +
|
|
372
|
+
(expired.length > 0 ? ` · ${expired.length} expired unconfirmed` : ''),
|
|
373
|
+
);
|
|
374
|
+
let n = 0;
|
|
375
|
+
for (const { stage } of live) {
|
|
376
|
+
n += 1;
|
|
377
|
+
lines.push(...renderStage(stage, n));
|
|
378
|
+
}
|
|
379
|
+
lines.push('');
|
|
380
|
+
return lines.join('\n') + '\n';
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
function renderStage(stage: StagedAction, index: number): string[] {
|
|
384
|
+
const head = `${index} · ${stage.action}`;
|
|
385
|
+
const tail = `token: ${stage.token}`;
|
|
386
|
+
const dashes = Math.max(3, WIDTH - head.length - tail.length - 6);
|
|
387
|
+
return [
|
|
388
|
+
'',
|
|
389
|
+
`── ${head} ${'─'.repeat(dashes)} ${tail}`.trimEnd(),
|
|
390
|
+
// The object is the first field on purpose: an approval that does not
|
|
391
|
+
// name the exact object is the thing non-destructive-by-default forbids,
|
|
392
|
+
// so it is what the reader must see before anything else.
|
|
393
|
+
...field('Object:', stage.object),
|
|
394
|
+
...field('Staged by:', stage.source),
|
|
395
|
+
...field('Expires:', stage.expires_at),
|
|
396
|
+
];
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
function renderPendingJson(root: string, now: number): string {
|
|
400
|
+
const rows = listPending(root, now);
|
|
401
|
+
return (
|
|
402
|
+
JSON.stringify(
|
|
403
|
+
{
|
|
404
|
+
awaitingYou: rows.filter((r) => r.status === 'pending').length,
|
|
405
|
+
expired: rows.filter((r) => r.status === 'expired').length,
|
|
406
|
+
staged: rows.map(({ stage, status }) => ({
|
|
407
|
+
token: stage.token,
|
|
408
|
+
action: stage.action,
|
|
409
|
+
object: stage.object,
|
|
410
|
+
source: stage.source,
|
|
411
|
+
stagedAt: stage.staged_at,
|
|
412
|
+
expiresAt: stage.expires_at,
|
|
413
|
+
status,
|
|
414
|
+
})),
|
|
415
|
+
},
|
|
416
|
+
null,
|
|
417
|
+
2,
|
|
418
|
+
) + '\n'
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
|
|
330
422
|
function _isDir(p: string): boolean {
|
|
331
423
|
try {
|
|
332
424
|
return fs.statSync(p).isDirectory();
|
|
@@ -340,8 +432,8 @@ function _isDir(p: string): boolean {
|
|
|
340
432
|
* `agents/roadmaps`, otherwise fall back to the git toplevel (monorepo
|
|
341
433
|
* sub-project support).
|
|
342
434
|
*/
|
|
343
|
-
function _resolveRepoRoot(start: string): string {
|
|
344
|
-
if (_isDir(path.join(start,
|
|
435
|
+
function _resolveRepoRoot(start: string, marker = path.join('agents', 'roadmaps')): string {
|
|
436
|
+
if (_isDir(path.join(start, marker))) {
|
|
345
437
|
return start;
|
|
346
438
|
}
|
|
347
439
|
try {
|
|
@@ -351,7 +443,7 @@ function _resolveRepoRoot(start: string): string {
|
|
|
351
443
|
timeout: 10_000,
|
|
352
444
|
});
|
|
353
445
|
const top = (r.stdout || '').trim();
|
|
354
|
-
if (r.status === 0 && top !== '' && _isDir(path.join(top,
|
|
446
|
+
if (r.status === 0 && top !== '' && _isDir(path.join(top, marker))) {
|
|
355
447
|
return top;
|
|
356
448
|
}
|
|
357
449
|
} catch {
|
|
@@ -365,6 +457,18 @@ function main(argv?: readonly string[]): number {
|
|
|
365
457
|
const all = args.includes('--all');
|
|
366
458
|
const json = args.includes('--json');
|
|
367
459
|
const reply = args.includes('--reply');
|
|
460
|
+
const pending = args.includes('--pending');
|
|
461
|
+
|
|
462
|
+
// `--pending` resolves against `agents/runtime/`, not `agents/roadmaps/`,
|
|
463
|
+
// and is answered BEFORE the roadmaps-directory exit below: a staged action
|
|
464
|
+
// is independent of whether this project plans in roadmaps at all, so
|
|
465
|
+
// "no roadmaps here" is not an answer to "what awaits my confirmation".
|
|
466
|
+
if (pending) {
|
|
467
|
+
const root = _resolveRepoRoot(process.cwd(), path.join('agents', 'runtime'));
|
|
468
|
+
const now = Date.now();
|
|
469
|
+
process.stdout.write(json ? renderPendingJson(root, now) : renderPending(root, now));
|
|
470
|
+
return 0;
|
|
471
|
+
}
|
|
368
472
|
|
|
369
473
|
const repoRoot = _resolveRepoRoot(process.cwd());
|
|
370
474
|
const roadmapRoot = path.join(repoRoot, 'agents', 'roadmaps');
|
|
@@ -412,5 +516,16 @@ if (_isCliEntry()) {
|
|
|
412
516
|
process.exitCode = main();
|
|
413
517
|
}
|
|
414
518
|
|
|
415
|
-
export {
|
|
519
|
+
export {
|
|
520
|
+
main,
|
|
521
|
+
needsUser,
|
|
522
|
+
regroupTodo,
|
|
523
|
+
wrap,
|
|
524
|
+
collectEntries,
|
|
525
|
+
render,
|
|
526
|
+
renderJson,
|
|
527
|
+
renderReply,
|
|
528
|
+
renderPending,
|
|
529
|
+
renderPendingJson,
|
|
530
|
+
};
|
|
416
531
|
export type { Entry };
|
|
@@ -199,7 +199,7 @@ external static-extraction tool and hand the result to this skill as a
|
|
|
199
199
|
`design-system.json` artifact. We own the **import contract**, not the crawler:
|
|
200
200
|
the package never ships the Playwright runtime, a font-bundler, or a `.skill`
|
|
201
201
|
auto-installer (out of scope). Full schema is lazy-loaded from
|
|
202
|
-
[`
|
|
202
|
+
[`references/design-system-json.md`](references/design-system-json.md) — read it
|
|
203
203
|
only when an import is requested.
|
|
204
204
|
|
|
205
205
|
**Import procedure:**
|
|
@@ -281,7 +281,7 @@ most common handoff ambiguity.
|
|
|
281
281
|
When the goal is to extract this repo's design system as a **reusable package
|
|
282
282
|
artifact** (not just DESIGN.md prose), the extraction meets this floor — the
|
|
283
283
|
handoff shape emitted alongside `design-system.json`
|
|
284
|
-
([import contract](
|
|
284
|
+
([import contract](references/design-system-json.md)).
|
|
285
285
|
|
|
286
286
|
- **Contract contents.** A complete extraction carries: a root guide / manifest;
|
|
287
287
|
token CSS (or the stack's equivalent); the typography / colour / spacing /
|
|
@@ -256,7 +256,7 @@ Load on demand once the audit needs the pitfall catalog:
|
|
|
256
256
|
**Design-system export (current-repo source):** when the goal is to seed
|
|
257
257
|
`DESIGN.md` from *this* repo, emit the inventory as a `design-system.json`
|
|
258
258
|
artifact (the import contract in
|
|
259
|
-
[`design-system-capture`](../design-system-capture/
|
|
259
|
+
[`design-system-capture`](../design-system-capture/references/design-system-json.md))
|
|
260
260
|
and hand it to `design-system-capture` — the same shape an external extraction
|
|
261
261
|
tool produces, so the import path is uniform.
|
|
262
262
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
model_tier: medium
|
|
3
3
|
name: fe-design
|
|
4
|
-
description: "
|
|
4
|
+
description: "Frontend design heuristics — and, outside the ticket engine, the loop that applies them: audit, brief, build, review. Use when building or changing any UI, not only when planning one."
|
|
5
5
|
personas:
|
|
6
6
|
- frontend-engineer
|
|
7
7
|
domain: engineering
|
|
@@ -11,15 +11,82 @@ packs:
|
|
|
11
11
|
- engineering-base
|
|
12
12
|
---
|
|
13
13
|
|
|
14
|
-
# Frontend Design Skill
|
|
15
|
-
|
|
16
|
-
##
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
14
|
+
# Frontend Design Skill
|
|
15
|
+
|
|
16
|
+
## Ad-hoc mode — outside the engine, YOU run this loop now
|
|
17
|
+
|
|
18
|
+
One question decides which mode you are in: **is a `/implement-ticket` run
|
|
19
|
+
dispatching this?**
|
|
20
|
+
|
|
21
|
+
| Situation | Who owns the UI write | This skill is |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| A ticketed run — the UI directive set is dispatching | `directives/ui/*` | a reference it cites |
|
|
24
|
+
| Anything else — "build me the page", "improve this form", "implement the approved design" | **you, in this turn** | the executor |
|
|
25
|
+
|
|
26
|
+
Outside the engine, nothing else owns the design quality of a UI write. Reading
|
|
27
|
+
this skill and then writing the UI from priors is the failure it exists to
|
|
28
|
+
prevent — the loop below is not optional context, it is the work.
|
|
29
|
+
|
|
30
|
+
**Skip only when the change is `ui-trivial`, decidable off the diff:** ≤ 1 file,
|
|
31
|
+
≤ 5 changed lines, no new component, no new state, no new dependency. Anything
|
|
32
|
+
else runs the loop.
|
|
33
|
+
|
|
34
|
+
### The loop
|
|
35
|
+
|
|
36
|
+
1. **Audit first** — run [`existing-ui-audit`](../existing-ui-audit/SKILL.md).
|
|
37
|
+
What already exists (components, tokens, layout conventions) outranks every
|
|
38
|
+
heuristic below. Reinventing an existing component is the #1 failure mode.
|
|
39
|
+
2. **Brief** — cover the same five keys the engine requires before any code:
|
|
40
|
+
`layout`, `components`, `states`, `microcopy`, `a11y`. `states` means all
|
|
41
|
+
five of `empty`, `loading`, `error`, `success`, `disabled` — a brief missing
|
|
42
|
+
one is unfinished, not concise.
|
|
43
|
+
3. **Build** — against the audit's primitives, in the project's stack.
|
|
44
|
+
4. **Review** — run [`design-review`](../design-review/SKILL.md) before calling
|
|
45
|
+
it done, and scope the verdict honestly: render-scoped when you can render
|
|
46
|
+
it, otherwise explicitly static-scoped, naming which checks actually ran.
|
|
47
|
+
"Looks good" with neither scope named is a verdict without evidence.
|
|
48
|
+
|
|
49
|
+
### The heuristics — here, not one hop away
|
|
50
|
+
|
|
51
|
+
The load-bearing subset, inline so that "loaded" means the content is in
|
|
52
|
+
context. Depth stays in [`references/design-patterns.md`](references/design-patterns.md).
|
|
53
|
+
|
|
54
|
+
1. **Audit outranks heuristic.** A token, primitive or convention the audit
|
|
55
|
+
found wins over anything on this list; say `[audit override]` when it does.
|
|
56
|
+
2. **Reuse tokens, never raw values.** A hex, font or px literal where the
|
|
57
|
+
audit found a token is off-brand by construction.
|
|
58
|
+
3. **All five states are designed.** `empty` is a helpful message, not a blank
|
|
59
|
+
region; `loading` prefers a skeleton over a spinner (it shows structure, so
|
|
60
|
+
it reads as faster); `error` says what to do next.
|
|
61
|
+
4. **Labels are always visible.** No placeholder-only inputs.
|
|
62
|
+
5. **Validate on blur and on submit**, never on every keystroke; the message
|
|
63
|
+
goes below the field and is specific.
|
|
64
|
+
6. **Mobile-first, and 320 px actually works.** Default styles are the small
|
|
65
|
+
viewport; complexity is added at larger breakpoints, never removed at
|
|
66
|
+
smaller ones.
|
|
67
|
+
7. **A11y minimums are non-negotiable:** 4.5:1 contrast for text (3:1 large),
|
|
68
|
+
every interactive element reachable by Tab, a visible focus ring, semantic
|
|
69
|
+
elements over `div`, and an `aria-label` wherever there is no visible text.
|
|
70
|
+
8. **Every action gets feedback.** Users read silence as failure.
|
|
71
|
+
9. **Prefer undo over a confirmation dialog** — confirmations get clicked
|
|
72
|
+
through; an undo affordance actually protects the user.
|
|
73
|
+
10. **Tables:** numbers right-aligned, text left-aligned, a designed empty
|
|
74
|
+
state, and a sticky header on anything long enough to scroll.
|
|
75
|
+
11. **No placeholder microcopy ships.** Lorem ipsum, `TODO`, and
|
|
76
|
+
`[Your text here]` are unfinished output, not drafts.
|
|
77
|
+
|
|
78
|
+
Before proposing a direction, run the anti-slop scan named under
|
|
79
|
+
[Anti-slop discipline](#anti-slop-discipline) below.
|
|
80
|
+
|
|
81
|
+
## Positioning — reference inside the engine, executor outside it
|
|
82
|
+
|
|
83
|
+
Inside a `/implement-ticket` run, `fe-design` is a **universal reference
|
|
84
|
+
skill**: it carries stack-agnostic heuristics the UI directive set cites, and
|
|
85
|
+
it does not own the flow. The ownership table below applies **to that mode**.
|
|
86
|
+
Outside the engine the table has no dispatcher behind it — the ad-hoc loop
|
|
87
|
+
above is the owner instead.
|
|
88
|
+
|
|
89
|
+
| Concern | Owner (engine-mediated runs) |
|
|
23
90
|
|---|---|
|
|
24
91
|
| Layout / states / microcopy lock | [`directives/ui/design.ts`](../../templates/scripts/work_engine/directives/ui/design.ts) |
|
|
25
92
|
| Stack-dispatched implementation | [`directives/ui/apply.ts`](../../templates/scripts/work_engine/directives/ui/apply.ts) → `blade-ui` / `livewire` / `flux` / `react-shadcn-ui` |
|
|
@@ -37,12 +104,17 @@ Cite this skill when:
|
|
|
37
104
|
- Making responsive design decisions
|
|
38
105
|
- Reviewing UI for accessibility and usability
|
|
39
106
|
|
|
40
|
-
|
|
107
|
+
**Inside a ticketed run**, do NOT use this skill to:
|
|
41
108
|
|
|
42
109
|
- Implement components — that is the apply-step's stack-dispatched skill
|
|
43
110
|
- Audit an existing UI — that is `existing-ui-audit`
|
|
44
111
|
- Drive the full UI flow — that is the `directives/ui/` orchestrator
|
|
45
112
|
|
|
113
|
+
Outside a ticketed run, the first and third lines invert: no dispatcher is
|
|
114
|
+
running, so implementation quality and the flow are yours. The second holds in
|
|
115
|
+
both modes — the audit is always `existing-ui-audit`; you invoke it, you do not
|
|
116
|
+
replace it.
|
|
117
|
+
|
|
46
118
|
> **Resource-first, before taste.** Any request to recreate / redesign / mock /
|
|
47
119
|
> prototype / improve an existing UI runs the
|
|
48
120
|
> [resource-first context gate](../existing-ui-audit/SKILL.md#resource-first-context-gate-design-fidelity)
|
|
@@ -129,4 +201,4 @@ approach or explicitly invoke the override condition in the design brief.
|
|
|
129
201
|
- Do NOT skip mobile viewport testing.
|
|
130
202
|
- Do NOT use fixed pixel widths for responsive layouts.
|
|
131
203
|
- Do NOT ignore accessibility requirements.
|
|
132
|
-
- Do NOT use this skill as an executor
|
|
204
|
+
- Do NOT use this skill as an executor INSIDE a ticketed run — there the executor is `directives/ui/design.ts` and this is the reference it cites. Outside one, the ad-hoc loop at the top of this file IS the executor; do NOT read the reference and then write the UI from priors.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"skill": "fe-design",
|
|
3
|
-
"last_eval": "2026-
|
|
4
|
-
"description": "
|
|
3
|
+
"last_eval": "2026-08-12",
|
|
4
|
+
"description": "Should-trigger covers BOTH halves of this skill's two modes: planning/exploration (give me directions, explore, plan the flow, pattern choice) AND — new — ad-hoc implementation, because outside a ticketed run no other artefact owns the design quality of a UI write. The implementation query used to be labelled should-not-trigger on the reasoning that it belongs to the apply step; that step only exists as a dispatch target inside the engine, so the label routed ad-hoc implementation prompts to nobody. Should-not-trigger keeps the genuine near-misses: inventorying existing UI (existing-ui-audit owns it in both modes), a ui-trivial one-line edit, and non-UI work.",
|
|
5
5
|
"queries": [
|
|
6
6
|
{
|
|
7
7
|
"q": "give me three directions for the pricing page",
|
|
@@ -25,7 +25,15 @@
|
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
"q": "implement the selected checkout design in React exactly as approved",
|
|
28
|
-
"trigger":
|
|
28
|
+
"trigger": true
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"q": "build the settings page",
|
|
32
|
+
"trigger": true
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"q": "improve this form, it feels clunky",
|
|
36
|
+
"trigger": true
|
|
29
37
|
},
|
|
30
38
|
{
|
|
31
39
|
"q": "what form components do we already have in the codebase?",
|
|
@@ -94,7 +94,7 @@ biggest publicly-viewable books**, not a single portal:
|
|
|
94
94
|
each special/award market a bonus question needs) from several books.
|
|
95
95
|
Odds-comparison aggregators (Oddschecker, Oddsportal / Betexplorer) show
|
|
96
96
|
many books at once; supplement with named books. Concrete book list and
|
|
97
|
-
the weighting recipe live in [`
|
|
97
|
+
the weighting recipe live in [`references/odds-and-bonus.md`](references/odds-and-bonus.md).
|
|
98
98
|
2. **De-vig each book** independently (remove its margin) → per-book implied
|
|
99
99
|
probabilities. Raw odds sum to >100%; never treat them as probabilities.
|
|
100
100
|
3. **Aggregate with a healthy weighting**, not a blind average: weight
|
|
@@ -203,7 +203,7 @@ Respect all strategy limits from step 1 (max identical tips, etc.).
|
|
|
203
203
|
|
|
204
204
|
Walk the **step-1 checklist** and answer **each** entry. Pick the method by
|
|
205
205
|
question type — full taxonomy + per-type method in
|
|
206
|
-
[`
|
|
206
|
+
[`references/odds-and-bonus.md`](references/odds-and-bonus.md):
|
|
207
207
|
|
|
208
208
|
- **Tournament structure** (group winners, KO rounds, finalists, champion):
|
|
209
209
|
use real **outright market odds** ("to win group", "to reach final",
|
|
@@ -253,7 +253,7 @@ deadline is the only hard constraint.
|
|
|
253
253
|
|
|
254
254
|
3. **Group standings and the full bracket** where the event has them.
|
|
255
255
|
4. **Self-check note** — (a) confirm the tips reconcile with
|
|
256
|
-
[`
|
|
256
|
+
[`references/ev-fixtures.md`](references/ev-fixtures.md) (known pool rules +
|
|
257
257
|
market odds → a known-good EV tip); (b) confirm the bonus table has the
|
|
258
258
|
**same number of rows as the step-1 checklist** — a shorter table means a
|
|
259
259
|
question was dropped. If your method disagrees with a fixture, your method
|
|
@@ -310,10 +310,10 @@ gate — the skill never enters or submits anything.
|
|
|
310
310
|
|
|
311
311
|
- [`/prediction-pool`](../../commands/prediction-pool.md) — the orchestrator (event,
|
|
312
312
|
persistence, Playwright entry, gates).
|
|
313
|
-
- [`
|
|
313
|
+
- [`references/odds-and-bonus.md`](references/odds-and-bonus.md) — the major-book
|
|
314
314
|
list + sharpness-weighted consensus recipe, and the bonus / award / special
|
|
315
315
|
question taxonomy with a per-type method.
|
|
316
|
-
- [`
|
|
316
|
+
- [`references/ev-fixtures.md`](references/ev-fixtures.md) — known-good
|
|
317
317
|
rules+odds → EV examples.
|
|
318
318
|
- `node_modules/@event4u/agent-config/src/scripts/prediction-pool/score_ev.ts` —
|
|
319
319
|
the executed exact-score EV optimiser (step 4a; λ + rule → EV-max scoreline).
|
|
@@ -132,7 +132,7 @@ The default path is the bundled `scripts/shadcn_add.ts` CLI wrapper + reading
|
|
|
132
132
|
`components.json` — it works on most shadcn projects and stays the default.
|
|
133
133
|
The modern registry model is an **opt-in enhancement**; do not add round-trips
|
|
134
134
|
to every component op. Full JSON-schema + namespace detail is lazy-loaded from
|
|
135
|
-
[`
|
|
135
|
+
[`references/registry.md`](references/registry.md) — read it only on this path,
|
|
136
136
|
not on the vanilla `add`.
|
|
137
137
|
|
|
138
138
|
**`shadcn info --json` handshake** — run it as the grounding step **when** the
|
|
@@ -106,6 +106,30 @@ Do NOT create a skill or rule for:
|
|
|
106
106
|
* If two skills overlap heavily → merge
|
|
107
107
|
* If a skill becomes "read the guideline" → it lost its purpose, restore the workflow
|
|
108
108
|
|
|
109
|
+
### Progressive disclosure — the directory is `references/`, plural
|
|
110
|
+
|
|
111
|
+
When a skill needs depth the workflow does not, the depth goes in a
|
|
112
|
+
**`references/`** subdirectory beside `SKILL.md` — that exact name, plural. It
|
|
113
|
+
was two spellings across nine skills until 2026-08-12 because nothing here
|
|
114
|
+
named one; the split cost a rename, not a decision.
|
|
115
|
+
|
|
116
|
+
* **Body:** the trigger, the workflow, the ownership statement, and every
|
|
117
|
+
heuristic that changes a write decision. A skill whose body is a map to its
|
|
118
|
+
own content is loaded and not applied.
|
|
119
|
+
* **`references/`:** corpora, lookup tables, long schemas, worked examples —
|
|
120
|
+
read on the path that needs them, never on every activation.
|
|
121
|
+
|
|
122
|
+
Splitting is not a size escape hatch. The measured estate (n=289, 2026-08-12):
|
|
123
|
+
median 1,077 words, p90 1,867, **only 6 skills above 2,500 and 4 above 3,000**.
|
|
124
|
+
So a skill at 1,500 words is ordinary, and moving prose out of the body to hit
|
|
125
|
+
a number makes it worse. Split when the material is genuinely
|
|
126
|
+
consulted-on-demand; keep the load-bearing part in the body even when that
|
|
127
|
+
leaves the file long.
|
|
128
|
+
|
|
129
|
+
A `references/` split does not change the gates that already apply: a
|
|
130
|
+
`token_budget_class: rich` skill still meets its 3,500-token ceiling on the
|
|
131
|
+
body alone.
|
|
132
|
+
|
|
109
133
|
## Procedure
|
|
110
134
|
|
|
111
135
|
### 0. Inspect, then run the Drafting Protocol
|
|
@@ -23,6 +23,35 @@ Every prompt cites the status taxonomy in
|
|
|
23
23
|
ends with the **return-envelope** instruction so the subagent's reply
|
|
24
24
|
validates against that schema.
|
|
25
25
|
|
|
26
|
+
### UI-shaped slices carry the design context, or name its absence
|
|
27
|
+
|
|
28
|
+
A delegated worker's context is whatever the dispatch prompt carries. For a
|
|
29
|
+
slice that writes UI, that has a specific consequence: the audit findings and
|
|
30
|
+
the design brief live in the orchestrator's context, and nothing moves them
|
|
31
|
+
across the dispatch boundary on its own. A worker that receives "build the
|
|
32
|
+
settings page" and nothing else will build it from priors — the same failure
|
|
33
|
+
the design skills exist to prevent, one layer down.
|
|
34
|
+
|
|
35
|
+
So a UI-shaped dispatch prompt carries, in its `CONTEXT FILES:` section:
|
|
36
|
+
|
|
37
|
+
- the **audit findings** from `existing-ui-audit` (components, tokens, layout
|
|
38
|
+
conventions the project already has), and
|
|
39
|
+
- the **design brief** — `layout`, `components`, `states`, `microcopy`, `a11y`,
|
|
40
|
+
with all five states covered.
|
|
41
|
+
|
|
42
|
+
When either is genuinely absent, **say so in the prompt** rather than omitting
|
|
43
|
+
it silently: `no audit findings available — run existing-ui-audit first`. A
|
|
44
|
+
worker told the context is missing can ask for it; a worker told nothing
|
|
45
|
+
assumes there was nothing to know.
|
|
46
|
+
|
|
47
|
+
**This is model-carried, and the reason is worth stating.** An orchestration
|
|
48
|
+
record carries `ts`, `spawn_count`, `token_delta`, `tier_chosen` and
|
|
49
|
+
`task_class` — it has no field able to hold a prompt, deliberately, for the same
|
|
50
|
+
privacy-by-construction reason the telemetry event has none. So no lint can join
|
|
51
|
+
a dispatch prompt against its record to check this clause: the data a check
|
|
52
|
+
would need does not exist and should not be made to exist. The obligation is
|
|
53
|
+
stated here and carried by the orchestrator, not enforced.
|
|
54
|
+
|
|
26
55
|
## Prompt-cache discipline
|
|
27
56
|
|
|
28
57
|
When dispatching sibling subagents (e.g. `do-in-parallel` with N independent
|