@event4u/agent-config 14.2.0 → 14.5.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 +33 -252
- package/agents/templates/.ai-council.yml.example +35 -0
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +83 -12
- package/dist/agent-src/rules/roadmap-progress-sync.md +48 -4
- package/dist/agent-src/scripts/resume_probe.ts +154 -9
- package/dist/agent-src/scripts/roadmap_gates.ts +210 -6
- package/dist/agent-src/skills/roadmap-management/SKILL.md +9 -4
- package/dist/agent-src/templates/agent-settings.md +70 -0
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/scripts/telemetry/remote.ts +571 -0
- package/dist/agent-src/templates/scripts/telemetry/settings.ts +222 -44
- package/dist/cli/python/workspace_drive.js +8 -3
- package/dist/cli/python/workspace_drive.js.map +1 -1
- package/dist/cli/python/workspace_hosts.js +16 -12
- package/dist/cli/python/workspace_hosts.js.map +1 -1
- package/dist/cli/registry.js +2 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli-delegate/{chunk-F3YUF7SA.js → chunk-3UCJWMMP.js} +1 -1
- package/dist/cli-delegate/chunk-F7DQWYR5.js +69 -0
- package/dist/cli-delegate/{chunk-7PZ4FSZB.js → chunk-FBKL6JWT.js} +61 -2
- package/dist/cli-delegate/{chunk-MNWRDMR5.js → chunk-PKOBQADP.js} +1 -1
- package/dist/cli-delegate/cmd_conformance.js +26 -11
- package/dist/cli-delegate/cmd_doctor.js +2 -2
- package/dist/cli-delegate/cmd_handoff.js +3 -3
- package/dist/cli-delegate/cmd_route_audit.js +2 -2
- package/dist/cli-delegate/cmd_settings_set.js +17 -3
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +4 -4
- 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 +3754 -1721
- package/dist/mcp/registry-manifest.json +2 -2
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +1070 -408
- package/dist/scripts/_lib/host_launch.js +66 -0
- package/dist/scripts/_lib/host_launch.js.map +1 -0
- package/dist/server/io/yamlIO.js +175 -3
- package/dist/server/io/yamlIO.js.map +1 -1
- package/dist/server/routes/wizard.js +20 -1
- package/dist/server/routes/wizard.js.map +1 -1
- package/dist/shared/settingsConsent.js +25 -0
- package/dist/shared/settingsConsent.js.map +1 -1
- package/docs/contracts/settings-classes.md +11 -0
- package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +2 -1
- package/package.json +1 -1
- package/src/agent-src/scripts/resume_probe.ts +154 -9
- package/src/agent-src/scripts/roadmap_gates.ts +210 -6
- package/src/agent-src/templates/scripts/telemetry/remote.ts +571 -0
- package/src/agent-src/templates/scripts/telemetry/settings.ts +222 -44
- package/src/config/estate-count-budget.json +127 -0
- package/src/config/evaluator-budgets.json +4 -4
- package/src/config/gate-coverage.yml +32 -4
- package/src/config/gate-violation-baselines.json +63 -63
- package/src/config/gitignore-block.txt +5 -0
- package/src/config/hook-latency-budget.json +40 -1
- package/src/config/hook-token-budget.json +16 -0
- package/src/config/rule-stub-ceilings.json +11 -3
- package/src/scripts/_dispatch.bash +42 -1
- package/src/scripts/_lib/council_fallback_posture.ts +81 -0
- package/src/scripts/_lib/council_fallback_wiring.ts +126 -0
- package/src/scripts/_lib/council_settings_block.ts +152 -0
- package/src/scripts/_lib/headless_invocation.ts +285 -0
- package/src/scripts/_lib/host_launch.ts +72 -0
- package/src/scripts/_lib/map_to_object.ts +16 -0
- package/src/scripts/_lib/roadmap_checkboxes.ts +88 -0
- package/src/scripts/_lib/run_checkpoint.ts +409 -0
- package/src/scripts/_lib/session_register.ts +32 -1
- package/src/scripts/_lib/stdin.ts +35 -1
- package/src/scripts/_lib/turn_end_refusals.ts +12 -4
- package/src/scripts/_lib/unattended_guard.ts +371 -0
- package/src/scripts/ai_council/config.ts +27 -1
- package/src/scripts/ai_council/events_log.ts +12 -1
- package/src/scripts/ai_council/fallback_config.ts +114 -0
- package/src/scripts/ai_council/mid_flight_fallback.ts +295 -0
- package/src/scripts/ai_council/orchestrator.ts +251 -292
- package/src/scripts/ai_council/py_parity.ts +139 -0
- package/src/scripts/ai_council/response_render.ts +99 -0
- package/src/scripts/ai_council/spend_gate.ts +123 -0
- package/src/scripts/ai_council/transport_resolver.ts +81 -13
- package/src/scripts/bench_hook_injection.ts +118 -7
- package/src/scripts/bench_hook_latency.ts +442 -16
- package/src/scripts/check_estate_count.ts +924 -0
- package/src/scripts/compile_hook_manifest.ts +67 -0
- package/src/scripts/council_cli.ts +100 -125
- package/src/scripts/decision_memo.ts +325 -0
- package/src/scripts/hook_manifest.json +1 -0
- package/src/scripts/hook_manifest.yaml +172 -25
- package/src/scripts/hooks/concern_registry.ts +6 -0
- package/src/scripts/hooks/dispatch_hook.ts +183 -10
- package/src/scripts/hooks/dispatch_issues.ts +26 -0
- package/src/scripts/hooks/end_review_nudge_hook.ts +97 -24
- package/src/scripts/hooks/hook_stdin.ts +111 -5
- package/src/scripts/hooks/host_semantics.ts +28 -0
- package/src/scripts/hooks/injection_budget.ts +731 -0
- package/src/scripts/hooks/payload_stub.ts +446 -0
- package/src/scripts/hooks/run_continuation_hook.ts +683 -0
- package/src/scripts/hooks/session_eol_hook.ts +52 -0
- package/src/scripts/hooks/telemetry_usage_hook.ts +339 -0
- package/src/scripts/hooks/tool_result_bytes_hook.ts +27 -0
- package/src/scripts/hooks/turn_end_gate_hook.ts +45 -7
- package/src/scripts/hooks_doctor.ts +16 -2
- package/src/scripts/interruption_report.ts +330 -13
- package/src/scripts/lint_hook_manifest.ts +167 -0
- package/src/scripts/roadmap_progress_hook.ts +254 -46
- package/src/scripts/run_supervise.ts +623 -0
- package/src/scripts/session_register_hook.ts +146 -12
- package/src/scripts/sessions_cli.ts +18 -6
- package/src/scripts/telemetry_disclosure_hook.ts +244 -0
- package/src/server/io/yamlIO.ts +167 -3
- package/src/shared/settingsConsent.ts +49 -2
- package/dist/cli-delegate/chunk-MMJL4TIX.js +0 -18
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* decision_memo — the decision-memo channel (UOTL Phase 4.3, sequenced by
|
|
3
|
+
* road-to-long-horizon-execution Phase 2.2).
|
|
4
|
+
*
|
|
5
|
+
* ## What this is for
|
|
6
|
+
*
|
|
7
|
+
* A question the agent resolves without contacting the user is only
|
|
8
|
+
* legitimate if the resolution is REVIEWABLE afterwards. Before this, a
|
|
9
|
+
* medium-impact resolution left no trace at all: the run either halted (a
|
|
10
|
+
* contact) or decided silently (no record). Neither is what the ladder wants
|
|
11
|
+
* between those two — the memo is.
|
|
12
|
+
*
|
|
13
|
+
* One file per resolution under
|
|
14
|
+
* `agents/runtime/state/decisions/<run>/NNN.md`, monotonic index per run.
|
|
15
|
+
* Local-only: the whole `agents/runtime/` tree is gitignored, so a memo never
|
|
16
|
+
* reaches a commit unless a human copies it out.
|
|
17
|
+
*
|
|
18
|
+
* ## Why a writer script rather than "the agent writes a markdown file"
|
|
19
|
+
*
|
|
20
|
+
* Two properties a prose instruction cannot give:
|
|
21
|
+
*
|
|
22
|
+
* - **The shape cannot drift.** Every memo carries the same five fields the
|
|
23
|
+
* roadmap names — question, chosen option, reasoning, resolver, confidence —
|
|
24
|
+
* because the writer refuses a memo missing any of them. A directory of
|
|
25
|
+
* free-form notes is not a channel, it is a folder.
|
|
26
|
+
* - **The index is monotonic and gap-free per run**, so "003 exists but 002
|
|
27
|
+
* does not" is impossible and a reader can tell a pruned memo from an
|
|
28
|
+
* unwritten one.
|
|
29
|
+
*
|
|
30
|
+
* ## What it deliberately does NOT do
|
|
31
|
+
*
|
|
32
|
+
* It does not decide anything, and it does not gate. A memo is a record of a
|
|
33
|
+
* resolution that already happened; making the writer refuse a resolution
|
|
34
|
+
* would put a decision gate in an observability surface, which is the shape
|
|
35
|
+
* `roadmap-progress` and the interruption ledger both stay clear of.
|
|
36
|
+
*
|
|
37
|
+
* It also carries no locked-class check, and that is not an omission to fix
|
|
38
|
+
* here: `high_impact` and `user_required` are refused at the SCHEMA
|
|
39
|
+
* (`config.ts::_build_decision_resolution`), before any model sees a route.
|
|
40
|
+
* A second check in the writer would read as the enforcement point and put
|
|
41
|
+
* the real one out of mind — the schema is the gate, this is the ledger.
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
import * as fs from 'node:fs';
|
|
45
|
+
import * as path from 'node:path';
|
|
46
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
47
|
+
|
|
48
|
+
export const DECISIONS_DIR_REL = path.join('agents', 'runtime', 'state', 'decisions');
|
|
49
|
+
|
|
50
|
+
/** The five fields the roadmap names, and nothing optional among them. */
|
|
51
|
+
export interface DecisionMemo {
|
|
52
|
+
/** The question as it was actually open — not a summary of the answer. */
|
|
53
|
+
question: string;
|
|
54
|
+
/** The option taken, stated so a reader can see what was NOT taken. */
|
|
55
|
+
chosen: string;
|
|
56
|
+
/** Why. The load-bearing field: without it the memo is a log line. */
|
|
57
|
+
reasoning: string;
|
|
58
|
+
/** Which rung resolved it — `agent`, `second-model:<provider>`, `council`. */
|
|
59
|
+
resolver: string;
|
|
60
|
+
/** Self-assessed, `high` | `medium` | `low`. Never a number. */
|
|
61
|
+
confidence: 'high' | 'medium' | 'low';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const CONFIDENCE: ReadonlySet<string> = new Set(['high', 'medium', 'low']);
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* A run id has to be a filename component. `safe` here is deliberately
|
|
68
|
+
* narrow rather than a sanitiser: a run id that needs escaping is a caller
|
|
69
|
+
* bug, and silently rewriting it would put two runs in one directory.
|
|
70
|
+
*/
|
|
71
|
+
export function isSafeRunId(runId: string): boolean {
|
|
72
|
+
return /^[A-Za-z0-9_-]{1,64}$/.test(runId);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function runDir(repoRoot: string, runId: string): string {
|
|
76
|
+
return path.join(repoRoot, DECISIONS_DIR_REL, runId);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* The next index for this run — one past the highest `NNN.md` present.
|
|
81
|
+
*
|
|
82
|
+
* Reads the directory rather than a counter file: a counter that drifts from
|
|
83
|
+
* the directory is a second source of truth, and the directory is the one a
|
|
84
|
+
* human reads.
|
|
85
|
+
*/
|
|
86
|
+
export function nextIndex(dir: string): number {
|
|
87
|
+
let entries: string[];
|
|
88
|
+
try {
|
|
89
|
+
entries = fs.readdirSync(dir);
|
|
90
|
+
} catch {
|
|
91
|
+
return 1;
|
|
92
|
+
}
|
|
93
|
+
let max = 0;
|
|
94
|
+
for (const name of entries) {
|
|
95
|
+
const m = /^(\d{3})\.md$/.exec(name);
|
|
96
|
+
if (m === null) continue;
|
|
97
|
+
const n = Number.parseInt(m[1] as string, 10);
|
|
98
|
+
if (Number.isFinite(n) && n > max) max = n;
|
|
99
|
+
}
|
|
100
|
+
return max + 1;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Refusal reasons, as a list so a caller can report all of them at once. */
|
|
104
|
+
export function validate(memo: Partial<DecisionMemo>): string[] {
|
|
105
|
+
const problems: string[] = [];
|
|
106
|
+
for (const field of ['question', 'chosen', 'reasoning', 'resolver'] as const) {
|
|
107
|
+
const v = memo[field];
|
|
108
|
+
if (typeof v !== 'string' || v.trim() === '') {
|
|
109
|
+
problems.push(`${field} is required and must be non-empty`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const c = memo.confidence;
|
|
113
|
+
if (typeof c !== 'string' || !CONFIDENCE.has(c)) {
|
|
114
|
+
problems.push(`confidence must be one of high | medium | low (got ${String(c)})`);
|
|
115
|
+
}
|
|
116
|
+
return problems;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function render(memo: DecisionMemo, index: number, stampedAt: string): string {
|
|
120
|
+
return [
|
|
121
|
+
`# Decision ${String(index).padStart(3, '0')}`,
|
|
122
|
+
'',
|
|
123
|
+
`- **Resolver:** ${memo.resolver}`,
|
|
124
|
+
`- **Confidence:** ${memo.confidence}`,
|
|
125
|
+
`- **Recorded:** ${stampedAt}`,
|
|
126
|
+
'',
|
|
127
|
+
'## Question',
|
|
128
|
+
'',
|
|
129
|
+
memo.question.trim(),
|
|
130
|
+
'',
|
|
131
|
+
'## Chosen',
|
|
132
|
+
'',
|
|
133
|
+
memo.chosen.trim(),
|
|
134
|
+
'',
|
|
135
|
+
'## Reasoning',
|
|
136
|
+
'',
|
|
137
|
+
memo.reasoning.trim(),
|
|
138
|
+
'',
|
|
139
|
+
].join('\n');
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export interface WriteResult {
|
|
143
|
+
path: string;
|
|
144
|
+
index: number;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Write one memo. Throws on a validation failure — a memo that cannot be
|
|
149
|
+
* written is a caller bug and must not degrade into a partial record.
|
|
150
|
+
*/
|
|
151
|
+
export function writeMemo(
|
|
152
|
+
repoRoot: string,
|
|
153
|
+
runId: string,
|
|
154
|
+
memo: DecisionMemo,
|
|
155
|
+
opts: { now?: () => Date } = {},
|
|
156
|
+
): WriteResult {
|
|
157
|
+
if (!isSafeRunId(runId)) {
|
|
158
|
+
throw new Error(
|
|
159
|
+
`decision_memo: run id ${JSON.stringify(runId)} is not a safe filename ` +
|
|
160
|
+
`component (letters, digits, _ and - only, 1..64 chars)`,
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
const problems = validate(memo);
|
|
164
|
+
if (problems.length > 0) {
|
|
165
|
+
throw new Error(`decision_memo: refusing an incomplete memo — ${problems.join('; ')}`);
|
|
166
|
+
}
|
|
167
|
+
const dir = runDir(repoRoot, runId);
|
|
168
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
169
|
+
const stamp = (opts.now ?? ((): Date => new Date()))().toISOString();
|
|
170
|
+
// Claim the slot with `wx` and retry on collision, rather than
|
|
171
|
+
// read-then-write.
|
|
172
|
+
//
|
|
173
|
+
// R2 review, finding 10. `nextIndex` followed by a plain `writeFileSync`
|
|
174
|
+
// is a read-then-write with no lock: two memos written for the same run
|
|
175
|
+
// concurrently — the unattended or parallel lane this module exists for,
|
|
176
|
+
// or simply two shell calls — compute the same index and the second
|
|
177
|
+
// silently overwrites the first. That breaks the exact property the header
|
|
178
|
+
// sells as this module's reason to exist ("monotonic and gap-free per run,
|
|
179
|
+
// so a reader can tell a pruned memo from an unwritten one"), because a
|
|
180
|
+
// LOST memo leaves no gap at all.
|
|
181
|
+
//
|
|
182
|
+
// The bound is generous and finite: a loop that cannot fail would hide a
|
|
183
|
+
// permission error as a hang.
|
|
184
|
+
const MAX_ATTEMPTS = 64;
|
|
185
|
+
for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
|
|
186
|
+
const index = nextIndex(dir);
|
|
187
|
+
const file = path.join(dir, `${String(index).padStart(3, '0')}.md`);
|
|
188
|
+
try {
|
|
189
|
+
fs.writeFileSync(file, render(memo, index, stamp), { encoding: 'utf-8', flag: 'wx' });
|
|
190
|
+
return { path: file, index };
|
|
191
|
+
} catch (err) {
|
|
192
|
+
// EEXIST means another writer took this index between the read and
|
|
193
|
+
// the write — re-read and take the next one. Anything else (EACCES,
|
|
194
|
+
// ENOSPC) is a real failure and must not be retried into a hang.
|
|
195
|
+
if ((err as NodeJS.ErrnoException).code !== 'EEXIST') throw err;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
throw new Error(
|
|
199
|
+
`decision_memo: could not claim an index for run ${JSON.stringify(runId)} ` +
|
|
200
|
+
`after ${MAX_ATTEMPTS} attempts — another writer is taking every slot`,
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** Every memo of one run, in index order. */
|
|
205
|
+
export function listMemos(repoRoot: string, runId: string): string[] {
|
|
206
|
+
const dir = runDir(repoRoot, runId);
|
|
207
|
+
let entries: string[];
|
|
208
|
+
try {
|
|
209
|
+
entries = fs.readdirSync(dir);
|
|
210
|
+
} catch {
|
|
211
|
+
return [];
|
|
212
|
+
}
|
|
213
|
+
return entries
|
|
214
|
+
.filter((n) => /^\d{3}\.md$/.test(n))
|
|
215
|
+
.sort()
|
|
216
|
+
.map((n) => path.join(dir, n));
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const USAGE = `usage: decision_memo write --run <id> --question <q> --chosen <c> \\
|
|
220
|
+
--reasoning <r> --resolver <who> --confidence <high|medium|low>
|
|
221
|
+
decision_memo list --run <id>
|
|
222
|
+
|
|
223
|
+
Records one autonomously-resolved question so it is reviewable after the run.
|
|
224
|
+
Writes agents/runtime/state/decisions/<run>/NNN.md — local-only (gitignored).
|
|
225
|
+
|
|
226
|
+
--run takes ANY slug, and that freedom has a cost worth stating (R2 round 4,
|
|
227
|
+
finding 3): interruption_report attributes memos to a run by joining on the
|
|
228
|
+
session-derived run id, so a memo written under a hand-picked slug is counted
|
|
229
|
+
by 'run:supervise --digest' (which counts directories) and NOT by the report's
|
|
230
|
+
median_memos_per_run (which joins). The two disagree about the same files, and
|
|
231
|
+
the report's zero reads as "no memos" rather than "no join".
|
|
232
|
+
|
|
233
|
+
To be attributable, pass the id the ledger uses:
|
|
234
|
+
agent-config run:supervise --digest # lists the session ids in play
|
|
235
|
+
A free-form slug is still valid and still recorded — it is simply a memo about
|
|
236
|
+
a run the report cannot name.
|
|
237
|
+
|
|
238
|
+
Locked classes (high_impact, user_required) are refused at the CONFIG SCHEMA,
|
|
239
|
+
never here: this is the ledger, not the gate.
|
|
240
|
+
`;
|
|
241
|
+
|
|
242
|
+
function argValue(argv: string[], flag: string): string | null {
|
|
243
|
+
const i = argv.indexOf(flag);
|
|
244
|
+
if (i === -1 || i + 1 >= argv.length) return null;
|
|
245
|
+
return argv[i + 1] ?? null;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export function main(argv: string[] = process.argv.slice(2)): number {
|
|
249
|
+
const sub = argv[0] ?? '';
|
|
250
|
+
if (sub === '' || sub === '--help' || sub === '-h') {
|
|
251
|
+
process.stdout.write(USAGE);
|
|
252
|
+
return sub === '' ? 2 : 0;
|
|
253
|
+
}
|
|
254
|
+
const repoRoot = argValue(argv, '--root') ?? process.cwd();
|
|
255
|
+
const runId = argValue(argv, '--run');
|
|
256
|
+
if (runId === null) {
|
|
257
|
+
process.stderr.write('decision_memo: --run <id> is required\n');
|
|
258
|
+
return 2;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (sub === 'list') {
|
|
262
|
+
const memos = listMemos(repoRoot, runId);
|
|
263
|
+
if (memos.length === 0) {
|
|
264
|
+
process.stdout.write(`decision_memo: no memos for run ${runId}\n`);
|
|
265
|
+
return 0;
|
|
266
|
+
}
|
|
267
|
+
for (const m of memos) {
|
|
268
|
+
process.stdout.write(`${path.relative(repoRoot, m)}\n`);
|
|
269
|
+
}
|
|
270
|
+
return 0;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (sub !== 'write') {
|
|
274
|
+
process.stderr.write(`decision_memo: unknown subcommand '${sub}'\n${USAGE}`);
|
|
275
|
+
return 2;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const memo: Partial<DecisionMemo> = {
|
|
279
|
+
question: argValue(argv, '--question') ?? '',
|
|
280
|
+
chosen: argValue(argv, '--chosen') ?? '',
|
|
281
|
+
reasoning: argValue(argv, '--reasoning') ?? '',
|
|
282
|
+
resolver: argValue(argv, '--resolver') ?? '',
|
|
283
|
+
confidence: (argValue(argv, '--confidence') ?? '') as DecisionMemo['confidence'],
|
|
284
|
+
};
|
|
285
|
+
const problems = validate(memo);
|
|
286
|
+
if (problems.length > 0) {
|
|
287
|
+
process.stderr.write(`decision_memo: ${problems.join('; ')}\n`);
|
|
288
|
+
return 2;
|
|
289
|
+
}
|
|
290
|
+
try {
|
|
291
|
+
const res = writeMemo(repoRoot, runId, memo as DecisionMemo);
|
|
292
|
+
process.stdout.write(`${path.relative(repoRoot, res.path)}\n`);
|
|
293
|
+
return 0;
|
|
294
|
+
} catch (exc) {
|
|
295
|
+
process.stderr.write(`${exc instanceof Error ? exc.message : String(exc)}\n`);
|
|
296
|
+
return 2;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* The realpath-comparing form, not a `basename` test: an installed projection
|
|
302
|
+
* and macOS `/var` → `/private/var` both make `argv[1]` a symlink whose URL
|
|
303
|
+
* differs from `import.meta.url`, and a naive comparison silently no-ops the
|
|
304
|
+
* CLI. Same shape as `interruption_report.ts::_isCliEntry`.
|
|
305
|
+
*/
|
|
306
|
+
function _isCliEntry(): boolean {
|
|
307
|
+
if (process.argv[1] === undefined) {
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
310
|
+
const argvUrl = pathToFileURL(path.resolve(process.argv[1])).href;
|
|
311
|
+
if (import.meta.url === argvUrl) {
|
|
312
|
+
return true;
|
|
313
|
+
}
|
|
314
|
+
try {
|
|
315
|
+
const here = fs.realpathSync(fileURLToPath(import.meta.url));
|
|
316
|
+
const argv = fs.realpathSync(path.resolve(process.argv[1]));
|
|
317
|
+
return here === argv;
|
|
318
|
+
} catch {
|
|
319
|
+
return false;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (_isCliEntry()) {
|
|
324
|
+
process.exit(main());
|
|
325
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"fingerprint":"4834904a:65187","manifest":{"schema_version":1,"concerns":{"chat-history":{"script":"src/scripts/chat_history.ts","args":["hook-dispatch"],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["result"]},"hot-context":{"script":"src/scripts/hot_context_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"handoff-context":{"script":"src/scripts/handoff_context_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"roadmap-progress":{"script":"src/scripts/roadmap_progress_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"onboarding-gate":{"script":"src/scripts/onboarding_gate_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"context-hygiene":{"script":"src/scripts/context_hygiene_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"verify-before-complete":{"script":"src/scripts/before_complete_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input","result"]},"ship-diff-volume":{"script":"src/scripts/hooks/ship_diff_volume_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"minimal-safe-diff":{"script":"src/scripts/minimal_safe_diff_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"injection-scan":{"script":"src/scripts/injection_scan_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input","result"]},"block-no-verify":{"script":"src/scripts/hooks/block_no_verify.ts","args":[],"fail_closed":true,"severity":"blocking","needs_payload_bodies":["input"]},"block-kernel-rule-writes":{"script":"src/scripts/hooks/block_kernel_rule_writes.ts","args":[],"fail_closed":true,"severity":"blocking","needs_payload_bodies":["input"]},"block-config-weakening":{"script":"src/scripts/hooks/block_config_weakening.ts","args":[],"fail_closed":false,"severity":"blocking","needs_payload_bodies":["input"]},"rtk-wrap":{"script":"src/scripts/hooks/rtk_wrap_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"design-slop":{"script":"src/scripts/hooks/design_slop_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"ui-route-nudge":{"script":"src/scripts/hooks/ui_route_nudge_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"code-graph-nudge":{"script":"src/scripts/hooks/code_graph_nudge_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Grep","Glob","Read"],"needs_payload_bodies":["input"]},"memory-learn":{"script":"src/scripts/memory_learn_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"first-run-gate":{"script":"src/scripts/first_run_gate_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"profile-staleness":{"script":"src/scripts/profile_staleness_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"wrapper-freshness":{"script":"src/scripts/wrapper_freshness_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"surface-probe":{"script":"src/scripts/surface_probe_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"team-review-gate":{"script":"src/scripts/team_review_gate_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"pr-url-reminder":{"script":"src/scripts/pr_url_reminder_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input","result"]},"language-mirror":{"script":"src/scripts/language_mirror_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"git-authorization":{"script":"src/scripts/git_authorization_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"block-unauthorized-git":{"script":"src/scripts/hooks/block_unauthorized_git.ts","args":[],"fail_closed":true,"severity":"blocking","needs_payload_bodies":["input"]},"evidence-independence":{"script":"src/scripts/hooks/evidence_independence.ts","args":[],"fail_closed":false,"severity":"blocking","needs_payload_bodies":["input"]},"session-canary":{"script":"src/scripts/session_canary_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"council-availability":{"script":"src/scripts/council_availability_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"telemetry-disclosure":{"script":"src/scripts/telemetry_disclosure_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"self-repair":{"script":"src/scripts/self_repair_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"session-register":{"script":"src/scripts/session_register_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"orchestration-record":{"script":"src/scripts/hooks/orchestration_record_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Agent","Task"],"needs_payload_bodies":["input","result"]},"telemetry-usage":{"script":"src/scripts/hooks/telemetry_usage_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Skill"],"needs_payload_bodies":["input"]},"delegation-nudge":{"script":"src/scripts/hooks/delegation_nudge_hook.ts","args":[],"fail_closed":false,"severity":"advisory","nudge_rank":1},"skill-route":{"script":"src/scripts/hooks/skill_route_hook.ts","args":[],"fail_closed":false,"severity":"advisory","nudge_rank":2},"end-review-nudge":{"script":"src/scripts/hooks/end_review_nudge_hook.ts","args":[],"fail_closed":false,"severity":"advisory","skip_on_refusal_retry":true},"turn-end-gate":{"script":"src/scripts/hooks/turn_end_gate_hook.ts","args":[],"fail_closed":false,"severity":"blocking"},"edit-shape":{"script":"src/scripts/hooks/edit_shape_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Write"],"needs_payload_bodies":["input"]},"reread-guard":{"script":"src/scripts/hooks/reread_guard_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Read","Edit","Write"],"needs_payload_bodies":["input"]},"session-eol":{"script":"src/scripts/hooks/session_eol_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"run-continuation":{"script":"src/scripts/hooks/run_continuation_hook.ts","args":[],"fail_closed":false,"severity":"blocking"},"interruption-ledger":{"script":"src/scripts/hooks/interruption_ledger_hook.ts","args":[],"fail_closed":false,"severity":"advisory","skip_on_refusal_retry":true},"subagent-ledger":{"script":"src/scripts/hooks/subagent_ledger_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"tool-result-bytes":{"script":"src/scripts/hooks/tool_result_bytes_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"spawn-guard-shadow":{"script":"src/scripts/hooks/spawn_guard_shadow_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Agent","Task"]}},"roles":{"worker":{"drop":["delegation-nudge","skill-route","end-review-nudge","council-availability","team-review-gate","self-repair","session-eol","interruption-ledger"]}},"platforms":{"augment":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress"],"pre_tool_use":["block-no-verify","block-unauthorized-git","evidence-independence","block-kernel-rule-writes","block-config-weakening","rtk-wrap","design-slop","ui-route-nudge","code-graph-nudge","ship-diff-volume","reread-guard"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape"]},"claude":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress"],"stop":["chat-history","hot-context","verify-before-complete","team-review-gate","end-review-nudge","turn-end-gate","self-repair","session-register","session-eol","interruption-ledger","roadmap-progress","run-continuation"],"user_prompt_submit":["chat-history","verify-before-complete","minimal-safe-diff","language-mirror","delegation-nudge","skill-route","git-authorization","session-canary","self-repair","session-register"],"pre_tool_use":["block-no-verify","block-unauthorized-git","evidence-independence","block-kernel-rule-writes","block-config-weakening","rtk-wrap","design-slop","ui-route-nudge","code-graph-nudge","ship-diff-volume","reread-guard","spawn-guard-shadow"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape","language-mirror"],"pre_compact":["language-mirror","hot-context"],"subagent_start":["subagent-ledger"],"subagent_stop":["subagent-ledger"]},"cowork":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress"],"user_prompt_submit":["chat-history","verify-before-complete","minimal-safe-diff","language-mirror","git-authorization","session-canary","self-repair","session-register"],"pre_tool_use":["block-no-verify","block-unauthorized-git","evidence-independence","block-kernel-rule-writes","block-config-weakening","rtk-wrap","design-slop","ui-route-nudge","code-graph-nudge","ship-diff-volume","reread-guard","spawn-guard-shadow"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape"],"subagent_start":["subagent-ledger"],"subagent_stop":["subagent-ledger"]},"cursor":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress"],"user_prompt_submit":["chat-history","verify-before-complete","minimal-safe-diff","language-mirror","git-authorization","session-canary","self-repair","session-register"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape"]},"cline":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress"],"user_prompt_submit":["chat-history","verify-before-complete","minimal-safe-diff","language-mirror","git-authorization","session-canary","self-repair","session-register"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape"]},"windsurf":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","profile-staleness","wrapper-freshness","surface-probe","session-register"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register"],"user_prompt_submit":["chat-history","verify-before-complete","language-mirror","git-authorization","session-canary","self-repair","session-register"]},"gemini":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress"],"user_prompt_submit":["chat-history","verify-before-complete","minimal-safe-diff","language-mirror","git-authorization","session-canary","self-repair","session-register"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape"]},"copilot":{"fallback_only":true}},"native_event_aliases":{"augment":{"SessionStart":"session_start","SessionEnd":"session_end","Stop":"stop","PostToolUse":"post_tool_use","PreToolUse":"pre_tool_use"},"claude":{"SessionStart":"session_start","SessionEnd":"session_end","Stop":"stop","UserPromptSubmit":"user_prompt_submit","PostToolUse":"post_tool_use","PreToolUse":"pre_tool_use","PreCompact":"pre_compact","SubagentStart":"subagent_start","SubagentStop":"subagent_stop"},"cowork":{"SessionStart":"session_start","SessionEnd":"session_end","Stop":"stop","UserPromptSubmit":"user_prompt_submit","PostToolUse":"post_tool_use","PreToolUse":"pre_tool_use","PreCompact":"pre_compact","SubagentStart":"subagent_start","SubagentStop":"subagent_stop"},"cursor":{"sessionStart":"session_start","sessionEnd":"session_end","stop":"stop","beforeSubmitPrompt":"user_prompt_submit","postToolUse":"post_tool_use","preToolUse":"pre_tool_use","preCompact":"pre_compact"},"cline":{"TaskStart":"session_start","TaskResume":"session_start","TaskComplete":"session_end","TaskCancel":"stop","UserPromptSubmit":"user_prompt_submit","PostToolUse":"post_tool_use","PreToolUse":"pre_tool_use","PreCompact":"pre_compact"},"windsurf":{"pre_user_prompt":"user_prompt_submit","post_cascade_response":"stop","post_setup_worktree":"session_start"},"gemini":{"SessionStart":"session_start","SessionEnd":"session_end","BeforeAgent":"user_prompt_submit","AfterAgent":"stop","BeforeTool":"pre_tool_use","AfterTool":"post_tool_use"}}}}
|