@event4u/agent-config 14.13.0 → 14.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.augment-plugin/marketplace.json +3 -3
- package/.augment-plugin/plugin.json +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +116 -387
- package/dist/agent-src/commands/analyze/inbox.md +36 -0
- package/dist/agent-src/rules/code-comment-discipline.md +6 -0
- package/dist/agent-src/scripts/archive_completed_roadmaps.ts +6 -6
- package/dist/agent-src/scripts/guarded_baseline.ts +22 -7
- package/dist/agent-src/scripts/stubs_due.ts +118 -2
- package/dist/agent-src/scripts/update_roadmap_progress.ts +8 -8
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/cli-delegate/cmd_conformance.js +38 -1
- 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 +1438 -711
- package/dist/mcp/registry-manifest.json +2 -2
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +112 -17
- package/docs/guidelines/agent-infra/guarded-baseline.md +1 -1
- package/docs/guidelines/code-clarity.md +18 -0
- package/package.json +1 -1
- package/src/agent-src/scripts/archive_completed_roadmaps.ts +6 -6
- package/src/agent-src/scripts/guarded_baseline.ts +22 -7
- package/src/agent-src/scripts/stubs_due.ts +118 -2
- package/src/agent-src/scripts/update_roadmap_progress.ts +8 -8
- package/src/config/estate-count-budget.json +20 -1
- package/src/config/gate-coverage.yml +150 -0
- package/src/config/gate-violation-baselines.json +8 -3
- package/src/config/preamble-payload-budget.json +19 -11
- package/src/config/rule-stub-ceilings.json +14 -7
- package/src/scripts/_dispatch.bash +0 -4
- package/src/scripts/_lib/activation_ladder.ts +47 -3
- package/src/scripts/_lib/activation_receipt_producer.ts +341 -0
- package/src/scripts/_lib/adr_frontmatter.ts +26 -0
- package/src/scripts/_lib/candidate_pair_delta.ts +349 -0
- package/src/scripts/_lib/carrier_status.ts +118 -0
- package/src/scripts/_lib/cascade_stage_enumeration.ts +92 -0
- package/src/scripts/_lib/corpus_manifest.ts +726 -0
- package/src/scripts/_lib/delivery_arm_experiment.ts +18 -2
- package/src/scripts/_lib/estate_carrier_cases.ts +72 -0
- package/src/scripts/_lib/evaluation_cascade.ts +452 -0
- package/src/scripts/_lib/evolution_roi.ts +562 -0
- package/src/scripts/_lib/harness_evolution_guards.ts +10 -0
- package/src/scripts/_lib/lexical_shortlist.ts +215 -0
- package/src/scripts/_lib/llm_candidate_proposer.ts +461 -0
- package/src/scripts/_lib/llm_proposer_transport.ts +153 -0
- package/src/scripts/_lib/pathology_archive.ts +393 -0
- package/src/scripts/_lib/promotion_capability.ts +315 -0
- package/src/scripts/_lib/promotion_evidence.ts +414 -0
- package/src/scripts/_lib/promotion_review.ts +294 -0
- package/src/scripts/_lib/prompt_shape.ts +92 -0
- package/src/scripts/_lib/release_highlights.ts +70 -1
- package/src/scripts/_lib/release_material.ts +125 -2
- package/src/scripts/_lib/routing_corpus.ts +307 -0
- package/src/scripts/_lib/routing_index_input.ts +104 -0
- package/src/scripts/_lib/rule_injection.ts +22 -1
- package/src/scripts/_lib/semantic_noop.ts +167 -0
- package/src/scripts/activation_receipt.ts +258 -0
- package/src/scripts/ai_council/cross_exam.ts +128 -0
- package/src/scripts/ai_council/explain_route.ts +157 -0
- package/src/scripts/ai_council/information_gain.ts +293 -0
- package/src/scripts/ai_council/leakage_corpus.ts +385 -0
- package/src/scripts/ai_council/leakage_patterns.ts +453 -0
- package/src/scripts/ai_council/minority_retention.ts +171 -0
- package/src/scripts/ai_council/recouncil_savings.ts +299 -0
- package/src/scripts/ai_council/replay_route.ts +223 -0
- package/src/scripts/ai_council/reviewer_assignment.ts +279 -0
- package/src/scripts/ai_council/routing_training_row.ts +197 -0
- package/src/scripts/ai_council/synthesis_strategy.ts +159 -0
- package/src/scripts/check_adr_frontmatter.ts +4 -9
- package/src/scripts/check_estate_count.ts +205 -24
- package/src/scripts/check_release_highlights.ts +96 -13
- package/src/scripts/check_roadmap_trackable.ts +17 -2
- package/src/scripts/corpus_manifest.ts +235 -0
- package/src/scripts/evolution_lab.ts +181 -8
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +28 -6
- package/src/scripts/hooks/comment_discipline_hook.ts +146 -0
- package/src/scripts/hooks/concern_registry.ts +2 -0
- package/src/scripts/hooks/turn_end_gate_hook.ts +9 -1
- package/src/scripts/language_mirror_hook.ts +14 -2
- package/src/scripts/lint_carrier_integrity.ts +820 -0
- package/src/scripts/lint_code_comments.ts +643 -0
- package/src/scripts/lint_plan_risk_register.ts +39 -19
- package/src/scripts/lint_promotion_paths.ts +779 -0
- package/src/scripts/llm_propose.ts +256 -0
- package/src/scripts/measure_delivery_sets.ts +361 -0
- package/src/scripts/measure_routing_signal.ts +307 -0
- package/src/scripts/model_rule_injection.ts +19 -3
- package/src/scripts/probe_council_retention.ts +495 -0
- package/src/scripts/release.ts +21 -37
- package/src/scripts/release_drill.ts +143 -0
- package/src/scripts/release_env.ts +35 -0
- package/src/scripts/release_publication.ts +84 -0
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* `corpus_manifest` — pin the metered-proposer experiment's subject, and check
|
|
4
|
+
* that a fresh checkout reproduces it.
|
|
5
|
+
*
|
|
6
|
+
* Two verbs and no third. `capture` writes the pin from the tree as it stands;
|
|
7
|
+
* `verify` re-captures and reports every difference against a pin on disk.
|
|
8
|
+
* There is deliberately no `update` verb: a pin that can be refreshed in place
|
|
9
|
+
* is a pin that silently follows the tree, which is the property it exists not
|
|
10
|
+
* to have.
|
|
11
|
+
*
|
|
12
|
+
* `verify` exits 3 when the SUBJECT differs and 0 when only the explanatory
|
|
13
|
+
* fields do. That split is the whole point of the exit code — a different
|
|
14
|
+
* runtime version is a fact worth printing and is not a reason to refuse a
|
|
15
|
+
* comparison, while a different subject means the two runs measured different
|
|
16
|
+
* things and no amount of green elsewhere repairs it.
|
|
17
|
+
*
|
|
18
|
+
* Nothing here spends: it reads files and shells out to `git` for the commit.
|
|
19
|
+
*/
|
|
20
|
+
import * as fs from 'node:fs';
|
|
21
|
+
import * as os from 'node:os';
|
|
22
|
+
import * as path from 'node:path';
|
|
23
|
+
import process from 'node:process';
|
|
24
|
+
import { fileURLToPath } from 'node:url';
|
|
25
|
+
|
|
26
|
+
import { partitionActive } from '../install/partitionEligibility.js';
|
|
27
|
+
import {
|
|
28
|
+
type CorpusManifest,
|
|
29
|
+
captureManifest,
|
|
30
|
+
diffManifests,
|
|
31
|
+
parseManifest,
|
|
32
|
+
serialiseManifest,
|
|
33
|
+
subjectsEquivalent,
|
|
34
|
+
} from './_lib/corpus_manifest.js';
|
|
35
|
+
|
|
36
|
+
const _HERE = fileURLToPath(import.meta.url);
|
|
37
|
+
const REPO_ROOT = path.resolve(path.dirname(_HERE), '..', '..');
|
|
38
|
+
|
|
39
|
+
export const EXIT_OK = 0;
|
|
40
|
+
export const EXIT_ERROR = 1;
|
|
41
|
+
export const EXIT_USAGE = 2;
|
|
42
|
+
/** The subject differs. Distinct from a plain error so a runner can branch. */
|
|
43
|
+
export const EXIT_SUBJECT_DIFFERS = 3;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The enumeration rule this manifest pins under, as an ID rather than prose.
|
|
47
|
+
*
|
|
48
|
+
* It is part of the digest, so changing the rule changes the subject even when
|
|
49
|
+
* every file hash is unchanged. That is correct: a corpus of the same five
|
|
50
|
+
* files selected by a different rule is a different experiment, and a digest
|
|
51
|
+
* that could not see the difference would let the selection semantics be
|
|
52
|
+
* amended without the pin noticing.
|
|
53
|
+
*/
|
|
54
|
+
export const ENUMERATION_RULE_ID = 'claude-rules-md-bytesorted-first-N/v1';
|
|
55
|
+
|
|
56
|
+
const USAGE = `usage: corpus_manifest capture --out FILE [--limit N]
|
|
57
|
+
corpus_manifest verify --manifest FILE
|
|
58
|
+
|
|
59
|
+
capture write the subject pin from the tree as it stands
|
|
60
|
+
verify re-capture and report every difference against FILE
|
|
61
|
+
|
|
62
|
+
--limit N corpus size, on CAPTURE only; defaults to max_candidates from the
|
|
63
|
+
pre-registered budget, which is the ceiling the run guard aborts
|
|
64
|
+
on. verify re-captures at the size its own manifest pinned, so it
|
|
65
|
+
REFUSES --limit rather than accepting a flag it cannot honour
|
|
66
|
+
|
|
67
|
+
Exit: 0 ok · 1 error · 2 usage · 3 the SUBJECT differs
|
|
68
|
+
`;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The corpus size, read from the pre-registered budget rather than defaulted.
|
|
72
|
+
*
|
|
73
|
+
* Hardcoding five here would put a second copy of a pre-registered number in a
|
|
74
|
+
* file nobody would think to check when the budget changed, and the two would
|
|
75
|
+
* disagree in the direction that matters: a manifest pinning more subjects than
|
|
76
|
+
* the run guard admits describes an experiment that cannot be run.
|
|
77
|
+
*/
|
|
78
|
+
export function defaultLimit(repoRoot: string = REPO_ROOT): number {
|
|
79
|
+
const raw = JSON.parse(
|
|
80
|
+
fs.readFileSync(path.join(repoRoot, 'src', 'config', 'harness-evolution-budget.json'), 'utf-8'),
|
|
81
|
+
) as { budget?: { max_candidates?: unknown } };
|
|
82
|
+
const n = raw.budget?.max_candidates;
|
|
83
|
+
if (typeof n !== 'number' || !Number.isInteger(n) || n <= 0) {
|
|
84
|
+
throw new Error('max_candidates missing or not a positive integer in the pre-registered budget');
|
|
85
|
+
}
|
|
86
|
+
return n;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
interface Parsed {
|
|
90
|
+
verb?: string;
|
|
91
|
+
out?: string;
|
|
92
|
+
manifest?: string;
|
|
93
|
+
limit?: number;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function parseArgs(argv: readonly string[]): Parsed | string {
|
|
97
|
+
const p: Parsed = {};
|
|
98
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
99
|
+
const a = argv[i] as string;
|
|
100
|
+
if (!a.startsWith('--') && p.verb === undefined) {
|
|
101
|
+
p.verb = a;
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
const v = argv[i + 1];
|
|
105
|
+
if (v === undefined || v.startsWith('--')) return `${a} requires a value`;
|
|
106
|
+
i += 1;
|
|
107
|
+
if (a === '--out') p.out = v;
|
|
108
|
+
else if (a === '--manifest') p.manifest = v;
|
|
109
|
+
else if (a === '--limit') {
|
|
110
|
+
const n = Number(v);
|
|
111
|
+
if (!Number.isInteger(n) || n <= 0) return '--limit must be a positive integer';
|
|
112
|
+
p.limit = n;
|
|
113
|
+
} else return `unknown option '${a}'`;
|
|
114
|
+
}
|
|
115
|
+
if (p.verb === 'verify' && p.limit !== undefined) {
|
|
116
|
+
return (
|
|
117
|
+
'verify does not take --limit: it re-captures at the size its own manifest pinned, ' +
|
|
118
|
+
'because a re-capture at another corpus size is a comparison against another subject. ' +
|
|
119
|
+
'Accepting the flag and then using the pinned size reported green on a run that had ' +
|
|
120
|
+
'not honoured it'
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
return p;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* One real capture over the real tree.
|
|
128
|
+
*
|
|
129
|
+
* This is the one caller for which the process globals `partitionActive` reads
|
|
130
|
+
* — the host layer under the running user's home, and the install lockfile —
|
|
131
|
+
* ARE this run's own host, so it is the one caller that passes the predicate.
|
|
132
|
+
* Everywhere else the field stays `null` rather than recording some other
|
|
133
|
+
* machine's state under this tree's name.
|
|
134
|
+
*/
|
|
135
|
+
function capture(limit: number): CorpusManifest {
|
|
136
|
+
return captureManifest({
|
|
137
|
+
repoRoot: REPO_ROOT,
|
|
138
|
+
userHome: process.env['HOME'] ?? os.homedir(),
|
|
139
|
+
limit,
|
|
140
|
+
enumerationRule: ENUMERATION_RULE_ID,
|
|
141
|
+
partitionActive,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function main(argv?: string[]): number {
|
|
146
|
+
const args = argv ?? process.argv.slice(2);
|
|
147
|
+
if (args.length === 0 || args.includes('-h') || args.includes('--help')) {
|
|
148
|
+
process.stdout.write(USAGE);
|
|
149
|
+
return args.length === 0 ? EXIT_USAGE : EXIT_OK;
|
|
150
|
+
}
|
|
151
|
+
const parsed = parseArgs(args);
|
|
152
|
+
if (typeof parsed === 'string') {
|
|
153
|
+
process.stderr.write(`corpus_manifest: error: ${parsed}\n${USAGE}`);
|
|
154
|
+
return EXIT_USAGE;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (parsed.verb === 'capture') {
|
|
158
|
+
if (parsed.out === undefined) {
|
|
159
|
+
process.stderr.write(`corpus_manifest: error: capture requires --out FILE\n${USAGE}`);
|
|
160
|
+
return EXIT_USAGE;
|
|
161
|
+
}
|
|
162
|
+
let m: CorpusManifest;
|
|
163
|
+
try {
|
|
164
|
+
m = capture(parsed.limit ?? defaultLimit());
|
|
165
|
+
} catch (e) {
|
|
166
|
+
process.stderr.write(`corpus_manifest: capture refused — ${(e as Error).message}\n`);
|
|
167
|
+
return EXIT_ERROR;
|
|
168
|
+
}
|
|
169
|
+
fs.mkdirSync(path.dirname(path.resolve(parsed.out)), { recursive: true });
|
|
170
|
+
fs.writeFileSync(parsed.out, serialiseManifest(m), 'utf-8');
|
|
171
|
+
process.stdout.write(
|
|
172
|
+
`corpus_manifest: wrote ${parsed.out} · subject_digest=${m.subject_digest.slice(0, 16)} · ` +
|
|
173
|
+
`${String(m.included.length)} subject(s) · ${String(m.produced.length)} produced · ` +
|
|
174
|
+
`${String(m.user_scope.filter((t) => t.byte_identical).length)} byte-identical ` +
|
|
175
|
+
`twin(s), ${String(m.user_scope.filter((t) => t.causes_skip).length)} of them ` +
|
|
176
|
+
`causing a skip under ${String(m.generator_config['projection.scope_dedup'])}\n`,
|
|
177
|
+
);
|
|
178
|
+
if (m.tree_dirty) {
|
|
179
|
+
process.stdout.write(
|
|
180
|
+
'corpus_manifest: WARNING the working tree is dirty, so the recorded commit does not ' +
|
|
181
|
+
'describe the bytes that were hashed\n',
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
return EXIT_OK;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (parsed.verb === 'verify') {
|
|
188
|
+
if (parsed.manifest === undefined) {
|
|
189
|
+
process.stderr.write(`corpus_manifest: error: verify requires --manifest FILE\n${USAGE}`);
|
|
190
|
+
return EXIT_USAGE;
|
|
191
|
+
}
|
|
192
|
+
let expected: CorpusManifest;
|
|
193
|
+
let actual: CorpusManifest;
|
|
194
|
+
try {
|
|
195
|
+
expected = parseManifest(JSON.parse(fs.readFileSync(parsed.manifest, 'utf-8')));
|
|
196
|
+
actual = capture(expected.included.length);
|
|
197
|
+
} catch (e) {
|
|
198
|
+
process.stderr.write(`corpus_manifest: verify refused — ${(e as Error).message}\n`);
|
|
199
|
+
return EXIT_ERROR;
|
|
200
|
+
}
|
|
201
|
+
const diffs = diffManifests(expected, actual);
|
|
202
|
+
for (const d of diffs) {
|
|
203
|
+
process.stdout.write(`corpus_manifest: DIFF ${d.field}: expected ${d.expected}, got ${d.actual}\n`);
|
|
204
|
+
}
|
|
205
|
+
if (subjectsEquivalent(expected, actual)) {
|
|
206
|
+
process.stdout.write(
|
|
207
|
+
`corpus_manifest: SUBJECT EQUIVALENT · ${String(actual.included.length)} subject(s) · ` +
|
|
208
|
+
`digest=${actual.subject_digest.slice(0, 16)}` +
|
|
209
|
+
(diffs.length > 0 ? ` · ${String(diffs.length)} explanatory difference(s) above\n` : '\n'),
|
|
210
|
+
);
|
|
211
|
+
return EXIT_OK;
|
|
212
|
+
}
|
|
213
|
+
process.stdout.write(
|
|
214
|
+
'corpus_manifest: SUBJECT DIFFERS — a comparison captured against this manifest is not ' +
|
|
215
|
+
'comparable to one captured here\n',
|
|
216
|
+
);
|
|
217
|
+
return EXIT_SUBJECT_DIFFERS;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
process.stderr.write(`corpus_manifest: error: unknown verb ${JSON.stringify(parsed.verb)}\n${USAGE}`);
|
|
221
|
+
return EXIT_USAGE;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function _isCliEntry(): boolean {
|
|
225
|
+
try {
|
|
226
|
+
if (process.argv[1] === undefined) return false;
|
|
227
|
+
return fs.realpathSync(_HERE) === fs.realpathSync(path.resolve(process.argv[1]));
|
|
228
|
+
} catch {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (_isCliEntry()) {
|
|
234
|
+
process.exit(main());
|
|
235
|
+
}
|
|
@@ -62,6 +62,12 @@ import {
|
|
|
62
62
|
clone_candidate,
|
|
63
63
|
} from './bench_ab_clone.js';
|
|
64
64
|
import { main as integrity_main } from './bench_ab_integrity.js';
|
|
65
|
+
import {
|
|
66
|
+
runCascade,
|
|
67
|
+
CHEAPEST_STAGE,
|
|
68
|
+
type CascadeResult,
|
|
69
|
+
} from './_lib/evaluation_cascade.js';
|
|
70
|
+
import type { MetricVector } from './_lib/evaluation_vector.js';
|
|
65
71
|
import {
|
|
66
72
|
type CandidateRecord,
|
|
67
73
|
CandidateSchemaError,
|
|
@@ -76,6 +82,13 @@ import {
|
|
|
76
82
|
parseCandidateRecord,
|
|
77
83
|
readCandidateRecord,
|
|
78
84
|
} from './_lib/candidate_record.js';
|
|
85
|
+
import {
|
|
86
|
+
PROMOTION_EVIDENCE_FIELDS,
|
|
87
|
+
PromotionEvidenceError,
|
|
88
|
+
parsePromotionEvidence,
|
|
89
|
+
} from './_lib/promotion_evidence.js';
|
|
90
|
+
import { MERGE_AUTHORITY_ROADMAP, readMergeAuthorityStatus } from './_lib/promotion_capability.js';
|
|
91
|
+
import { assertNotSemanticNoOp, isSemanticNoOp, SemanticNoOpError } from './_lib/semantic_noop.js';
|
|
79
92
|
import {
|
|
80
93
|
RECIPES,
|
|
81
94
|
byteCompare,
|
|
@@ -84,6 +97,13 @@ import {
|
|
|
84
97
|
proposeCandidates,
|
|
85
98
|
serialiseCandidateRecord,
|
|
86
99
|
} from './_lib/candidate_proposer.js';
|
|
100
|
+
import {
|
|
101
|
+
type RunReport,
|
|
102
|
+
buildRunReport,
|
|
103
|
+
parseMetricVectorJson,
|
|
104
|
+
renderRunReport,
|
|
105
|
+
roiFigure,
|
|
106
|
+
} from './_lib/evolution_roi.js';
|
|
87
107
|
import {
|
|
88
108
|
BudgetExceededError,
|
|
89
109
|
type DisclosureRecord,
|
|
@@ -379,11 +399,11 @@ const USAGE = `usage: evolution_lab <verb> [options]
|
|
|
379
399
|
|
|
380
400
|
inspect [--record FILE]... [--records DIR] [--clones]
|
|
381
401
|
propose --observations FILE --out DIR [--force]
|
|
382
|
-
run --record FILE... [--refresh]
|
|
402
|
+
run --record FILE... [--refresh] [--vector FILE]...
|
|
383
403
|
[--trials-per-candidate N] [--estimated-spend-cents N]
|
|
384
404
|
compare [--verbose]
|
|
385
405
|
explain [--record FILE [--to STATE]] [--criteria]
|
|
386
|
-
promote --record FILE
|
|
406
|
+
promote --record FILE [--evidence FILE] (always refuses: blocker merge-authority)
|
|
387
407
|
clean [--yes]
|
|
388
408
|
|
|
389
409
|
No verb starts a resident process, a timer, or a watcher.
|
|
@@ -698,7 +718,7 @@ function verbRun(argv: readonly string[]): number {
|
|
|
698
718
|
const flags = parseFlags(
|
|
699
719
|
argv,
|
|
700
720
|
['refresh'],
|
|
701
|
-
['record', 'records', 'trials-per-candidate', 'estimated-spend-cents'],
|
|
721
|
+
['record', 'records', 'trials-per-candidate', 'estimated-spend-cents', 'vector'],
|
|
702
722
|
);
|
|
703
723
|
const files: string[] = [...(flags.values.get('record') ?? [])];
|
|
704
724
|
const dir = one(flags, 'records');
|
|
@@ -734,7 +754,22 @@ function verbRun(argv: readonly string[]): number {
|
|
|
734
754
|
}
|
|
735
755
|
throw e;
|
|
736
756
|
}
|
|
757
|
+
// Evaluation evidence is parsed BEFORE the first clone, for the same reason
|
|
758
|
+
// the budget guard runs before it: a malformed vector discovered after the
|
|
759
|
+
// work is a failed run that already spent, and `parseMetricVectorJson`
|
|
760
|
+
// inherits `buildVector`'s refusal of a vector missing its artifact-count
|
|
761
|
+
// row, so this is also where that refusal lands.
|
|
762
|
+
const vectors: MetricVector[] = [];
|
|
763
|
+
for (const vf of flags.values.get('vector') ?? []) {
|
|
764
|
+
try {
|
|
765
|
+
vectors.push(parseMetricVectorJson(fs.readFileSync(vf, 'utf-8'), vf));
|
|
766
|
+
} catch (e) {
|
|
767
|
+
return fail(`vector ${vf} rejected — ${(e as Error).message}`);
|
|
768
|
+
}
|
|
769
|
+
}
|
|
737
770
|
const seen = new Set<string>();
|
|
771
|
+
const ids: string[] = [];
|
|
772
|
+
const results: CascadeResult[] = [];
|
|
738
773
|
for (const f of files.sort(byteCompare)) {
|
|
739
774
|
let record: CandidateRecord;
|
|
740
775
|
try {
|
|
@@ -754,6 +789,95 @@ function verbRun(argv: readonly string[]): number {
|
|
|
754
789
|
}
|
|
755
790
|
return fail(`candidate ${record.id} failed — ${(e as Error).message}`);
|
|
756
791
|
}
|
|
792
|
+
|
|
793
|
+
// EVALUATE. Step 4.1's deterministic prefix, wired here because a
|
|
794
|
+
// library nothing calls has no coverage — the defect AC-3 and AC-5
|
|
795
|
+
// were both open on. The record is re-read from disk rather than
|
|
796
|
+
// reusing `record`, so stage 1 is a real schema gate at this call
|
|
797
|
+
// site and not a formality over an already-parsed object.
|
|
798
|
+
let raw: unknown;
|
|
799
|
+
try {
|
|
800
|
+
raw = JSON.parse(fs.readFileSync(f, 'utf-8'));
|
|
801
|
+
} catch (e) {
|
|
802
|
+
return fail(`${f} unreadable at evaluation — ${(e as Error).message}`);
|
|
803
|
+
}
|
|
804
|
+
const result = runCascade({
|
|
805
|
+
raw,
|
|
806
|
+
plan: {
|
|
807
|
+
candidates: files.length,
|
|
808
|
+
trialsPerCandidate: intFlag(flags, 'trials-per-candidate', 1),
|
|
809
|
+
estimatedSpendCents: intFlag(flags, 'estimated-spend-cents', 0),
|
|
810
|
+
},
|
|
811
|
+
budget: loadRunBudget(),
|
|
812
|
+
peers: ids,
|
|
813
|
+
// ONE evidence input, two consumers. `--vector` is the only
|
|
814
|
+
// measurement flag: step 5.6's run report and step 4.1's cascade
|
|
815
|
+
// read the same parsed vectors rather than each taking a file of
|
|
816
|
+
// its own, so a run cannot report an ROI over one set of numbers
|
|
817
|
+
// while the verdict was decided on another.
|
|
818
|
+
vector: vectors.find((v) => v.candidate_id === record.id),
|
|
819
|
+
});
|
|
820
|
+
ids.push(record.id);
|
|
821
|
+
results.push(result);
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
for (const r of results) {
|
|
825
|
+
if (r.outcome === 'abort') {
|
|
826
|
+
process.stdout.write(
|
|
827
|
+
`evolution_lab:cascade · ${r.candidate_id ?? '<unparsed>'} · aborted at ` +
|
|
828
|
+
`${r.failed_stage} · family=${r.family} · model_calls=${r.model_calls} · ${r.detail}\n`,
|
|
829
|
+
);
|
|
830
|
+
} else if (r.outcome === 'incomplete') {
|
|
831
|
+
process.stdout.write(
|
|
832
|
+
`evolution_lab:cascade · ${r.candidate_id} · passed ${r.stages_run.length} stage(s) · ` +
|
|
833
|
+
`model_calls=${r.model_calls} · ${r.not_reached} NOT REACHED · ${r.why}\n`,
|
|
834
|
+
);
|
|
835
|
+
} else {
|
|
836
|
+
process.stdout.write(
|
|
837
|
+
`evolution_lab:cascade · ${r.candidate_id} · passed ${r.stages_run.length} stage(s) · ` +
|
|
838
|
+
`model_calls=${r.model_calls} · verdict=${r.verdict.promote ? 'promote' : 'refuse'} · ` +
|
|
839
|
+
`${r.verdict.reason}\n`,
|
|
840
|
+
);
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
// A cascade abort is a run outcome, not a crash: the run did its job by
|
|
845
|
+
// refusing. The cheapest stage is named so a reader can see that a stage-1
|
|
846
|
+
// abort cost nothing.
|
|
847
|
+
const aborted = results.filter((r) => r.outcome === 'abort');
|
|
848
|
+
if (aborted.length > 0) {
|
|
849
|
+
const atCheapest = aborted.filter(
|
|
850
|
+
(r) => r.outcome === 'abort' && r.failed_stage === CHEAPEST_STAGE,
|
|
851
|
+
).length;
|
|
852
|
+
process.stdout.write(
|
|
853
|
+
`evolution_lab:cascade · ${aborted.length} of ${results.length} aborted ` +
|
|
854
|
+
`(${atCheapest} at the cheapest stage, ${CHEAPEST_STAGE}, costing no model call)\n`,
|
|
855
|
+
);
|
|
856
|
+
return EXIT_REFUSED;
|
|
857
|
+
}
|
|
858
|
+
// STEP 5.6 — the run report, on the ONE path a run completes on.
|
|
859
|
+
//
|
|
860
|
+
// Placed after the clone loop and before the only success return, so there
|
|
861
|
+
// is no completed run without a report. Every other exit from this verb is
|
|
862
|
+
// an abort (budget) or a failure (unreadable record), and neither is a run
|
|
863
|
+
// whose ROI could be reported: nothing was cloned and nothing was spent.
|
|
864
|
+
let report: RunReport;
|
|
865
|
+
try {
|
|
866
|
+
report = buildRunReport({
|
|
867
|
+
// Deterministic and identifying: the candidate ids, in the byte
|
|
868
|
+
// order the run walked them. Two runs over the same record set
|
|
869
|
+
// produce the same id, and a run over a different set cannot
|
|
870
|
+
// borrow another run's report line.
|
|
871
|
+
run_id: `run:${[...seen].sort(byteCompare).join('+')}`,
|
|
872
|
+
candidates: files.length,
|
|
873
|
+
trials_per_candidate: intFlag(flags, 'trials-per-candidate', 1),
|
|
874
|
+
roi: roiFigure(vectors, intFlag(flags, 'estimated-spend-cents', 0)),
|
|
875
|
+
});
|
|
876
|
+
} catch (e) {
|
|
877
|
+
return fail(`run report rejected — ${(e as Error).message}`);
|
|
878
|
+
}
|
|
879
|
+
for (const line of renderRunReport(report)) {
|
|
880
|
+
process.stdout.write(`${line}\n`);
|
|
757
881
|
}
|
|
758
882
|
return EXIT_OK;
|
|
759
883
|
}
|
|
@@ -854,9 +978,15 @@ function verbExplain(argv: readonly string[]): number {
|
|
|
854
978
|
* There is no flag, no environment variable and no argument that turns this
|
|
855
979
|
* into a promotion. `--approver` is deliberately NOT a flag: adding one is what
|
|
856
980
|
* would let an unattended run name a human who never approved.
|
|
981
|
+
*
|
|
982
|
+
* `--evidence FILE` IS a flag, and it changes nothing about the refusal. It is
|
|
983
|
+
* how steps 7.1, 7.3, 7.4 and 7.5 are exercised against a refused promotion: the
|
|
984
|
+
* package is validated FIRST and its finding names the missing field, so an
|
|
985
|
+
* operator assembling one can see which field is wrong instead of only being
|
|
986
|
+
* told the blocker is open. Both paths still return {@link EXIT_REFUSED}.
|
|
857
987
|
*/
|
|
858
988
|
function verbPromote(argv: readonly string[]): number {
|
|
859
|
-
const flags = parseFlags(argv, [], ['record']);
|
|
989
|
+
const flags = parseFlags(argv, [], ['record', 'evidence']);
|
|
860
990
|
const file = one(flags, 'record');
|
|
861
991
|
if (file === undefined) {
|
|
862
992
|
return usageError('promote requires --record FILE');
|
|
@@ -867,20 +997,63 @@ function verbPromote(argv: readonly string[]): number {
|
|
|
867
997
|
} catch (e) {
|
|
868
998
|
return fail(`${file} rejected — ${(e as Error).message}`);
|
|
869
999
|
}
|
|
1000
|
+
|
|
1001
|
+
// 7.1 / 7.3 / 7.4 / 7.5 — the evidence package, checked BEFORE the governance
|
|
1002
|
+
// refusal so its finding names the missing field rather than being swallowed
|
|
1003
|
+
// by a blocker message the operator cannot act on.
|
|
1004
|
+
const evidenceFile = one(flags, 'evidence');
|
|
1005
|
+
if (evidenceFile === undefined) {
|
|
1006
|
+
process.stderr.write(
|
|
1007
|
+
`evolution_lab: promote REFUSED for ${record.id}\n` +
|
|
1008
|
+
' evidence package: absent. A promotion carries ONE package with all ' +
|
|
1009
|
+
`${String(PROMOTION_EVIDENCE_FIELDS.length)} fields ` +
|
|
1010
|
+
`(${PROMOTION_EVIDENCE_FIELDS.join(', ')}); pass --evidence FILE.\n`,
|
|
1011
|
+
);
|
|
1012
|
+
} else {
|
|
1013
|
+
try {
|
|
1014
|
+
const evidence = parsePromotionEvidence(JSON.parse(fs.readFileSync(evidenceFile, 'utf-8')));
|
|
1015
|
+
assertNotSemanticNoOp(
|
|
1016
|
+
evidence.candidateId,
|
|
1017
|
+
isSemanticNoOp(
|
|
1018
|
+
evidence.materialImprovement.baselineText,
|
|
1019
|
+
evidence.materialImprovement.candidateText,
|
|
1020
|
+
evidence.materialImprovement.deltaPercent,
|
|
1021
|
+
),
|
|
1022
|
+
);
|
|
1023
|
+
} catch (e) {
|
|
1024
|
+
if (e instanceof PromotionEvidenceError || e instanceof SemanticNoOpError) {
|
|
1025
|
+
process.stderr.write(
|
|
1026
|
+
`evolution_lab: promote REFUSED for ${record.id}\n evidence package: ${e.message}\n`,
|
|
1027
|
+
);
|
|
1028
|
+
} else {
|
|
1029
|
+
return fail(`${evidenceFile} unreadable — ${(e as Error).message}`);
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
|
|
870
1034
|
let gate = 'the lifecycle gate did not refuse, which is itself a defect';
|
|
871
1035
|
try {
|
|
872
1036
|
assertTransition(record.lifecycle, 'promoted');
|
|
873
1037
|
} catch (e) {
|
|
874
1038
|
gate = (e as Error).message;
|
|
875
1039
|
}
|
|
1040
|
+
// READ the status, never assert it. This line said `is OPEN` as a literal,
|
|
1041
|
+
// and on 2026-09-01 the blocker closed as `refused` — at which point the
|
|
1042
|
+
// refusal was still correct and its stated reason was not. Reading keeps the
|
|
1043
|
+
// two from diverging again, and every value the reader can return is a
|
|
1044
|
+
// refusing one, so no branch here can print a grant.
|
|
1045
|
+
const blockerStatus = readMergeAuthorityStatus();
|
|
876
1046
|
process.stderr.write(
|
|
877
1047
|
`evolution_lab: promote REFUSED for ${record.id}\n` +
|
|
878
1048
|
` lifecycle gate: ${gate}\n` +
|
|
879
|
-
|
|
1049
|
+
` blocker: merge-authority reads ${blockerStatus.toUpperCase()} on ` +
|
|
1050
|
+
`${path.basename(MERGE_AUTHORITY_ROADMAP, '.md')}.\n` +
|
|
880
1051
|
' Phases 1-6 are legal because they promote nothing (AI council 2026-08-29,\n' +
|
|
881
|
-
' anthropic + openai, 2/2). Phase 7
|
|
882
|
-
'
|
|
883
|
-
'
|
|
1052
|
+
' anthropic + openai, 2/2). Phase 7 was gated on this blocker; on 2026-09-01\n' +
|
|
1053
|
+
' the AI council settled ADR-239 Decision 3 in the REFUSING direction, scoped\n' +
|
|
1054
|
+
' to PREAUTHORIZED authority, and the blocker closed as `refused`. Only\n' +
|
|
1055
|
+
' `Status: resolved` AND `Disposition: granted` mint the capability, so a\n' +
|
|
1056
|
+
' refusal keeps this verb shut exactly as an open blocker did.\n' +
|
|
884
1057
|
' Promotion into canonical agent-config remains a named human act performed\n' +
|
|
885
1058
|
' outside this tool. This verb will not perform it.\n',
|
|
886
1059
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"fingerprint":"81bdd86d:80948","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-speaking-inbox-dir":{"script":"src/scripts/hooks/block_speaking_inbox_dir.ts","args":[],"fail_closed":false,"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"]},"design-pass":{"script":"src/scripts/hooks/design_pass_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"design-pass-stop":{"script":"src/scripts/hooks/design_pass_hook.ts","args":["--slot","stop"],"fail_closed":false,"severity":"advisory"},"ui-route-nudge":{"script":"src/scripts/hooks/ui_route_nudge_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"suggestion-capture":{"script":"src/scripts/hooks/suggestion_capture_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"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"},"telemetry-flush":{"script":"src/scripts/hooks/telemetry_flush_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},"rule-inject":{"script":"src/scripts/hooks/rule_inject_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"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"]},"source-first-gate":{"script":"src/scripts/hooks/source_first_gate_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"journal-record":{"script":"src/scripts/hooks/journal_record_hook.ts","args":[],"fail_closed":false,"severity":"advisory"}},"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","telemetry-flush"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress","design-pass-stop"],"pre_tool_use":["block-no-verify","block-unauthorized-git","evidence-independence","block-kernel-rule-writes","block-config-weakening","block-speaking-inbox-dir","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","design-pass"]},"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","journal-record"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress","telemetry-flush","journal-record"],"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","design-pass-stop","suggestion-capture","journal-record","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","rule-inject","suggestion-capture","journal-record"],"pre_tool_use":["block-no-verify","block-unauthorized-git","evidence-independence","block-kernel-rule-writes","block-config-weakening","block-speaking-inbox-dir","rtk-wrap","design-slop","ui-route-nudge","code-graph-nudge","ship-diff-volume","reread-guard","spawn-guard-shadow","source-first-gate","rule-inject"],"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","design-pass","journal-record"],"pre_compact":["language-mirror","hot-context","rule-inject","journal-record"],"subagent_start":["subagent-ledger","journal-record"],"subagent_stop":["subagent-ledger","journal-record"]},"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","telemetry-flush"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress","design-pass-stop"],"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","block-speaking-inbox-dir","rtk-wrap","design-slop","ui-route-nudge","code-graph-nudge","ship-diff-volume","reread-guard","spawn-guard-shadow","source-first-gate"],"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","design-pass"],"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","telemetry-flush"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress","design-pass-stop"],"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","design-pass"]},"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","telemetry-flush"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress","design-pass-stop"],"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","design-pass"]},"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","design-pass-stop"],"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","telemetry-flush"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress","design-pass-stop"],"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","design-pass"]},"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"}}}}
|
|
1
|
+
{"fingerprint":"877cc83a:82357","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-speaking-inbox-dir":{"script":"src/scripts/hooks/block_speaking_inbox_dir.ts","args":[],"fail_closed":false,"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"]},"design-pass":{"script":"src/scripts/hooks/design_pass_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"design-pass-stop":{"script":"src/scripts/hooks/design_pass_hook.ts","args":["--slot","stop"],"fail_closed":false,"severity":"advisory"},"ui-route-nudge":{"script":"src/scripts/hooks/ui_route_nudge_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"suggestion-capture":{"script":"src/scripts/hooks/suggestion_capture_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"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"},"telemetry-flush":{"script":"src/scripts/hooks/telemetry_flush_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},"rule-inject":{"script":"src/scripts/hooks/rule_inject_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"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"},"comment-discipline":{"script":"src/scripts/hooks/comment_discipline_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Write","Edit"],"needs_payload_bodies":["input"]},"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"]},"source-first-gate":{"script":"src/scripts/hooks/source_first_gate_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"journal-record":{"script":"src/scripts/hooks/journal_record_hook.ts","args":[],"fail_closed":false,"severity":"advisory"}},"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","telemetry-flush"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress","design-pass-stop"],"pre_tool_use":["block-no-verify","block-unauthorized-git","evidence-independence","block-kernel-rule-writes","block-config-weakening","block-speaking-inbox-dir","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","comment-discipline","design-pass"]},"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","journal-record"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress","telemetry-flush","journal-record"],"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","design-pass-stop","suggestion-capture","journal-record","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","rule-inject","suggestion-capture","journal-record"],"pre_tool_use":["block-no-verify","block-unauthorized-git","evidence-independence","block-kernel-rule-writes","block-config-weakening","block-speaking-inbox-dir","rtk-wrap","design-slop","ui-route-nudge","code-graph-nudge","ship-diff-volume","reread-guard","spawn-guard-shadow","source-first-gate","rule-inject"],"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","comment-discipline","language-mirror","design-pass","journal-record"],"pre_compact":["language-mirror","hot-context","rule-inject","journal-record"],"subagent_start":["subagent-ledger","journal-record"],"subagent_stop":["subagent-ledger","journal-record"]},"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","telemetry-flush"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress","design-pass-stop"],"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","block-speaking-inbox-dir","rtk-wrap","design-slop","ui-route-nudge","code-graph-nudge","ship-diff-volume","reread-guard","spawn-guard-shadow","source-first-gate"],"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","comment-discipline","design-pass"],"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","telemetry-flush"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress","design-pass-stop"],"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","comment-discipline","design-pass"]},"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","telemetry-flush"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress","design-pass-stop"],"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","comment-discipline","design-pass"]},"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","design-pass-stop"],"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","telemetry-flush"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress","design-pass-stop"],"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","comment-discipline","design-pass"]},"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"}}}}
|