@event4u/agent-config 9.33.0 → 9.35.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 +154 -145
- package/CONTRIBUTING.md +23 -14
- package/dist/agent-src/commands/agent-handoff.md +15 -3
- package/dist/agent-src/commands/roadmap/next.md +37 -5
- package/dist/agent-src/scripts/archive_completed_roadmaps.ts +35 -1
- package/dist/agent-src/scripts/roadmap_gates.ts +119 -4
- package/dist/agent-src/skills/corpus-grounding/SKILL.md +21 -12
- package/dist/agent-src/skills/design-tokens/SKILL.md +15 -0
- package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +24 -0
- package/dist/agent-src/skills/rule-writing/SKILL.md +23 -0
- package/dist/agent-src/skills/skill-writing/SKILL.md +80 -2
- package/dist/agent-src/skills/systematic-debugging/SKILL.md +5 -3
- package/dist/agent-src/skills/tailwind-engineer/SKILL.md +24 -0
- package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +25 -0
- 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-PMQ6Z3T3.js → chunk-2TGMGLBL.js} +11 -4
- package/dist/cli-delegate/{chunk-YPAWXXXR.js → chunk-55RI5UXK.js} +17 -0
- package/dist/cli-delegate/{chunk-MA4GFWDY.js → chunk-H6F2CQFI.js} +1 -1
- package/dist/cli-delegate/{chunk-2WELHO3P.js → chunk-I5EAFRII.js} +35 -0
- package/dist/cli-delegate/{chunk-3EWYC3YK.js → chunk-UEZ7D35A.js} +4 -3
- package/dist/cli-delegate/{chunk-UVKNIJH2.js → chunk-ZAXH3ZWU.js} +3 -0
- package/dist/cli-delegate/cmd_conformance.js +2 -2
- package/dist/cli-delegate/cmd_doctor.js +2 -2
- package/dist/cli-delegate/cmd_export.js +2 -2
- package/dist/cli-delegate/cmd_handoff.js +3 -3
- package/dist/cli-delegate/cmd_memory_get.js +1 -1
- package/dist/cli-delegate/cmd_prune.js +2 -2
- package/dist/cli-delegate/cmd_route_audit.js +1 -1
- package/dist/cli-delegate/cmd_session_recycle.js +7 -2
- package/dist/cli-delegate/cmd_settings_migrate.js +2 -2
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +2 -2
- package/dist/cli-delegate/cmd_uninstall.js +2 -2
- package/dist/cli-delegate/cmd_validate.js +2 -2
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +13 -13
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +2 -2
- package/dist/discovery/dormancy-report.md +17 -0
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +3 -3
- package/dist/discovery/trust-report.md +1 -1
- package/dist/discovery/workspaces.json +3 -3
- package/dist/hooks/dispatch.js +355 -85
- package/dist/install/install.mjs +3 -0
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +192 -12
- package/dist/server/schemas/settings.js +1 -0
- package/dist/server/schemas/settings.js.map +1 -1
- package/docs/contracts/settings-classes.md +3 -2
- package/docs/guidelines/agent-infra/failure-signatures.md +47 -12
- package/package.json +2 -2
- package/src/agent-src/scripts/archive_completed_roadmaps.ts +35 -1
- package/src/agent-src/scripts/roadmap_gates.ts +119 -4
- 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 +11 -2
- package/src/config/quorum-attendance-budget.json +11 -3
- package/src/scripts/_cli/cmd_session_recycle.ts +6 -1
- package/src/scripts/_dispatch.bash +6 -2
- package/src/scripts/_lib/env_kill_switch.ts +37 -0
- package/src/scripts/_lib/security_lint.ts +18 -4
- package/src/scripts/_lib/self_repair.ts +60 -0
- package/src/scripts/_lib/self_repair_store.ts +65 -5
- package/src/scripts/_lib/session_register.ts +67 -1
- package/src/scripts/_lib/subagent_capsule.ts +78 -1
- package/src/scripts/ai_council/config.ts +60 -0
- package/src/scripts/ai_council/events_log.ts +105 -6
- package/src/scripts/ai_council/orchestrator.ts +38 -0
- package/src/scripts/ai_council/prompts.ts +165 -3
- package/src/scripts/ai_council/quorum.ts +87 -0
- package/src/scripts/ai_team/review_gate.ts +2 -2
- package/src/scripts/build_discovery_manifest.ts +165 -0
- package/src/scripts/check_claims.ts +51 -2
- package/src/scripts/ci_time_ratio.ts +3 -1
- package/src/scripts/council_cli.ts +36 -1
- package/src/scripts/discovery_graph.ts +201 -27
- package/src/scripts/dispatch_r2_reviewer.ts +102 -1
- package/src/scripts/hooks/turn_end_gate_hook.ts +172 -11
- package/src/scripts/lint_framework_leakage.ts +195 -28
- package/src/scripts/lint_framework_leakage_allowlist.json +94 -86
- package/src/scripts/lint_handoffs.ts +92 -2
- package/src/scripts/lint_hedge_words.ts +317 -0
- package/src/scripts/lint_mcp_config_security.ts +1 -1
- package/src/scripts/lint_skill_frontmatter_safety.ts +1 -1
- package/src/scripts/memory_lookup.ts +1 -2
- package/src/scripts/schemas/command.schema.json +4 -0
- package/src/scripts/schemas/skill.schema.json +4 -0
- package/src/scripts/self_repair_cli.ts +26 -1
- package/src/scripts/session_register_hook.ts +238 -18
- package/src/scripts/sessions_cli.ts +377 -12
- package/src/scripts/skill_linter.ts +58 -2
- package/src/server/schemas/settings.ts +3 -0
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Staged confirmation — the pure half of exactly-once confirmed execution.
|
|
3
|
+
*
|
|
4
|
+
* `src/rules/non-destructive-by-default.md` already carries the whole policy:
|
|
5
|
+
* an irreversible action is confirmed on THIS turn, ask and action are strictly
|
|
6
|
+
* sequential ("Never act while asking"), and the approval names the exact
|
|
7
|
+
* object. What the tree had no mechanism for is the *sequencing itself* — a
|
|
8
|
+
* staged action, a confirmation that matches it, and the guarantee that a
|
|
9
|
+
* second approval of the same stage does not fire the action twice.
|
|
10
|
+
*
|
|
11
|
+
* Two properties carry that guarantee, and they are split across two files on
|
|
12
|
+
* purpose:
|
|
13
|
+
*
|
|
14
|
+
* - **Identity is derived, not invented.** {@link stageAction} hashes the
|
|
15
|
+
* action, the exact object, and a caller-supplied nonce into a token, so a
|
|
16
|
+
* confirmation can only match the stage it was issued for. Restaging the
|
|
17
|
+
* same object under a fresh nonce yields a different token — an approval
|
|
18
|
+
* never carries over to "the next one like it".
|
|
19
|
+
* - **The claim is atomic, and it lives in the store.** Nothing here can be
|
|
20
|
+
* exactly-once by itself: two processes reading the same `pending` record
|
|
21
|
+
* and both deciding "execute" is a check-then-act race no pure function can
|
|
22
|
+
* close. This module decides WHAT the outcome should be;
|
|
23
|
+
* `staged_confirmation_store.ts` makes the transition atomic with a
|
|
24
|
+
* directory rename, which either succeeds once or fails.
|
|
25
|
+
*
|
|
26
|
+
* Nothing binds on this yet, deliberately. `pre_tool_use` exists on 3 of 8
|
|
27
|
+
* platform rows (`hook_manifest.yaml`), so a guard that claimed to enforce
|
|
28
|
+
* confirmation would be prose on the other five while reading like a control —
|
|
29
|
+
* the failure `src/rules/ui-audit-gate.md` names about its own scope. The
|
|
30
|
+
* decision is deferred behind blocker `confirmation-degraded-host-semantics`;
|
|
31
|
+
* until it lands, callers opt in explicitly.
|
|
32
|
+
*
|
|
33
|
+
* Pure: no filesystem, no clock, no randomness. `now` and `nonce` are
|
|
34
|
+
* parameters so a test pins a whole lifecycle without faking globals.
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
import { createHash } from 'node:crypto';
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Lifecycle of one staged action. `expired` is not a stored state — it is
|
|
41
|
+
* derived from the clock by {@link stageStatus}, so a stale pending record
|
|
42
|
+
* cannot read as awaiting-approval merely because nobody swept it.
|
|
43
|
+
*/
|
|
44
|
+
export type StageState = 'pending' | 'confirmed' | 'declined';
|
|
45
|
+
|
|
46
|
+
/** What {@link confirmOnce} concluded. Only `execute` authorizes the action. */
|
|
47
|
+
export type ConfirmOutcome =
|
|
48
|
+
| 'execute'
|
|
49
|
+
| 'already-confirmed'
|
|
50
|
+
| 'expired'
|
|
51
|
+
| 'declined'
|
|
52
|
+
| 'token-mismatch';
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The `on_block_fallback` vocabulary from
|
|
56
|
+
* `work_engine/scoring/decision_engine.ts` (`stop` / `warn`, default `stop`),
|
|
57
|
+
* reused rather than re-invented: this module extends that gate's ask path, so
|
|
58
|
+
* a second fallback vocabulary would be a second contract to keep in sync.
|
|
59
|
+
*/
|
|
60
|
+
export type NonInteractiveFallback = 'stop' | 'warn';
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Default staging window. A confirmation the user never gives must not sit in
|
|
64
|
+
* the store as an approval waiting to be collected: an abandoned stage that
|
|
65
|
+
* stays valid indefinitely is a pre-approved irreversible action, which is the
|
|
66
|
+
* opposite of what the policy asks for. Fifteen minutes is long enough for a
|
|
67
|
+
* human to read the surface and answer, short enough that a turn which ended
|
|
68
|
+
* hours ago cannot authorize anything.
|
|
69
|
+
*/
|
|
70
|
+
export const STAGE_TTL_MS = 15 * 60 * 1000;
|
|
71
|
+
|
|
72
|
+
export interface StagedAction {
|
|
73
|
+
/** Confirmation token — derived, never guessable from the object alone. */
|
|
74
|
+
readonly token: string;
|
|
75
|
+
/** What would fire: a command name, a skill slug, a concern id. */
|
|
76
|
+
readonly action: string;
|
|
77
|
+
/**
|
|
78
|
+
* The exact object the approval names — a path, a URL, a recipient, an
|
|
79
|
+
* amount. The policy's "names the exact object" clause lives here, which is
|
|
80
|
+
* why it is required rather than optional: a stage with no object is a
|
|
81
|
+
* category confirmation, and the rule forbids exactly that.
|
|
82
|
+
*/
|
|
83
|
+
readonly object: string;
|
|
84
|
+
/** Who staged it — the surface a `gates --pending` reader needs. */
|
|
85
|
+
readonly source: string;
|
|
86
|
+
readonly staged_at: string;
|
|
87
|
+
readonly expires_at: string;
|
|
88
|
+
readonly state: StageState;
|
|
89
|
+
/** Set on the transition out of `pending`, never rewritten afterwards. */
|
|
90
|
+
readonly resolved_at?: string;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** ISO-8601 seconds, matching the runtime records already in the tree. */
|
|
94
|
+
function iso(ms: number): string {
|
|
95
|
+
return new Date(ms).toISOString().replace(/\.\d{3}Z$/, 'Z');
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Derive the confirmation token.
|
|
100
|
+
*
|
|
101
|
+
* The nonce is a parameter and not read from a clock or an RNG here, so the
|
|
102
|
+
* derivation is reproducible in a test. It is also what makes two stages of the
|
|
103
|
+
* same object distinct: without it, approving a delete of `x` once would
|
|
104
|
+
* produce a token that matches every future delete of `x`.
|
|
105
|
+
*
|
|
106
|
+
* The separator is NUL, written as an escape sequence and never as a raw byte.
|
|
107
|
+
* NUL is the right separator — it cannot occur in an action, a path or a nonce,
|
|
108
|
+
* so no two different triples concatenate to the same string. A RAW NUL in a
|
|
109
|
+
* text source would make git, grep and file(1) treat the whole file as binary
|
|
110
|
+
* and skip it silently, which `lint_hidden_unicode` blocks on; the escape keeps
|
|
111
|
+
* the domain separation and leaves the file readable by every tool.
|
|
112
|
+
*/
|
|
113
|
+
export function deriveToken(action: string, object: string, nonce: string): string {
|
|
114
|
+
return createHash('sha256')
|
|
115
|
+
.update(`${action}\u0000${object}\u0000${nonce}`)
|
|
116
|
+
.digest('hex')
|
|
117
|
+
.slice(0, 16);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** Stage an action. Returns the record; it is the caller's job to persist it. */
|
|
121
|
+
export function stageAction(args: {
|
|
122
|
+
action: string;
|
|
123
|
+
object: string;
|
|
124
|
+
source: string;
|
|
125
|
+
nonce: string;
|
|
126
|
+
now: number;
|
|
127
|
+
ttlMs?: number;
|
|
128
|
+
}): StagedAction {
|
|
129
|
+
const ttl = args.ttlMs ?? STAGE_TTL_MS;
|
|
130
|
+
return {
|
|
131
|
+
token: deriveToken(args.action, args.object, args.nonce),
|
|
132
|
+
action: args.action,
|
|
133
|
+
object: args.object,
|
|
134
|
+
source: args.source,
|
|
135
|
+
staged_at: iso(args.now),
|
|
136
|
+
expires_at: iso(args.now + ttl),
|
|
137
|
+
state: 'pending',
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Effective status at `now` — `expired` is derived, not stored.
|
|
143
|
+
*
|
|
144
|
+
* A pending record past its `expires_at` reads as `expired` even though no
|
|
145
|
+
* sweep has run, so the guarantee does not depend on a pruner having been
|
|
146
|
+
* called. Prune is housekeeping; this is the decision.
|
|
147
|
+
*/
|
|
148
|
+
export function stageStatus(stage: StagedAction, now: number): StageState | 'expired' {
|
|
149
|
+
if (stage.state === 'pending' && Date.parse(stage.expires_at) <= now) {
|
|
150
|
+
return 'expired';
|
|
151
|
+
}
|
|
152
|
+
return stage.state;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export function isExpired(stage: StagedAction, now: number): boolean {
|
|
156
|
+
return stageStatus(stage, now) === 'expired';
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Decide what a confirmation attempt means. `execute` — and only `execute` —
|
|
161
|
+
* authorizes the action, and it is returned at most once per stage because the
|
|
162
|
+
* caller writes the returned record back before acting.
|
|
163
|
+
*
|
|
164
|
+
* The token is compared in full: a confirmation for a different stage is
|
|
165
|
+
* `token-mismatch` rather than a silent no-op, because a mismatch is a real
|
|
166
|
+
* signal (a stale surface, a copied token) and swallowing it would hide it.
|
|
167
|
+
*/
|
|
168
|
+
export function confirmOnce(
|
|
169
|
+
stage: StagedAction,
|
|
170
|
+
token: string,
|
|
171
|
+
now: number,
|
|
172
|
+
): { outcome: ConfirmOutcome; stage: StagedAction } {
|
|
173
|
+
if (token !== stage.token) {
|
|
174
|
+
return { outcome: 'token-mismatch', stage };
|
|
175
|
+
}
|
|
176
|
+
const status = stageStatus(stage, now);
|
|
177
|
+
if (status === 'confirmed') {
|
|
178
|
+
return { outcome: 'already-confirmed', stage };
|
|
179
|
+
}
|
|
180
|
+
if (status === 'declined') {
|
|
181
|
+
return { outcome: 'declined', stage };
|
|
182
|
+
}
|
|
183
|
+
if (status === 'expired') {
|
|
184
|
+
return { outcome: 'expired', stage };
|
|
185
|
+
}
|
|
186
|
+
return {
|
|
187
|
+
outcome: 'execute',
|
|
188
|
+
stage: { ...stage, state: 'confirmed', resolved_at: iso(now) },
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** Decline a stage. Idempotent for the same reason `confirmOnce` is. */
|
|
193
|
+
export function declineStage(
|
|
194
|
+
stage: StagedAction,
|
|
195
|
+
token: string,
|
|
196
|
+
now: number,
|
|
197
|
+
): { declined: boolean; stage: StagedAction } {
|
|
198
|
+
if (token !== stage.token || stageStatus(stage, now) !== 'pending') {
|
|
199
|
+
return { declined: false, stage };
|
|
200
|
+
}
|
|
201
|
+
return { declined: true, stage: { ...stage, state: 'declined', resolved_at: iso(now) } };
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* What a non-interactive context does with a stage.
|
|
206
|
+
*
|
|
207
|
+
* Both fallbacks REFUSE — `decision_engine`'s `stop` and `warn` differ in how
|
|
208
|
+
* loudly they surface, never in whether the gated thing proceeds, and a staged
|
|
209
|
+
* irreversible action is the last place to invent an auto-approve. Naming the
|
|
210
|
+
* `warn` case explicitly is the point: a reader looking for the permissive
|
|
211
|
+
* branch finds it absent on purpose.
|
|
212
|
+
*/
|
|
213
|
+
export function nonInteractiveDecision(fallback: NonInteractiveFallback): {
|
|
214
|
+
execute: false;
|
|
215
|
+
surface: 'halt' | 'warn';
|
|
216
|
+
} {
|
|
217
|
+
return { execute: false, surface: fallback === 'warn' ? 'warn' : 'halt' };
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* The confirmation surface, in the numbered-options shape
|
|
222
|
+
* `src/rules/user-interaction.md` requires. Returned as lines rather than
|
|
223
|
+
* written, so the same text serves a hook halt, a CLI pane, and a chat reply.
|
|
224
|
+
*
|
|
225
|
+
* `confirmWith` / `declineWith` are the caller's channel and are NOT defaulted
|
|
226
|
+
* to a command name. Which channel confirms a staged action is precisely what
|
|
227
|
+
* blocker `confirmation-degraded-host-semantics` has not decided — a
|
|
228
|
+
* `pre_tool_use` reply on three hosts, prose on the other five — and printing
|
|
229
|
+
* an invocation that does not exist yet would put a false instruction into a
|
|
230
|
+
* shipped surface. Until a binding caller supplies one, the surface names the
|
|
231
|
+
* token and says plainly that no channel is wired.
|
|
232
|
+
*/
|
|
233
|
+
export function confirmationSurface(
|
|
234
|
+
stage: StagedAction,
|
|
235
|
+
channel?: { confirmWith?: string; declineWith?: string },
|
|
236
|
+
): string[] {
|
|
237
|
+
const confirm = channel?.confirmWith;
|
|
238
|
+
const decline = channel?.declineWith;
|
|
239
|
+
return [
|
|
240
|
+
`Confirmation required: ${stage.action}`,
|
|
241
|
+
`Object: ${stage.object}`,
|
|
242
|
+
`Staged by: ${stage.source} · token ${stage.token} · expires ${stage.expires_at}`,
|
|
243
|
+
confirm === undefined
|
|
244
|
+
? `1) Confirm — quote token ${stage.token} back to the caller that staged it.`
|
|
245
|
+
: `1) Confirm — ${confirm}`,
|
|
246
|
+
decline === undefined
|
|
247
|
+
? '2) Decline — say so; the stage is resolved without firing.'
|
|
248
|
+
: `2) Decline — ${decline}`,
|
|
249
|
+
'3) Do nothing — the stage expires and the action never fires.',
|
|
250
|
+
'Pending stages: `agent-config gates --pending`.',
|
|
251
|
+
];
|
|
252
|
+
}
|
package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/staged_confirmation_store.ts
ADDED
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Staged-confirmation store — the I/O half, and the half that makes
|
|
3
|
+
* exactly-once real.
|
|
4
|
+
*
|
|
5
|
+
* `staged_confirmation.ts` decides what a confirmation attempt MEANS. It cannot
|
|
6
|
+
* make the transition happen only once: two processes that both read a
|
|
7
|
+
* `pending` record and both conclude `execute` is a check-then-act race, and no
|
|
8
|
+
* pure function closes it. So the claim is a **directory rename**, which the
|
|
9
|
+
* filesystem performs atomically — the first caller moves
|
|
10
|
+
* `pending/<token>.json` to `resolved/`, every later caller gets `ENOENT` and
|
|
11
|
+
* learns the stage is already taken.
|
|
12
|
+
*
|
|
13
|
+
* That is also why the state lives in the path and not only in a field: a
|
|
14
|
+
* read-modify-write of a `state:` key would reopen exactly the window the
|
|
15
|
+
* rename closes.
|
|
16
|
+
*
|
|
17
|
+
* Records live under `agents/runtime/staged-confirmations/`, which the repo
|
|
18
|
+
* `.gitignore` already covers via the `/agents/runtime/` catch-all — a staged
|
|
19
|
+
* action is machine-generated local state, never a tracked artefact. The store
|
|
20
|
+
* mirrors `_lib/self_repair_store.ts`: one file per identity, every read
|
|
21
|
+
* tolerant of a malformed file, and no throw on a missing directory.
|
|
22
|
+
*/
|
|
23
|
+
import * as fs from 'node:fs';
|
|
24
|
+
import * as path from 'node:path';
|
|
25
|
+
|
|
26
|
+
import {
|
|
27
|
+
confirmOnce,
|
|
28
|
+
declineStage,
|
|
29
|
+
type ConfirmOutcome,
|
|
30
|
+
type StageState,
|
|
31
|
+
type StagedAction,
|
|
32
|
+
stageStatus,
|
|
33
|
+
} from './staged_confirmation.js';
|
|
34
|
+
|
|
35
|
+
export const STORE_REL = path.join('agents', 'runtime', 'staged-confirmations');
|
|
36
|
+
|
|
37
|
+
export function storeDir(root: string): string {
|
|
38
|
+
return path.join(root, STORE_REL);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function pendingDir(root: string): string {
|
|
42
|
+
return path.join(storeDir(root), 'pending');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function resolvedDir(root: string): string {
|
|
46
|
+
return path.join(storeDir(root), 'resolved');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* A token is a filename before it is an identifier, so every site that turns
|
|
51
|
+
* one into a path checks it first — the read verbs, the write verb, and the
|
|
52
|
+
* record guard itself.
|
|
53
|
+
*
|
|
54
|
+
* `deriveToken` returns a 16-char sha256 prefix, so a token this module mints
|
|
55
|
+
* is always safe. Everything else is a way in: `readPending`,
|
|
56
|
+
* `claimConfirmation` and `declineConfirmation` take a caller-supplied token;
|
|
57
|
+
* `putPending` joins `stage.token` from a caller-built record (verified: it
|
|
58
|
+
* wrote outside the store root); and `isStage` accepted any string, so a record
|
|
59
|
+
* written by something else carried its token into the prune path. All four are
|
|
60
|
+
* guarded, and `path.join(pendingDir(root), '../x.json')` resolving outside
|
|
61
|
+
* `pending/` is what makes that necessary.
|
|
62
|
+
*/
|
|
63
|
+
const _TOKEN_RE = /^[0-9a-f]{8,64}$/;
|
|
64
|
+
|
|
65
|
+
export function isSafeToken(token: string): boolean {
|
|
66
|
+
return _TOKEN_RE.test(token);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Every field the module later reads, `staged_at` included.
|
|
71
|
+
*
|
|
72
|
+
* It checked four of five while still asserting `v is StagedAction`, so a
|
|
73
|
+
* record that was valid JSON but carried no `staged_at` passed the guard and
|
|
74
|
+
* reached `listPending`'s `staged_at.localeCompare(...)`: a TypeError thrown
|
|
75
|
+
* through `roadmap_gates.renderPending`, i.e. one malformed file on disk taking
|
|
76
|
+
* out a shipped gate. An unsound guard is worse than no guard — it makes the
|
|
77
|
+
* caller's `!== null` check read as a proof that it is not.
|
|
78
|
+
*/
|
|
79
|
+
function isStage(v: unknown): v is StagedAction {
|
|
80
|
+
if (typeof v !== 'object' || v === null) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
const s = v as Partial<StagedAction>;
|
|
84
|
+
return (
|
|
85
|
+
typeof s.token === 'string' &&
|
|
86
|
+
isSafeToken(s.token) &&
|
|
87
|
+
typeof s.action === 'string' &&
|
|
88
|
+
typeof s.object === 'string' &&
|
|
89
|
+
typeof s.staged_at === 'string' &&
|
|
90
|
+
typeof s.expires_at === 'string'
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function readStageFile(file: string): StagedAction | null {
|
|
95
|
+
try {
|
|
96
|
+
const parsed: unknown = JSON.parse(fs.readFileSync(file, 'utf-8'));
|
|
97
|
+
return isStage(parsed) ? parsed : null;
|
|
98
|
+
} catch {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function writeStageFile(file: string, stage: StagedAction): void {
|
|
104
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
105
|
+
fs.writeFileSync(file, `${JSON.stringify(stage, null, 2)}\n`, 'utf-8');
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Persist a freshly staged action. Returns the path written.
|
|
110
|
+
*
|
|
111
|
+
* Throws on an unsafe token rather than returning: a caller reaching here with
|
|
112
|
+
* one built the record itself and has a bug, and `writeStageFile` creates
|
|
113
|
+
* directories, so a silent refusal would look like a successful stage nothing
|
|
114
|
+
* can ever confirm.
|
|
115
|
+
*/
|
|
116
|
+
export function putPending(root: string, stage: StagedAction): string {
|
|
117
|
+
if (!isSafeToken(stage.token)) {
|
|
118
|
+
throw new Error(
|
|
119
|
+
`staged-confirmation: refusing to write under an unsafe token '${stage.token}' — ` +
|
|
120
|
+
'a token is a filename and must match the deriveToken shape',
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
const file = path.join(pendingDir(root), `${stage.token}.json`);
|
|
124
|
+
writeStageFile(file, stage);
|
|
125
|
+
return file;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function readPending(root: string, token: string): StagedAction | null {
|
|
129
|
+
if (!isSafeToken(token)) {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
return readStageFile(path.join(pendingDir(root), `${token}.json`));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function readResolved(root: string, token: string): StagedAction | null {
|
|
136
|
+
if (!isSafeToken(token)) {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
return readStageFile(path.join(resolvedDir(root), `${token}.json`));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Every stage still in `pending/`, with its effective status at `now` so an
|
|
144
|
+
* expired one is never rendered as awaiting approval. Sorted by `staged_at`
|
|
145
|
+
* (oldest first, ties by token) so two runs on an unchanged store print
|
|
146
|
+
* byte-identical output.
|
|
147
|
+
*/
|
|
148
|
+
export function listPending(
|
|
149
|
+
root: string,
|
|
150
|
+
now: number,
|
|
151
|
+
): { stage: StagedAction; status: StageState | 'expired' }[] {
|
|
152
|
+
let names: string[];
|
|
153
|
+
try {
|
|
154
|
+
names = fs.readdirSync(pendingDir(root));
|
|
155
|
+
} catch {
|
|
156
|
+
return [];
|
|
157
|
+
}
|
|
158
|
+
const out: { stage: StagedAction; status: StageState | 'expired' }[] = [];
|
|
159
|
+
for (const n of names.sort()) {
|
|
160
|
+
if (!n.endsWith('.json')) {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
const stage = readStageFile(path.join(pendingDir(root), n));
|
|
164
|
+
if (stage !== null) {
|
|
165
|
+
out.push({ stage, status: stageStatus(stage, now) });
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
out.sort(
|
|
169
|
+
(a, b) =>
|
|
170
|
+
a.stage.staged_at.localeCompare(b.stage.staged_at) ||
|
|
171
|
+
a.stage.token.localeCompare(b.stage.token),
|
|
172
|
+
);
|
|
173
|
+
return out;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Atomically claim a pending stage and decide the outcome.
|
|
178
|
+
*
|
|
179
|
+
* Order matters and is the whole mechanism:
|
|
180
|
+
*
|
|
181
|
+
* 1. Read the record. An absent one is `token-mismatch` — from the caller's
|
|
182
|
+
* side an unknown token and a wrong token are the same fact, and inventing
|
|
183
|
+
* a third outcome for "was never staged" would only be actionable if the
|
|
184
|
+
* store were a public index, which it is not.
|
|
185
|
+
* 2. Ask `confirmOnce` what the outcome WOULD be. A mismatch, a decline, or
|
|
186
|
+
* an expiry never claims anything — a stale surface must not consume a
|
|
187
|
+
* stage a human might still legitimately confirm.
|
|
188
|
+
* 3. Only for `execute`: rename `pending/` → `resolved/`. That is the claim.
|
|
189
|
+
* `ENOENT` means a concurrent caller won the race, so this caller reports
|
|
190
|
+
* `already-confirmed` and does NOT act — the exactly-once guarantee.
|
|
191
|
+
* 4. Write the confirmed record into `resolved/`, overwriting the moved file
|
|
192
|
+
* with the same content plus `state`/`resolved_at`.
|
|
193
|
+
*/
|
|
194
|
+
export function claimConfirmation(
|
|
195
|
+
root: string,
|
|
196
|
+
token: string,
|
|
197
|
+
now: number,
|
|
198
|
+
): { outcome: ConfirmOutcome; stage: StagedAction | null } {
|
|
199
|
+
if (!isSafeToken(token)) {
|
|
200
|
+
// Nothing this module staged can have that shape, so the honest answer
|
|
201
|
+
// is the same one an unknown token gets — and refusing here is what
|
|
202
|
+
// keeps the rename below off an arbitrary path.
|
|
203
|
+
return { outcome: 'token-mismatch', stage: null };
|
|
204
|
+
}
|
|
205
|
+
const pendingFile = path.join(pendingDir(root), `${token}.json`);
|
|
206
|
+
const stage = readStageFile(pendingFile);
|
|
207
|
+
if (stage === null) {
|
|
208
|
+
const already = readResolved(root, token);
|
|
209
|
+
if (already !== null) {
|
|
210
|
+
// `pruneExpired` moves a stage here WITHOUT rewriting `state`, so the
|
|
211
|
+
// status is derived rather than read off the field — otherwise an
|
|
212
|
+
// expired stage swept out of `pending/` would report as confirmed,
|
|
213
|
+
// which is the one wrong answer available here.
|
|
214
|
+
const status = stageStatus(already, now);
|
|
215
|
+
const outcome: ConfirmOutcome =
|
|
216
|
+
status === 'expired' ? 'expired' : status === 'declined' ? 'declined' : 'already-confirmed';
|
|
217
|
+
return { outcome, stage: already };
|
|
218
|
+
}
|
|
219
|
+
return { outcome: 'token-mismatch', stage: null };
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const decided = confirmOnce(stage, token, now);
|
|
223
|
+
if (decided.outcome !== 'execute') {
|
|
224
|
+
return decided;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const resolvedFile = path.join(resolvedDir(root), `${token}.json`);
|
|
228
|
+
fs.mkdirSync(resolvedDir(root), { recursive: true });
|
|
229
|
+
try {
|
|
230
|
+
fs.renameSync(pendingFile, resolvedFile);
|
|
231
|
+
} catch {
|
|
232
|
+
// Lost the race, or the pending file vanished between the read and the
|
|
233
|
+
// rename. Either way this caller has NOT claimed the stage and must not
|
|
234
|
+
// act on it.
|
|
235
|
+
return { outcome: 'already-confirmed', stage: readResolved(root, token) ?? stage };
|
|
236
|
+
}
|
|
237
|
+
writeStageFile(resolvedFile, decided.stage);
|
|
238
|
+
return decided;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/** Decline a pending stage. Same claim discipline as `claimConfirmation`. */
|
|
242
|
+
export function declineConfirmation(
|
|
243
|
+
root: string,
|
|
244
|
+
token: string,
|
|
245
|
+
now: number,
|
|
246
|
+
): { declined: boolean; stage: StagedAction | null } {
|
|
247
|
+
if (!isSafeToken(token)) {
|
|
248
|
+
return { declined: false, stage: null };
|
|
249
|
+
}
|
|
250
|
+
const pendingFile = path.join(pendingDir(root), `${token}.json`);
|
|
251
|
+
const stage = readStageFile(pendingFile);
|
|
252
|
+
if (stage === null) {
|
|
253
|
+
return { declined: false, stage: readResolved(root, token) };
|
|
254
|
+
}
|
|
255
|
+
const decided = declineStage(stage, token, now);
|
|
256
|
+
if (!decided.declined) {
|
|
257
|
+
return { declined: false, stage };
|
|
258
|
+
}
|
|
259
|
+
const resolvedFile = path.join(resolvedDir(root), `${token}.json`);
|
|
260
|
+
fs.mkdirSync(resolvedDir(root), { recursive: true });
|
|
261
|
+
try {
|
|
262
|
+
fs.renameSync(pendingFile, resolvedFile);
|
|
263
|
+
} catch {
|
|
264
|
+
return { declined: false, stage: readResolved(root, token) ?? stage };
|
|
265
|
+
}
|
|
266
|
+
writeStageFile(resolvedFile, decided.stage);
|
|
267
|
+
return { declined: true, stage: decided.stage };
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Move expired stages out of `pending/` so the enumeration stays a list of
|
|
272
|
+
* live decisions. Housekeeping only — `stageStatus` already derives expiry, so
|
|
273
|
+
* skipping the sweep changes what is *listed*, never what may execute.
|
|
274
|
+
*/
|
|
275
|
+
export function pruneExpired(root: string, now: number): number {
|
|
276
|
+
let names: string[];
|
|
277
|
+
try {
|
|
278
|
+
names = fs.readdirSync(pendingDir(root));
|
|
279
|
+
} catch {
|
|
280
|
+
return 0;
|
|
281
|
+
}
|
|
282
|
+
let moved = 0;
|
|
283
|
+
for (const name of names.sort()) {
|
|
284
|
+
if (!name.endsWith('.json')) {
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
// Move the file that was ENUMERATED, never a path rebuilt from the
|
|
288
|
+
// record's `token` field. The two disagree whenever a filename and its
|
|
289
|
+
// token do — a record written by anything but `putPending` — and the
|
|
290
|
+
// rebuilt path then hits ENOENT, gets swallowed by the catch below, and
|
|
291
|
+
// the stage sits in `pending/` forever while `moved` under-reports it.
|
|
292
|
+
const from = path.join(pendingDir(root), name);
|
|
293
|
+
const stage = readStageFile(from);
|
|
294
|
+
if (stage === null || stageStatus(stage, now) !== 'expired') {
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
297
|
+
const to = path.join(resolvedDir(root), name);
|
|
298
|
+
fs.mkdirSync(resolvedDir(root), { recursive: true });
|
|
299
|
+
try {
|
|
300
|
+
fs.renameSync(from, to);
|
|
301
|
+
} catch {
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
moved += 1;
|
|
305
|
+
}
|
|
306
|
+
return moved;
|
|
307
|
+
}
|
package/dist/cli/registry.js
CHANGED
|
@@ -56,13 +56,13 @@ export const REGISTRY = [
|
|
|
56
56
|
{ name: 'mcp:run', disposition: 'delegate', synopsis: 'Run the built-in MCP server over stdio (experimental).' },
|
|
57
57
|
{ name: 'mcp-server', disposition: 'native', synopsis: 'Turnkey read-only stdio MCP server over the bundled content (no repo clone; ADR-085).' },
|
|
58
58
|
{ name: 'use', disposition: 'delegate', synopsis: 'Switch the active experience/profile (writes profile.id).' },
|
|
59
|
-
{ name: 'sessions:list', disposition: 'delegate', synopsis: 'List live agent sessions
|
|
59
|
+
{ name: 'sessions:list', disposition: 'delegate', synopsis: 'List live agent sessions plus unmerged branches held by other worktrees; --json, --branches.' },
|
|
60
60
|
{ name: 'sessions:claim', disposition: 'delegate', synopsis: 'Claim a roadmap for this session so other sessions skip it; --release clears it.' },
|
|
61
61
|
{ name: 'session:recycle', disposition: 'delegate', synopsis: 'Validate + write the main-session recycle envelope (--verify validates only); the successor resumes from it after /clear.' },
|
|
62
62
|
{ name: 'roadmap:progress', disposition: 'delegate', synopsis: 'Regenerate agents/roadmaps-progress.md from open roadmaps.' },
|
|
63
63
|
{ name: 'roadmap:progress-check', disposition: 'delegate', synopsis: 'Fail if agents/roadmaps-progress.md is stale (for CI).' },
|
|
64
64
|
{ name: 'roadmap:archive', disposition: 'delegate', synopsis: 'Archive completed roadmaps (PR-gate sweep).' },
|
|
65
|
-
{ name: 'gates', disposition: 'delegate', synopsis: 'Open decisions that need you, as actions — owner-filtered roadmap blockers; --all, --json, --reply.' },
|
|
65
|
+
{ name: 'gates', disposition: 'delegate', synopsis: 'Open decisions that need you, as actions — owner-filtered roadmap blockers; --all, --json, --reply, --pending (staged requires_confirmation actions).' },
|
|
66
66
|
{ name: 'capabilities:index', disposition: 'delegate', synopsis: 'Regenerate CAPABILITIES.yaml (the package coverage index); --check for CI.' },
|
|
67
67
|
{ name: 'affected', disposition: 'delegate', synopsis: 'Artefacts related to <artefact> via the discovery relation-graph (BFS).' },
|
|
68
68
|
{ name: 'graph-explain', disposition: 'delegate', synopsis: 'Seed on a <concept>, expand 2 hops over the discovery relation-graph with a node budget.' },
|
package/dist/cli/registry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/cli/registry.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/cli/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
hardenedSpawnEnv,
|
|
19
19
|
scanTranscripts,
|
|
20
20
|
weightedInputUnits
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-55RI5UXK.js";
|
|
22
22
|
import {
|
|
23
23
|
git_common_dir
|
|
24
24
|
} from "./chunk-PZWRPRWP.js";
|
|
@@ -1622,7 +1622,15 @@ import * as crypto from "node:crypto";
|
|
|
1622
1622
|
import * as fs7 from "node:fs";
|
|
1623
1623
|
import * as path10 from "node:path";
|
|
1624
1624
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
1625
|
-
|
|
1625
|
+
|
|
1626
|
+
// src/scripts/_lib/env_kill_switch.ts
|
|
1627
|
+
var _OFF_VALUES = /* @__PURE__ */ new Set(["", "0", "false", "False"]);
|
|
1628
|
+
function isEnvKillSwitchActive(name) {
|
|
1629
|
+
return !_OFF_VALUES.has(process.env[name] ?? "");
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
// src/scripts/ai_council/events_log.ts
|
|
1633
|
+
var SCHEMA_VERSION = 4;
|
|
1626
1634
|
var _VALID_ACTIONS = /* @__PURE__ */ new Set([
|
|
1627
1635
|
"proceed",
|
|
1628
1636
|
"skip_necessity",
|
|
@@ -1690,8 +1698,7 @@ function _utf8Bytes(cp) {
|
|
|
1690
1698
|
);
|
|
1691
1699
|
}
|
|
1692
1700
|
function _kill_switch_active() {
|
|
1693
|
-
|
|
1694
|
-
return !(value === "" || value === "0" || value === "false" || value === "False");
|
|
1701
|
+
return isEnvKillSwitchActive(_KILL_SWITCH_ENV);
|
|
1695
1702
|
}
|
|
1696
1703
|
function appendEvent(event, opts = {}) {
|
|
1697
1704
|
if (_kill_switch_active()) {
|