@event4u/agent-config 17.0.0 → 17.2.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 +157 -468
- package/README.md +4 -3
- package/dist/agent-src/commands/project/analyze.md +9 -6
- package/dist/agent-src/commands/project/map.md +58 -0
- package/dist/agent-src/commands/project.md +5 -3
- package/dist/agent-src/contexts/execution/host-capability-manifest.md +5 -3
- package/dist/agent-src/skills/code-intelligence/SKILL.md +6 -0
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +5 -1
- package/dist/cli/registry.js +1 -1
- package/dist/cli-delegate/{chunk-IROAQ77A.js → chunk-3PK3VZHB.js} +107 -9
- package/dist/cli-delegate/{chunk-2SFOOFJJ.js → chunk-BZJ4Y3CI.js} +1 -1
- package/dist/cli-delegate/{chunk-CAL76ADI.js → chunk-CMZEKSNN.js} +52 -10
- package/dist/cli-delegate/{chunk-ESUNQ5XR.js → chunk-E3CFULNX.js} +22 -4
- package/dist/cli-delegate/{chunk-GOMILC3O.js → chunk-QBHEI5N4.js} +4 -3
- package/dist/cli-delegate/{chunk-SIOMDAKL.js → chunk-VYZGJLCA.js} +29 -39
- package/dist/cli-delegate/chunk-W5JXMF2T.js +77 -0
- package/dist/cli-delegate/{chunk-4SHNERBL.js → chunk-XIAPY44N.js} +1 -1
- package/dist/cli-delegate/{chunk-JHMMWNJ2.js → chunk-YHAPONWV.js} +1 -1
- package/dist/cli-delegate/cmd_conformance.js +32 -47
- package/dist/cli-delegate/cmd_doctor.js +4 -4
- package/dist/cli-delegate/cmd_doctor_neighbours.js +2 -2
- package/dist/cli-delegate/cmd_explain.js +1 -1
- package/dist/cli-delegate/cmd_export.js +6 -6
- package/dist/cli-delegate/cmd_fleet.js +3 -3
- package/dist/cli-delegate/cmd_preflight.js +3 -3
- package/dist/cli-delegate/cmd_prune.js +6 -6
- package/dist/cli-delegate/cmd_settings_migrate.js +6 -6
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +6 -6
- package/dist/cli-delegate/cmd_uninstall.js +6 -6
- package/dist/cli-delegate/cmd_update.js +9 -13
- package/dist/cli-delegate/cmd_validate.js +6 -6
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +41 -15
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +3 -3
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +6 -5
- package/dist/discovery/trust-report.md +2 -2
- package/dist/discovery/workspaces.json +5 -4
- package/dist/hooks/dispatch.js +163 -148
- package/dist/hooks/dispatch.sha256 +1 -1
- package/dist/hooks/instructions_observer.chunk.cjs +301 -0
- package/dist/hooks/instructions_observer.chunk.cjs.sha256 +1 -0
- package/dist/install/claudeRuleRewrite.js +10 -3
- package/dist/install/conflict.js +24 -2
- package/dist/install/conflictTracker.js +14 -3
- package/dist/install/install.mjs +222 -117
- package/dist/install/installThinLayer.js +1 -0
- package/dist/install/loggedWrites.js +142 -0
- package/dist/install/paths.js +12 -2
- package/dist/install/preserve.js +25 -4
- package/dist/install/txlog.js +10 -6
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +33595 -22916
- package/dist/scripts/_lib/egress_rules.js +4 -1
- package/dist/scripts/_lib/identifier_redaction.js +35 -2
- package/dist/scripts/ai_council/seat_policy.js +7 -1
- package/dist/server/schemas/settings.js +1 -1
- package/package.json +4 -1
- package/src/config/ci-local-parity.yml +1 -1
- package/src/config/continuity-surface.json +7 -0
- package/src/config/evaluator-budgets.json +4 -4
- package/src/config/gate-coverage.yml +27 -7
- package/src/config/gate-violation-baselines.json +9 -3
- package/src/config/gitignore-block.txt +6 -0
- package/src/config/hook-bundle-budget.json +19 -4
- package/src/config/hook-token-budget.json +1 -1
- package/src/config/packed-binary-manifest.json +27 -0
- package/src/config/production-entries.json +18 -0
- package/src/config/release-gate-locality.yml +0 -7
- package/src/config/skill-body-budget.json +7 -1
- package/src/install/claudeRuleRewrite.ts +10 -1
- package/src/install/conflict.ts +24 -1
- package/src/install/conflictTracker.ts +18 -2
- package/src/install/installThinLayer.ts +6 -0
- package/src/install/loggedWrites.ts +148 -0
- package/src/install/paths.ts +11 -2
- package/src/install/preserve.ts +40 -4
- package/src/install/txlog.ts +10 -6
- package/src/scripts/_cli/cmd_conformance.ts +3 -2
- package/src/scripts/_cli/cmd_update.ts +15 -17
- package/src/scripts/_lib/bench_ab_complexity.ts +14 -2
- package/src/scripts/_lib/collector_record.ts +1 -0
- package/src/scripts/_lib/council_settings_block.ts +9 -2
- package/src/scripts/_lib/egress_rules.ts +4 -1
- package/src/scripts/_lib/host_capability.ts +10 -5
- package/src/scripts/_lib/identifier_redaction.ts +38 -2
- package/src/scripts/_lib/price_freshness.ts +112 -0
- package/src/scripts/_lib/production_reach.ts +194 -0
- package/src/scripts/_lib/quota_parked.ts +17 -28
- package/src/scripts/_lib/release_findings_ingest.ts +13 -335
- package/src/scripts/_lib/runtime_journal.ts +7 -7
- package/src/scripts/_lib/tier_downshift_verdict.ts +81 -35
- package/src/scripts/ai_council/chairman.ts +5 -2
- package/src/scripts/ai_council/clients.ts +4 -3
- package/src/scripts/ai_council/free_hand_shadow.ts +24 -12
- package/src/scripts/ai_council/free_route_catalog.ts +142 -5
- package/src/scripts/ai_council/free_route_client.ts +4 -0
- package/src/scripts/ai_council/hand_payload.ts +115 -7
- package/src/scripts/ai_council/orchestrator.ts +7 -10
- package/src/scripts/ai_council/route_chooser.ts +1 -1
- package/src/scripts/ai_council/route_member.ts +66 -4
- package/src/scripts/ai_council/seat_policy.ts +8 -1
- package/src/scripts/ai_council/self_hosted_probe.ts +327 -0
- package/src/scripts/ai_council/status_surface.ts +2 -0
- package/src/scripts/ask_transport.ts +137 -15
- package/src/scripts/check_finding_dispositions.ts +25 -71
- package/src/scripts/check_release_pr_shape.ts +3 -3
- package/src/scripts/check_step_production_reach.ts +257 -0
- package/src/scripts/code_graph/build.ts +210 -10
- package/src/scripts/code_graph/cli.ts +168 -46
- package/src/scripts/code_graph/detect.ts +5 -4
- package/src/scripts/code_graph/docs_layer.ts +57 -0
- package/src/scripts/code_graph/extract.ts +58 -13
- package/src/scripts/code_graph/extract_more.ts +314 -0
- package/src/scripts/code_graph/laravel_overlay.ts +454 -0
- package/src/scripts/code_graph/map.ts +846 -0
- package/src/scripts/code_graph/map_model.ts +977 -0
- package/src/scripts/code_graph/map_verify.ts +140 -0
- package/src/scripts/code_graph/map_viewer/viewer.css +278 -0
- package/src/scripts/code_graph/map_viewer/viewer.js +756 -0
- package/src/scripts/code_graph/scip_reader.ts +201 -0
- package/src/scripts/code_graph/sqlite_store.ts +8 -1
- package/src/scripts/code_graph/types.ts +81 -15
- package/src/scripts/code_graph/validate.ts +16 -26
- package/src/scripts/code_graph/verbs.ts +7 -0
- package/src/scripts/council_cli.ts +10 -8
- package/src/scripts/hook_chunks.mjs +7 -0
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +23 -0
- package/src/scripts/hooks/dispatch_hook.ts +4 -4
- package/src/scripts/hooks/instructions_observer_hook.ts +25 -6
- package/src/scripts/hooks/lazy_concern.ts +4 -0
- package/src/scripts/hooks/payload_stub.ts +27 -0
- package/src/scripts/hooks/spawn_guard_shadow_hook.ts +29 -70
- package/src/scripts/hooks/subagent_ledger_hook.ts +80 -0
- package/src/scripts/install-hooks.sh +5 -0
- package/src/scripts/install.ts +2 -2
- package/src/scripts/lint_agents_layout.ts +2 -0
- package/src/scripts/lint_decision_classes.ts +34 -0
- package/src/scripts/lint_hook_manifest.ts +25 -0
- package/src/scripts/lint_roadmap_blockers.ts +52 -3
- package/src/scripts/mcp_server/consumer_tool_catalog.json +53 -6
- package/src/scripts/mcp_server/graph_tools.ts +73 -1
- package/src/scripts/mcp_server/tools.ts +19 -36
- package/src/scripts/release.ts +5 -9
- package/src/scripts/release_drill.ts +11 -165
- package/src/scripts/release_publication.ts +0 -9
- package/src/scripts/report_production_reach.ts +35 -0
- package/src/scripts/worker_reuse_shadow_report.ts +399 -1
- package/src/server/schemas/settings.ts +1 -1
- package/src/vendor/grammars/README.md +10 -5
- package/src/vendor/grammars/tree-sitter-go.wasm +0 -0
- package/src/vendor/grammars/tree-sitter-java.wasm +0 -0
- package/src/vendor/grammars/tree-sitter-python.wasm +0 -0
- package/dist/cli-delegate/chunk-A4QJ6ENT.js +0 -50
- /package/dist/cli-delegate/{chunk-E6XNBVE4.js → chunk-KR5ZIFPO.js} +0 -0
|
@@ -34,6 +34,7 @@ import process from 'node:process';
|
|
|
34
34
|
import { fileURLToPath } from 'node:url';
|
|
35
35
|
|
|
36
36
|
import { assertScanned, DeadScopeError } from './_lib/scan_scope.js';
|
|
37
|
+
import { OWNER_LOCKED_CLASSES } from './ai_council/ownership_classes.js';
|
|
37
38
|
|
|
38
39
|
const _HERE = fileURLToPath(import.meta.url);
|
|
39
40
|
const _PROG = 'lint_decision_classes';
|
|
@@ -65,6 +66,19 @@ export const RESOLVER_FORMS: readonly string[] = [
|
|
|
65
66
|
'owner',
|
|
66
67
|
];
|
|
67
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Locked-class rows resolved by the council before the owner lock reached this
|
|
71
|
+
* lint (road-to-a-tick-the-shipped-path-earns 2.2, decision A6). Listed rather
|
|
72
|
+
* than rewritten, so a fifth cannot land; each waits on the owner's ruling on
|
|
73
|
+
* blocker `delegated-owner-defaults`.
|
|
74
|
+
*/
|
|
75
|
+
export const LOCKED_RESOLVER_BASELINE: ReadonlySet<string> = new Set([
|
|
76
|
+
'agents/roadmaps/road-to-an-update-that-installs-itself-only-when-it-is-safe.md#D7',
|
|
77
|
+
'agents/roadmaps/road-to-an-update-that-installs-itself-only-when-it-is-safe.md#D8',
|
|
78
|
+
'agents/roadmaps/road-to-authority-routing-mechanism.md#D11',
|
|
79
|
+
'agents/roadmaps/road-to-placeholders-on-the-wire.md#D7',
|
|
80
|
+
]);
|
|
81
|
+
|
|
68
82
|
/**
|
|
69
83
|
* Unresolved-decision markers. Deliberately narrow: every pattern is a phrase
|
|
70
84
|
* an author writes when they KNOW a decision is open, never a word that shows
|
|
@@ -206,6 +220,21 @@ export function checkOwnershipColumn(rel: string, lines: readonly string[]): Vio
|
|
|
206
220
|
`team:<record>, owner`,
|
|
207
221
|
});
|
|
208
222
|
}
|
|
223
|
+
const id = (cells[0] ?? '').replace(/`/g, '').trim();
|
|
224
|
+
if (
|
|
225
|
+
OWNER_LOCKED_CLASSES.has(owner) &&
|
|
226
|
+
resolved !== 'owner' &&
|
|
227
|
+
!LOCKED_RESOLVER_BASELINE.has(`${rel}#${id}`)
|
|
228
|
+
) {
|
|
229
|
+
out.push({
|
|
230
|
+
file: rel,
|
|
231
|
+
line: i + 1,
|
|
232
|
+
reason:
|
|
233
|
+
`ownership=\`${owner}\` is locked to the owner (ownership_classes.ts), ` +
|
|
234
|
+
`so resolved by=\`${resolved}\` cannot close it. Record a council answer ` +
|
|
235
|
+
`as \`owner\` with a decision cell starting "proposed".`,
|
|
236
|
+
});
|
|
237
|
+
}
|
|
209
238
|
}
|
|
210
239
|
}
|
|
211
240
|
return out;
|
|
@@ -438,6 +467,11 @@ function _selfTest(): number {
|
|
|
438
467
|
if (checkFile('m2.md', resolved).length !== 0) {
|
|
439
468
|
failures.push('a marker naming its own closure row red');
|
|
440
469
|
}
|
|
470
|
+
const locked = good.replace('critical-technical | council:rec-1', 'product-owned | council:rec-1');
|
|
471
|
+
if (checkFile('l.md', locked).length === 0) failures.push('a locked class closed by the council did not red');
|
|
472
|
+
if (checkFile('l2.md', locked.replace('council:rec-1', 'owner')).length !== 0) {
|
|
473
|
+
failures.push('a locked class closed by the owner red');
|
|
474
|
+
}
|
|
441
475
|
const dangling = 'Pick the codec: TBD — closed as D9.\n';
|
|
442
476
|
if (checkFile('m3.md', dangling).length === 0) {
|
|
443
477
|
failures.push('a marker naming a row that does not exist did not red');
|
|
@@ -93,6 +93,7 @@ const EVENT_VOCABULARY: ReadonlySet<string> = new Set([
|
|
|
93
93
|
"agent_error",
|
|
94
94
|
"subagent_start",
|
|
95
95
|
"subagent_stop",
|
|
96
|
+
"instructions_loaded",
|
|
96
97
|
]);
|
|
97
98
|
|
|
98
99
|
// Known platform identifiers.
|
|
@@ -276,6 +277,30 @@ function _check_concerns(manifest: YamlObject, errors: string[]): Set<string> {
|
|
|
276
277
|
}
|
|
277
278
|
}
|
|
278
279
|
}
|
|
280
|
+
// `payload_fields:` — field-level projection of the declared bodies. A
|
|
281
|
+
// non-list is ignored at run time, which would silently hand the concern
|
|
282
|
+
// whole bodies; a projection on a guard is ignored by design, so declaring
|
|
283
|
+
// one there states a narrowing that never happens.
|
|
284
|
+
if ("payload_fields" in spec) {
|
|
285
|
+
const raw = spec["payload_fields"];
|
|
286
|
+
if (!Array.isArray(raw) || raw.length === 0 || raw.some((f) => typeof f !== "string" || f === "")) {
|
|
287
|
+
errors.push(
|
|
288
|
+
`concerns.${name}: 'payload_fields' must be a non-empty list of key names`,
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
if (!("needs_payload_bodies" in spec)) {
|
|
292
|
+
errors.push(
|
|
293
|
+
`concerns.${name}: 'payload_fields' without 'needs_payload_bodies' ` +
|
|
294
|
+
`narrows bodies the concern never receives — declare the body classes`,
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
if (spec["fail_closed"] === true || spec["severity"] === "blocking") {
|
|
298
|
+
errors.push(
|
|
299
|
+
`concerns.${name}: 'payload_fields' has no effect on a blocking or ` +
|
|
300
|
+
`fail-closed concern, which always receives whole bodies — remove it`,
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
279
304
|
// `re_arm:` — the named boundary at which a rebuilt prompt prefix is
|
|
280
305
|
// expected and paid for once (`road-to-runtime-context-floors` step 1.2).
|
|
281
306
|
// `check_prefix_stable_mutation` reads this key to decide whether a
|
|
@@ -281,6 +281,27 @@ const TECHNICAL_CLASSES: ReadonlySet<string> = new Set([
|
|
|
281
281
|
* parses as `1`: the taxonomy name is documentation for the reader and must
|
|
282
282
|
* not have to be spelled identically in every entry to stay valid.
|
|
283
283
|
*/
|
|
284
|
+
/** A `## Decisions` row resolved by `owner`, dated, that names blocker `id`. */
|
|
285
|
+
function _ownerDecisionNames(text: string, id: string): boolean {
|
|
286
|
+
const lines = text.split('\n');
|
|
287
|
+
const start = lines.findIndex((l) => /^##\s+Decisions\s*$/.test(l));
|
|
288
|
+
if (start < 0) return false;
|
|
289
|
+
let resolvedCol = -1;
|
|
290
|
+
for (let i = start + 1; i < lines.length && !/^##\s/.test(lines[i] as string); i += 1) {
|
|
291
|
+
const line = (lines[i] as string).trim();
|
|
292
|
+
if (!line.startsWith('|')) continue;
|
|
293
|
+
const cells = line.replace(/^\|/, '').replace(/\|$/, '').split('|').map((c) => c.trim());
|
|
294
|
+
if (resolvedCol < 0) {
|
|
295
|
+
resolvedCol = cells.findIndex((c) => /^resolved[ _]by$/i.test(c));
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
if (cells[resolvedCol]?.replace(/`/g, '') !== 'owner') continue;
|
|
299
|
+
if (!line.includes(id) || !/\b\d{4}-\d{2}-\d{2}\b/.test(line)) continue;
|
|
300
|
+
return true;
|
|
301
|
+
}
|
|
302
|
+
return false;
|
|
303
|
+
}
|
|
304
|
+
|
|
284
305
|
function _blockerClass(body: string): string {
|
|
285
306
|
const m = CLASS_FIELD_RE.exec(body);
|
|
286
307
|
if (!m) {
|
|
@@ -341,6 +362,8 @@ interface ScanResult {
|
|
|
341
362
|
decidability: Violation[];
|
|
342
363
|
/** Open human-owned entries with no `Routed:` field — counted against its own ratchet. */
|
|
343
364
|
routing: Violation[];
|
|
365
|
+
/** Resolved human-only entries no owner `## Decisions` row names — ratcheted (K1). */
|
|
366
|
+
ownerClose: Violation[];
|
|
344
367
|
}
|
|
345
368
|
|
|
346
369
|
/** What a scan needs to resolve a qualified reference: who it is, and where it may point. */
|
|
@@ -354,6 +377,7 @@ function _scanBoth(rawText: string, ctx: ScanContext = {}): ScanResult {
|
|
|
354
377
|
const violations: Violation[] = [];
|
|
355
378
|
const decidability: Violation[] = [];
|
|
356
379
|
const routing: Violation[] = [];
|
|
380
|
+
const ownerClose: Violation[] = [];
|
|
357
381
|
const text = _stripFencedCode(rawText);
|
|
358
382
|
const declaredIds = new Set<string>();
|
|
359
383
|
const userDecisionIds = new Set<string>();
|
|
@@ -416,6 +440,15 @@ function _scanBoth(rawText: string, ctx: ScanContext = {}): ScanResult {
|
|
|
416
440
|
// Resolved entries are history — re-litigating a decision already
|
|
417
441
|
// made would be churn, and the ratchet would never reach zero.
|
|
418
442
|
const isResolved = /^-[ \t]*\*\*Status:\*\*[ \t]*resolved/im.test(body);
|
|
443
|
+
if (isResolved && ['', '3'].includes(_blockerClass(body)) && !_ownerDecisionNames(text, cur.id)) {
|
|
444
|
+
ownerClose.push({
|
|
445
|
+
line: _lineAt(text, sectionStart + cur.start),
|
|
446
|
+
message:
|
|
447
|
+
`blocker '${cur.id}' is human-only and resolved, but no \`## Decisions\` row ` +
|
|
448
|
+
'resolved by `owner` names it with a date — a class-3 blocker closes only on an ' +
|
|
449
|
+
'owner decision (road-to-a-tick-the-shipped-path-earns 2.3)',
|
|
450
|
+
});
|
|
451
|
+
}
|
|
419
452
|
if (!isResolved) {
|
|
420
453
|
openIds.add(cur.id);
|
|
421
454
|
// The class/run contract is HARD rather than ratcheted, and it
|
|
@@ -552,7 +585,7 @@ function _scanBoth(rawText: string, ctx: ScanContext = {}): ScanResult {
|
|
|
552
585
|
violations.sort((a, b) => a.line - b.line);
|
|
553
586
|
decidability.sort((a, b) => a.line - b.line);
|
|
554
587
|
routing.sort((a, b) => a.line - b.line);
|
|
555
|
-
return { hard: violations, decidability, routing };
|
|
588
|
+
return { hard: violations, decidability, routing, ownerClose };
|
|
556
589
|
}
|
|
557
590
|
|
|
558
591
|
interface LocalBlockers {
|
|
@@ -920,10 +953,11 @@ function main(): number {
|
|
|
920
953
|
let failed = 0;
|
|
921
954
|
const undecidable: Array<{ rel: string; v: Violation }> = [];
|
|
922
955
|
const unrouted: Array<{ rel: string; v: Violation }> = [];
|
|
956
|
+
const unowned: Array<{ rel: string; v: Violation }> = [];
|
|
923
957
|
for (const roadmap of roadmaps) {
|
|
924
958
|
const rel = _relPosix(roadmap, REPO_ROOT);
|
|
925
959
|
const text = fs.readFileSync(roadmap, 'utf-8');
|
|
926
|
-
const { hard, decidability, routing } = _scanBoth(text, {
|
|
960
|
+
const { hard, decidability, routing, ownerClose } = _scanBoth(text, {
|
|
927
961
|
selfStem: path.basename(roadmap, '.md'),
|
|
928
962
|
index,
|
|
929
963
|
});
|
|
@@ -933,6 +967,9 @@ function main(): number {
|
|
|
933
967
|
for (const v of routing) {
|
|
934
968
|
unrouted.push({ rel, v });
|
|
935
969
|
}
|
|
970
|
+
for (const v of ownerClose) {
|
|
971
|
+
unowned.push({ rel, v });
|
|
972
|
+
}
|
|
936
973
|
if (hard.length) {
|
|
937
974
|
failed += 1;
|
|
938
975
|
process.stderr.write(`❌ ${rel}\n`);
|
|
@@ -1021,12 +1058,24 @@ function main(): number {
|
|
|
1021
1058
|
' See templates/roadmaps.md rule 20 "Route before you file".\n',
|
|
1022
1059
|
);
|
|
1023
1060
|
}
|
|
1024
|
-
|
|
1061
|
+
const ownerVerdict = checkRatchet({
|
|
1062
|
+
gate: 'lint_roadmap_blockers:owner-close',
|
|
1063
|
+
actual: unowned.length,
|
|
1064
|
+
repoRoot: REPO_ROOT,
|
|
1065
|
+
});
|
|
1066
|
+
if (!ownerVerdict.ok) {
|
|
1067
|
+
process.stderr.write(`❌ ${ownerVerdict.message}\n`);
|
|
1068
|
+
for (const { rel, v } of unowned) {
|
|
1069
|
+
process.stderr.write(` ${rel}:${v.line}: ${v.message}\n`);
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
if (!verdict.ok || !routingVerdict.ok || !ownerVerdict.ok) {
|
|
1025
1073
|
return 1;
|
|
1026
1074
|
}
|
|
1027
1075
|
if (!QUIET) {
|
|
1028
1076
|
process.stdout.write(`\n✅ ${roadmaps.length} roadmap(s) blocker-contract-clean\n`);
|
|
1029
1077
|
process.stdout.write(`✅ ${routingVerdict.message}\n`);
|
|
1078
|
+
process.stdout.write(`✅ ${ownerVerdict.message}\n`);
|
|
1030
1079
|
process.stdout.write(
|
|
1031
1080
|
`✅ 0 blocker id(s) open in both an active and an archived roadmap ` +
|
|
1032
1081
|
`(${_globArchivedRoadmaps().length} archived file(s) read)\n`,
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
},
|
|
94
94
|
{
|
|
95
95
|
"name": "chat_history_read",
|
|
96
|
-
"description": "Read recent entries
|
|
96
|
+
"description": "Read recent entries from the chat-history JSONL (`agents/runtime/.agent-chat-history`; legacy `agents/.agent-chat-history` accepted) to recover decisions, notes and phase markers from an earlier session. Returns the resolved path and matching entries, newest last.",
|
|
97
97
|
"side_effect": "ro",
|
|
98
98
|
"implemented_on": [
|
|
99
99
|
"stdio"
|
|
@@ -116,7 +116,7 @@
|
|
|
116
116
|
},
|
|
117
117
|
"path": {
|
|
118
118
|
"type": "string",
|
|
119
|
-
"description": "
|
|
119
|
+
"description": "History-file override; default is the standard location."
|
|
120
120
|
},
|
|
121
121
|
"around": {
|
|
122
122
|
"type": "integer",
|
|
@@ -142,7 +142,7 @@
|
|
|
142
142
|
"full"
|
|
143
143
|
],
|
|
144
144
|
"default": "full",
|
|
145
|
-
"description": "'index' returns compact rows (ref, t tag,
|
|
145
|
+
"description": "'index' returns compact rows (ref, t tag, preview, tokens_estimate) — scan, then re-read refs via `around` or a filter. 'full' (default) returns whole entries."
|
|
146
146
|
}
|
|
147
147
|
},
|
|
148
148
|
"additionalProperties": false
|
|
@@ -222,6 +222,29 @@
|
|
|
222
222
|
"readOnlyHint": true
|
|
223
223
|
}
|
|
224
224
|
},
|
|
225
|
+
{
|
|
226
|
+
"name": "graph_area",
|
|
227
|
+
"description": "One code-map area by id, exact name or member file: files, hubs, dependencies. Else refused.",
|
|
228
|
+
"side_effect": "ro",
|
|
229
|
+
"implemented_on": [
|
|
230
|
+
"stdio"
|
|
231
|
+
],
|
|
232
|
+
"input_schema": {
|
|
233
|
+
"type": "object",
|
|
234
|
+
"required": [
|
|
235
|
+
"area"
|
|
236
|
+
],
|
|
237
|
+
"properties": {
|
|
238
|
+
"area": {
|
|
239
|
+
"type": "string"
|
|
240
|
+
}
|
|
241
|
+
},
|
|
242
|
+
"additionalProperties": false
|
|
243
|
+
},
|
|
244
|
+
"annotations": {
|
|
245
|
+
"readOnlyHint": true
|
|
246
|
+
}
|
|
247
|
+
},
|
|
225
248
|
{
|
|
226
249
|
"name": "graph_dead",
|
|
227
250
|
"description": "Symbols with no accepted reference that no declared entry point names. REFUSES (status `refused`) while a source is unreadable: with no exportedness recorded, an exported-but-unimported symbol is indistinguishable from a dead one. Never a deletion recommendation.",
|
|
@@ -283,6 +306,22 @@
|
|
|
283
306
|
"readOnlyHint": false
|
|
284
307
|
}
|
|
285
308
|
},
|
|
309
|
+
{
|
|
310
|
+
"name": "graph_map_status",
|
|
311
|
+
"description": "Is there a code map (agents/map/)? Its freshness, counts and MAP.md path.",
|
|
312
|
+
"side_effect": "ro",
|
|
313
|
+
"implemented_on": [
|
|
314
|
+
"stdio"
|
|
315
|
+
],
|
|
316
|
+
"input_schema": {
|
|
317
|
+
"type": "object",
|
|
318
|
+
"properties": {},
|
|
319
|
+
"additionalProperties": false
|
|
320
|
+
},
|
|
321
|
+
"annotations": {
|
|
322
|
+
"readOnlyHint": true
|
|
323
|
+
}
|
|
324
|
+
},
|
|
286
325
|
{
|
|
287
326
|
"name": "graph_node",
|
|
288
327
|
"description": "One symbol in full: where it is declared, what reaches it, what it reaches, and how connected it is. Resolves EXACTLY (node id, then label) and refuses anything it cannot — it never scores free text, so an answer is always about the node you named.",
|
|
@@ -325,7 +364,15 @@
|
|
|
325
364
|
"uses",
|
|
326
365
|
"inherits",
|
|
327
366
|
"member",
|
|
328
|
-
"tests"
|
|
367
|
+
"tests",
|
|
368
|
+
"routes-to",
|
|
369
|
+
"renders",
|
|
370
|
+
"includes",
|
|
371
|
+
"reads",
|
|
372
|
+
"migrates",
|
|
373
|
+
"persists",
|
|
374
|
+
"relates",
|
|
375
|
+
"documents"
|
|
329
376
|
],
|
|
330
377
|
"description": "Restrict to one relation. Omit for all of them."
|
|
331
378
|
}
|
|
@@ -527,7 +574,7 @@
|
|
|
527
574
|
},
|
|
528
575
|
{
|
|
529
576
|
"name": "memory_lookup",
|
|
530
|
-
"description": "
|
|
577
|
+
"description": "Engineering-memory entries for one or more types, optionally narrowed to anchor paths — use before editing a security-sensitive or historically buggy file. Call with detail:\"index\" FIRST (rows carry id, title, tokens_estimate), then memory_get only the ids you will use, batched. Reads `agents/memory/<type>/*.yml` and `agents/memory/intake/*.jsonl`. Returns a `status` plus per-type `slices`.",
|
|
531
578
|
"side_effect": "ro",
|
|
532
579
|
"implemented_on": [
|
|
533
580
|
"stdio"
|
|
@@ -568,7 +615,7 @@
|
|
|
568
615
|
"token_budget": {
|
|
569
616
|
"type": "integer",
|
|
570
617
|
"minimum": 1,
|
|
571
|
-
"description": "Optional
|
|
618
|
+
"description": "Optional: render compact rows (id, type, confidence, `line`) hard-cut at token_budget × 4 chars; omitted hits yield a top-level `truncation` hint."
|
|
572
619
|
}
|
|
573
620
|
},
|
|
574
621
|
"required": [
|
|
@@ -62,6 +62,7 @@ import {
|
|
|
62
62
|
testsFor,
|
|
63
63
|
untested,
|
|
64
64
|
} from '../code_graph/verbs.js';
|
|
65
|
+
import { areaReport, readMap } from '../code_graph/map.js';
|
|
65
66
|
import type { BuiltinTool } from './tools.js';
|
|
66
67
|
|
|
67
68
|
/** The `no graph here` answer, in one place so all five agree on its shape. */
|
|
@@ -119,7 +120,22 @@ function str(args: Record<string, unknown>, key: string): string {
|
|
|
119
120
|
* drift. An enum that silently lost a value would turn a legal filter into a
|
|
120
121
|
* rejected argument.
|
|
121
122
|
*/
|
|
122
|
-
const RELATIONS = [
|
|
123
|
+
const RELATIONS = [
|
|
124
|
+
'calls',
|
|
125
|
+
'imports',
|
|
126
|
+
'uses',
|
|
127
|
+
'inherits',
|
|
128
|
+
'member',
|
|
129
|
+
'tests',
|
|
130
|
+
'routes-to',
|
|
131
|
+
'renders',
|
|
132
|
+
'includes',
|
|
133
|
+
'reads',
|
|
134
|
+
'migrates',
|
|
135
|
+
'persists',
|
|
136
|
+
'relates',
|
|
137
|
+
'documents',
|
|
138
|
+
] as const;
|
|
123
139
|
|
|
124
140
|
function num(args: Record<string, unknown>, key: string, dflt: number): number {
|
|
125
141
|
const v = args[key];
|
|
@@ -360,4 +376,60 @@ export const GRAPH_TOOLS: Record<string, BuiltinTool> = {
|
|
|
360
376
|
}));
|
|
361
377
|
},
|
|
362
378
|
},
|
|
379
|
+
graph_map_status: {
|
|
380
|
+
name: 'graph_map_status',
|
|
381
|
+
side_effect: 'ro',
|
|
382
|
+
description: 'Is there a code map (agents/map/)? Its freshness, counts and MAP.md path.',
|
|
383
|
+
input_schema: { type: 'object', properties: {}, additionalProperties: false },
|
|
384
|
+
handler: async (_args, root) => {
|
|
385
|
+
const staleness = graphState(root);
|
|
386
|
+
const map = readMap(root);
|
|
387
|
+
if (!map) {
|
|
388
|
+
return {
|
|
389
|
+
status: 'unavailable',
|
|
390
|
+
staleness,
|
|
391
|
+
map: 'absent',
|
|
392
|
+
hint: 'run `agent-config code-graph map` to draw it into agents/map/',
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
const m = map.model;
|
|
396
|
+
return {
|
|
397
|
+
status: 'ok',
|
|
398
|
+
staleness,
|
|
399
|
+
map: 'present',
|
|
400
|
+
drawn_at_commit: map.meta.commit,
|
|
401
|
+
graph_state_when_drawn: map.meta.state,
|
|
402
|
+
files: m.files.length,
|
|
403
|
+
areas: m.areas.length,
|
|
404
|
+
trusted_links: m.analyses.trustedEdges,
|
|
405
|
+
guess_share: m.analyses.guessShare,
|
|
406
|
+
request_paths: m.analyses.requestPathsTotal,
|
|
407
|
+
largest_areas: m.areas.slice(0, 5).map((a) => `${a.id} ${a.name} (${a.files.length})`),
|
|
408
|
+
map_md: 'agents/map/MAP.md',
|
|
409
|
+
index_html: 'agents/map/index.html',
|
|
410
|
+
};
|
|
411
|
+
},
|
|
412
|
+
},
|
|
413
|
+
graph_area: {
|
|
414
|
+
name: 'graph_area',
|
|
415
|
+
side_effect: 'ro',
|
|
416
|
+
description: 'One code-map area by id, exact name or member file: files, hubs, dependencies. Else refused.',
|
|
417
|
+
input_schema: {
|
|
418
|
+
type: 'object',
|
|
419
|
+
required: ['area'],
|
|
420
|
+
properties: {
|
|
421
|
+
area: { type: 'string' },
|
|
422
|
+
},
|
|
423
|
+
additionalProperties: false,
|
|
424
|
+
},
|
|
425
|
+
handler: async (args, root) => {
|
|
426
|
+
const q = str(args, 'area');
|
|
427
|
+
if (q === '') return { status: 'error', error: 'area must be a non-empty string' };
|
|
428
|
+
const map = readMap(root);
|
|
429
|
+
if (!map) return { status: 'unavailable', error: 'no map — run `agent-config code-graph map`' };
|
|
430
|
+
const r = areaReport(map.model, q);
|
|
431
|
+
if ('refusal' in r) return { status: 'refused', refusal: r.refusal, candidates: r.candidates };
|
|
432
|
+
return { status: 'ok', drawn_at_commit: map.meta.commit, ...r };
|
|
433
|
+
},
|
|
434
|
+
},
|
|
363
435
|
};
|
|
@@ -1298,15 +1298,11 @@ export const ALLOWLIST: Record<string, BuiltinTool> = {
|
|
|
1298
1298
|
name: 'chat_history_read',
|
|
1299
1299
|
side_effect: 'ro',
|
|
1300
1300
|
description:
|
|
1301
|
-
|
|
1302
|
-
'chat-history
|
|
1303
|
-
'
|
|
1304
|
-
'
|
|
1305
|
-
'
|
|
1306
|
-
'notes, phase markers — at the start of a new task. ' +
|
|
1307
|
-
'Read-only. Returns the resolved file path plus a list of ' +
|
|
1308
|
-
'matching entries (newest last). Combine `session`, `last`, ' +
|
|
1309
|
-
'and `entry_type` to narrow the result.',
|
|
1301
|
+
'Read recent entries from the chat-history JSONL ' +
|
|
1302
|
+
'(`agents/runtime/.agent-chat-history`; legacy ' +
|
|
1303
|
+
'`agents/.agent-chat-history` accepted) to recover decisions, ' +
|
|
1304
|
+
'notes and phase markers from an earlier session. Returns the ' +
|
|
1305
|
+
'resolved path and matching entries, newest last.',
|
|
1310
1306
|
input_schema: {
|
|
1311
1307
|
type: 'object',
|
|
1312
1308
|
properties: {
|
|
@@ -1328,9 +1324,7 @@ export const ALLOWLIST: Record<string, BuiltinTool> = {
|
|
|
1328
1324
|
path: {
|
|
1329
1325
|
type: 'string',
|
|
1330
1326
|
description:
|
|
1331
|
-
'
|
|
1332
|
-
'the standard chat-history location under the ' +
|
|
1333
|
-
'project root.',
|
|
1327
|
+
'History-file override; default is the standard location.',
|
|
1334
1328
|
},
|
|
1335
1329
|
around: {
|
|
1336
1330
|
type: 'integer',
|
|
@@ -1359,12 +1353,9 @@ export const ALLOWLIST: Record<string, BuiltinTool> = {
|
|
|
1359
1353
|
enum: ['index', 'full'],
|
|
1360
1354
|
default: 'full',
|
|
1361
1355
|
description:
|
|
1362
|
-
"'index' returns compact rows (ref, t tag,
|
|
1363
|
-
'
|
|
1364
|
-
|
|
1365
|
-
'`around` or a narrowed filter. History entries are ' +
|
|
1366
|
-
"large, so index mode pays off here. 'full' " +
|
|
1367
|
-
'(default) returns complete entries.',
|
|
1356
|
+
"'index' returns compact rows (ref, t tag, preview, " +
|
|
1357
|
+
'tokens_estimate) — scan, then re-read refs via ' +
|
|
1358
|
+
"`around` or a filter. 'full' (default) returns whole entries.",
|
|
1368
1359
|
},
|
|
1369
1360
|
},
|
|
1370
1361
|
additionalProperties: false,
|
|
@@ -1375,18 +1366,13 @@ export const ALLOWLIST: Record<string, BuiltinTool> = {
|
|
|
1375
1366
|
name: 'memory_lookup',
|
|
1376
1367
|
side_effect: 'ro',
|
|
1377
1368
|
description:
|
|
1378
|
-
'
|
|
1379
|
-
'
|
|
1380
|
-
'
|
|
1381
|
-
'
|
|
1382
|
-
'
|
|
1383
|
-
'
|
|
1384
|
-
'
|
|
1385
|
-
'for the ids you will actually use, batching multiple ids ' +
|
|
1386
|
-
'into one call. Reads `agents/memory/<type>/*.yml` plus the ' +
|
|
1387
|
-
'`agents/memory/intake/*.jsonl` signal log. Read-only. ' +
|
|
1388
|
-
'Returns the v1 retrieval envelope: a `status` field plus ' +
|
|
1389
|
-
'per-type `slices` carrying the matched entries.',
|
|
1369
|
+
'Engineering-memory entries for one or more types, optionally ' +
|
|
1370
|
+
'narrowed to anchor paths — use before editing a ' +
|
|
1371
|
+
'security-sensitive or historically buggy file. Call with ' +
|
|
1372
|
+
'detail:"index" FIRST (rows carry id, title, tokens_estimate), ' +
|
|
1373
|
+
'then memory_get only the ids you will use, batched. Reads ' +
|
|
1374
|
+
'`agents/memory/<type>/*.yml` and `agents/memory/intake/*.jsonl`. ' +
|
|
1375
|
+
'Returns a `status` plus per-type `slices`.',
|
|
1390
1376
|
input_schema: {
|
|
1391
1377
|
type: 'object',
|
|
1392
1378
|
properties: {
|
|
@@ -1426,12 +1412,9 @@ export const ALLOWLIST: Record<string, BuiltinTool> = {
|
|
|
1426
1412
|
type: 'integer',
|
|
1427
1413
|
minimum: 1,
|
|
1428
1414
|
description:
|
|
1429
|
-
'Optional
|
|
1430
|
-
'
|
|
1431
|
-
'
|
|
1432
|
-
'token_budget × 4 chars; omitted hits appear as a ' +
|
|
1433
|
-
'top-level `truncation` hint naming a concrete next ' +
|
|
1434
|
-
'step. Absent → the envelope is unchanged.',
|
|
1415
|
+
'Optional: render compact rows (id, type, confidence, ' +
|
|
1416
|
+
'`line`) hard-cut at token_budget × 4 chars; omitted ' +
|
|
1417
|
+
'hits yield a top-level `truncation` hint.',
|
|
1435
1418
|
},
|
|
1436
1419
|
},
|
|
1437
1420
|
required: ['types'],
|
package/src/scripts/release.ts
CHANGED
|
@@ -36,8 +36,9 @@
|
|
|
36
36
|
* the PR's own consistency check fails — PR #226).
|
|
37
37
|
* 5. Commit + push — `release: X.Y.Z`, push branch, open PR.
|
|
38
38
|
* 6. Wait for CI — `gh pr checks --watch` (skippable with --no-wait).
|
|
39
|
-
* 7.
|
|
40
|
-
*
|
|
39
|
+
* 7. No review gate — a release waits for no review ledger: every commit
|
|
40
|
+
* on main is already reviewed and merged (owner,
|
|
41
|
+
* 2026-10-22). The self-review stays advisory.
|
|
41
42
|
* 8. Merge — `gh pr merge --merge --delete-branch`.
|
|
42
43
|
* 9. Tag main — fast-forward main, tag the merge commit, push the
|
|
43
44
|
* tag (triggers publish-npm.yml, except under --ci).
|
|
@@ -128,7 +129,6 @@ import { canPrompt, promptLine } from './_lib/tty_prompt.js';
|
|
|
128
129
|
import type { CommitRecord, ImpactTrailers } from './_lib/consumer_impact.js';
|
|
129
130
|
import { COMMIT_LOG_FORMAT, NO_IMPACT_TRAILERS, is_breaking_commit, parse_commit_log, parse_impact_trailers, write_impact_map } from './_lib/consumer_impact.js';
|
|
130
131
|
import { preflightPosition } from './_lib/release_position.js';
|
|
131
|
-
import { settleFindingsLedger } from './_lib/release_findings_ingest.js';
|
|
132
132
|
import { TAG_TRIGGERED_WORKFLOWS, dispatchTagWorkflows } from './_lib/release_tag_dispatch.js';
|
|
133
133
|
import {
|
|
134
134
|
RELEASE_HEAD_DEFAULT,
|
|
@@ -1041,12 +1041,8 @@ function execute(
|
|
|
1041
1041
|
_step(6, total, 'Skip waiting for checks (--no-wait)');
|
|
1042
1042
|
}
|
|
1043
1043
|
|
|
1044
|
-
// Step 7 —
|
|
1045
|
-
|
|
1046
|
-
run, die, repoRoot: REPO_ROOT, remote: REMOTE, trunk: MAIN_BRANCH,
|
|
1047
|
-
step: (m) => { _step(7, total, m); }, write: (s) => process.stdout.write(s),
|
|
1048
|
-
resolvePr: () => Number((pr_info ?? _pr_for_branch(branch))?.['number'] ?? NaN) || null,
|
|
1049
|
-
}, plan.target, branch, pr_merged);
|
|
1044
|
+
// Step 7 — kept as a numbered line so the step anchors stay stable.
|
|
1045
|
+
_step(7, total, 'No review gate — main is already reviewed and merged');
|
|
1050
1046
|
// Step 8 — merge
|
|
1051
1047
|
if (pr_merged) {
|
|
1052
1048
|
_step(8, total, `PR #${pr_info!['number']} already merged — skip`);
|