@event4u/agent-config 9.31.0 → 9.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +146 -0
- package/dist/agent-src/commands/review/routing.md +3 -4
- package/dist/agent-src/contexts/communication/rules-auto/reply-close-mechanics.md +65 -0
- package/dist/agent-src/contexts/execution/host-capability-manifest.md +32 -1
- package/dist/agent-src/contexts/execution/orchestration-telemetry.md +3 -0
- package/dist/agent-src/rules/delegation-policy.md +17 -1
- package/dist/agent-src/scripts/roadmap_gates.ts +107 -3
- package/dist/agent-src/skills/docker/SKILL.md +11 -0
- package/dist/agent-src/skills/laravel/SKILL.md +11 -0
- package/dist/agent-src/skills/review-routing/SKILL.md +23 -6
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/scripts/ownership-map.example.yml +1 -1
- package/dist/agent-src/templates/scripts/work_engine/delivery_state.ts +6 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +332 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/refine.ts +106 -1
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/test.ts +50 -15
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +49 -15
- package/dist/agent-src/templates/scripts/work_engine/state.ts +74 -0
- package/dist/agent-src/templates/scripts/work_engine/state_io.ts +6 -0
- package/dist/cli/registry.js +4 -4
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli-delegate/chunk-2WELHO3P.js +582 -0
- package/dist/cli-delegate/chunk-HTIU3W56.js +66 -0
- package/dist/cli-delegate/{chunk-ITIQSGOQ.js → chunk-MA4GFWDY.js} +7 -4
- package/dist/cli-delegate/{chunk-2WCLVDWC.js → chunk-PMQ6Z3T3.js} +1642 -165
- package/dist/cli-delegate/chunk-PZWRPRWP.js +38 -0
- package/dist/cli-delegate/{chunk-PFBV6XRT.js → chunk-Q26HT4QT.js} +1 -63
- package/dist/cli-delegate/{chunk-LVRYBKTI.js → chunk-YPAWXXXR.js} +158 -0
- package/dist/cli-delegate/cmd_conformance.js +308 -227
- package/dist/cli-delegate/cmd_doctor.js +4 -2
- package/dist/cli-delegate/cmd_export.js +1 -1
- package/dist/cli-delegate/cmd_handoff.js +160 -58
- package/dist/cli-delegate/cmd_prune.js +1 -1
- package/dist/cli-delegate/cmd_session_recycle.js +30 -5
- package/dist/cli-delegate/cmd_settings_get.js +4 -2
- package/dist/cli-delegate/cmd_settings_migrate.js +1 -1
- package/dist/cli-delegate/cmd_settings_set.js +5 -3
- package/dist/cli-delegate/cmd_sync.js +1 -1
- package/dist/cli-delegate/cmd_uninstall.js +1 -1
- package/dist/cli-delegate/cmd_validate.js +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +8 -8
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.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 +1136 -690
- package/dist/install/install.mjs +7 -4
- package/dist/mcp/registry-manifest.json +2 -2
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +3688 -1159
- package/package.json +1 -1
- package/src/agent-src/scripts/roadmap_gates.ts +107 -3
- package/src/agent-src/templates/scripts/ownership-map.example.yml +1 -1
- package/src/agent-src/templates/scripts/work_engine/delivery_state.ts +6 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +332 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/refine.ts +106 -1
- package/src/agent-src/templates/scripts/work_engine/directives/backend/test.ts +50 -15
- package/src/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +49 -15
- package/src/agent-src/templates/scripts/work_engine/state.ts +74 -0
- package/src/agent-src/templates/scripts/work_engine/state_io.ts +6 -0
- package/src/config/cost-parity-budget.json +167 -0
- package/src/config/gate-coverage.yml +44 -5
- package/src/config/quorum-attendance-budget.json +39 -0
- package/src/scripts/_cli/cmd_doctor.ts +69 -1
- package/src/scripts/_cli/cmd_session_recycle.ts +44 -3
- package/src/scripts/_cli/handoff_generate.ts +36 -1
- package/src/scripts/_cli/handoff_sessions.ts +140 -9
- package/src/scripts/_dispatch.bash +5 -3
- package/src/scripts/_lib/carrier_divergence.ts +98 -27
- package/src/scripts/_lib/envelope_grounding.ts +206 -0
- package/src/scripts/_lib/host_capability.ts +79 -0
- package/src/scripts/_lib/orchestration_record.ts +45 -0
- package/src/scripts/_lib/session_eol.ts +85 -0
- package/src/scripts/_lib/subagent_capsule.ts +256 -1
- package/src/scripts/ai_council/clients.ts +31 -0
- package/src/scripts/ai_council/events_log.ts +128 -6
- package/src/scripts/ai_council/orchestrator.ts +12 -3
- package/src/scripts/ai_council/pricing.ts +48 -1
- package/src/scripts/ai_council/quorum.ts +20 -0
- package/src/scripts/ai_council/session.ts +11 -0
- package/src/scripts/ask_transport.ts +20 -1
- package/src/scripts/cache_realization_report.ts +38 -0
- package/src/scripts/check_release_highlights.ts +7 -1
- package/src/scripts/check_secret_leak.test.ts +43 -0
- package/src/scripts/check_secret_leak.ts +12 -0
- package/src/scripts/conformance_scan.ts +105 -0
- package/src/scripts/cost/track.mjs +39 -0
- package/src/scripts/cost_summary.ts +104 -1
- package/src/scripts/council_cli.ts +131 -13
- package/src/scripts/dispatch_economy_report.ts +5 -2
- package/src/scripts/handoff_context_hook.ts +66 -18
- package/src/scripts/hooks/session_eol_hook.ts +12 -12
- package/src/scripts/install.ts +20 -6
- package/src/scripts/lint_budget_ownership.ts +81 -0
- package/src/scripts/lint_skill_frontmatter_safety.ts +55 -1
- package/src/scripts/lint_workflow_paths.ts +384 -0
- package/src/scripts/preamble_byte_census.ts +9 -1
- package/src/scripts/report_carrier_divergence.ts +104 -29
- package/src/scripts/report_conformance_funnel.ts +51 -4
- package/src/scripts/routing_doctor.ts +25 -2
- package/src/scripts/schemas/dod.schema.json +45 -0
- package/src/scripts/schemas/subagent.schema.json +3 -2
- package/dist/cli-delegate/chunk-RVGBH4XK.js +0 -142
|
@@ -13,15 +13,22 @@ import {
|
|
|
13
13
|
_resolve_project_root,
|
|
14
14
|
_run_checks,
|
|
15
15
|
_run_checks_no_manifest,
|
|
16
|
-
_scan_foreign
|
|
17
|
-
|
|
16
|
+
_scan_foreign,
|
|
17
|
+
censusRuleDir,
|
|
18
|
+
comparePair,
|
|
19
|
+
frontmatterPaths,
|
|
20
|
+
proseEqual,
|
|
21
|
+
splitFrontmatter
|
|
22
|
+
} from "./chunk-PMQ6Z3T3.js";
|
|
18
23
|
import "./chunk-FTAISGDQ.js";
|
|
19
24
|
import {
|
|
20
25
|
atomic_write_json,
|
|
21
26
|
atomic_write_text,
|
|
22
27
|
is_replay_mode
|
|
23
28
|
} from "./chunk-EJITJBJX.js";
|
|
24
|
-
import "./chunk-
|
|
29
|
+
import "./chunk-Q26HT4QT.js";
|
|
30
|
+
import "./chunk-YPAWXXXR.js";
|
|
31
|
+
import "./chunk-PZWRPRWP.js";
|
|
25
32
|
import "./chunk-736JCWLM.js";
|
|
26
33
|
import {
|
|
27
34
|
atomicAppendLine,
|
|
@@ -47,9 +54,9 @@ import {
|
|
|
47
54
|
|
|
48
55
|
// src/scripts/_cli/cmd_conformance.ts
|
|
49
56
|
var YAML = __toESM(require_dist(), 1);
|
|
50
|
-
import * as
|
|
57
|
+
import * as fs11 from "node:fs";
|
|
51
58
|
import * as os6 from "node:os";
|
|
52
|
-
import * as
|
|
59
|
+
import * as path11 from "node:path";
|
|
53
60
|
import process5 from "node:process";
|
|
54
61
|
import { spawnSync } from "node:child_process";
|
|
55
62
|
import { fileURLToPath as fileURLToPath11, pathToFileURL as pathToFileURL11 } from "node:url";
|
|
@@ -113,65 +120,19 @@ function routeTargetPathsPosix(target) {
|
|
|
113
120
|
}
|
|
114
121
|
|
|
115
122
|
// src/scripts/report_conformance_funnel.ts
|
|
116
|
-
import * as
|
|
123
|
+
import * as fs10 from "node:fs";
|
|
117
124
|
import * as os5 from "node:os";
|
|
118
|
-
import * as
|
|
125
|
+
import * as path10 from "node:path";
|
|
119
126
|
import process4 from "node:process";
|
|
120
127
|
import { fileURLToPath as fileURLToPath10, pathToFileURL as pathToFileURL10 } from "node:url";
|
|
121
128
|
|
|
122
129
|
// src/scripts/conformance_scan.ts
|
|
123
130
|
import { createHash } from "node:crypto";
|
|
124
|
-
import
|
|
131
|
+
import fs6 from "node:fs";
|
|
125
132
|
import os from "node:os";
|
|
126
|
-
import
|
|
133
|
+
import path6 from "node:path";
|
|
127
134
|
import { fileURLToPath as fileURLToPath6, pathToFileURL as pathToFileURL6 } from "node:url";
|
|
128
135
|
|
|
129
|
-
// src/scripts/_lib/carrier_divergence.ts
|
|
130
|
-
import * as fs from "node:fs";
|
|
131
|
-
import * as path from "node:path";
|
|
132
|
-
var OWNERSHIP_KEYS = ["package", "source_path"];
|
|
133
|
-
function stripOwnershipKeys(text) {
|
|
134
|
-
return text.split("\n").filter((line) => !OWNERSHIP_KEYS.some((k) => line.startsWith(`${k}:`))).join("\n");
|
|
135
|
-
}
|
|
136
|
-
function comparePair(a, b) {
|
|
137
|
-
if (a.equals(b)) {
|
|
138
|
-
return "identical";
|
|
139
|
-
}
|
|
140
|
-
if (stripOwnershipKeys(a.toString("utf-8")) === stripOwnershipKeys(b.toString("utf-8"))) {
|
|
141
|
-
return "provenance-only";
|
|
142
|
-
}
|
|
143
|
-
return "body-diff";
|
|
144
|
-
}
|
|
145
|
-
function stripFrontmatter(text) {
|
|
146
|
-
if (!text.startsWith("---")) return text;
|
|
147
|
-
const end = text.indexOf("\n---", 3);
|
|
148
|
-
if (end === -1) return text;
|
|
149
|
-
const afterFence = text.indexOf("\n", end + 1);
|
|
150
|
-
return afterFence === -1 ? "" : text.slice(afterFence + 1);
|
|
151
|
-
}
|
|
152
|
-
function proseEqual(a, b) {
|
|
153
|
-
return stripFrontmatter(a).trim() === stripFrontmatter(b).trim();
|
|
154
|
-
}
|
|
155
|
-
function censusRuleDir(dir) {
|
|
156
|
-
let files = 0;
|
|
157
|
-
let chars = 0;
|
|
158
|
-
let entries;
|
|
159
|
-
try {
|
|
160
|
-
entries = fs.readdirSync(dir);
|
|
161
|
-
} catch {
|
|
162
|
-
return { files: 0, chars: 0 };
|
|
163
|
-
}
|
|
164
|
-
for (const name of entries) {
|
|
165
|
-
if (!name.endsWith(".md")) continue;
|
|
166
|
-
try {
|
|
167
|
-
chars += fs.statSync(path.join(dir, name)).size;
|
|
168
|
-
files += 1;
|
|
169
|
-
} catch {
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
return { files, chars };
|
|
173
|
-
}
|
|
174
|
-
|
|
175
136
|
// src/scripts/_lib/transcript_entry.ts
|
|
176
137
|
function _isObject(v) {
|
|
177
138
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
@@ -210,8 +171,8 @@ function toolUses(entry) {
|
|
|
210
171
|
}
|
|
211
172
|
|
|
212
173
|
// src/scripts/language_mirror_hook.ts
|
|
213
|
-
import
|
|
214
|
-
import
|
|
174
|
+
import fs from "node:fs";
|
|
175
|
+
import path from "node:path";
|
|
215
176
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
216
177
|
|
|
217
178
|
// src/scripts/_lib/prompt_shape.ts
|
|
@@ -234,11 +195,11 @@ function humanAuthoredLead(text) {
|
|
|
234
195
|
// src/scripts/language_mirror_hook.ts
|
|
235
196
|
var EXIT_ALLOW = 0;
|
|
236
197
|
var EXIT_WARN = 2;
|
|
237
|
-
var STATE_FILE =
|
|
238
|
-
var PIN_LOST_DIR =
|
|
198
|
+
var STATE_FILE = path.join("agents", "state", "language-mirror.json");
|
|
199
|
+
var PIN_LOST_DIR = path.join("agents", "state", "language-mirror.pin-lost");
|
|
239
200
|
function pinLostMarker(session_id) {
|
|
240
201
|
const safe = (session_id || "unknown-session").replace(/[^A-Za-z0-9._-]/g, "_");
|
|
241
|
-
return
|
|
202
|
+
return path.join(PIN_LOST_DIR, `${safe}.marker`);
|
|
242
203
|
}
|
|
243
204
|
function _isObject2(v) {
|
|
244
205
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
@@ -334,7 +295,7 @@ This pin exists because the trigger is not observable from the transcript alone:
|
|
|
334
295
|
}
|
|
335
296
|
function _loadState(target) {
|
|
336
297
|
try {
|
|
337
|
-
const raw =
|
|
298
|
+
const raw = fs.readFileSync(target, "utf8");
|
|
338
299
|
const decoded = JSON.parse(raw);
|
|
339
300
|
return _isObject2(decoded) ? decoded : {};
|
|
340
301
|
} catch {
|
|
@@ -383,10 +344,10 @@ function _sessionId(envelope) {
|
|
|
383
344
|
return typeof v === "string" && v.trim() !== "" ? v : "unknown-session";
|
|
384
345
|
}
|
|
385
346
|
function _migrateLegacyMarker(consumer_root) {
|
|
386
|
-
const legacy =
|
|
347
|
+
const legacy = path.join(consumer_root, PIN_LOST_DIR);
|
|
387
348
|
try {
|
|
388
|
-
if (
|
|
389
|
-
|
|
349
|
+
if (fs.statSync(legacy).isFile()) {
|
|
350
|
+
fs.rmSync(legacy, { force: true });
|
|
390
351
|
}
|
|
391
352
|
} catch {
|
|
392
353
|
}
|
|
@@ -395,13 +356,13 @@ function _setPinLost(consumer_root, session_id) {
|
|
|
395
356
|
if (is_replay_mode()) return;
|
|
396
357
|
_migrateLegacyMarker(consumer_root);
|
|
397
358
|
try {
|
|
398
|
-
atomic_write_text(
|
|
359
|
+
atomic_write_text(path.join(consumer_root, pinLostMarker(session_id)), (/* @__PURE__ */ new Date()).toISOString());
|
|
399
360
|
} catch {
|
|
400
361
|
}
|
|
401
362
|
}
|
|
402
363
|
function _pinLost(consumer_root, session_id) {
|
|
403
364
|
try {
|
|
404
|
-
return
|
|
365
|
+
return fs.existsSync(path.join(consumer_root, pinLostMarker(session_id)));
|
|
405
366
|
} catch {
|
|
406
367
|
return false;
|
|
407
368
|
}
|
|
@@ -409,7 +370,7 @@ function _pinLost(consumer_root, session_id) {
|
|
|
409
370
|
function _clearPinLost(consumer_root, session_id) {
|
|
410
371
|
if (is_replay_mode()) return;
|
|
411
372
|
try {
|
|
412
|
-
|
|
373
|
+
fs.rmSync(path.join(consumer_root, pinLostMarker(session_id)), { force: true });
|
|
413
374
|
} catch {
|
|
414
375
|
}
|
|
415
376
|
}
|
|
@@ -417,7 +378,7 @@ function _reEmitAfterCompaction(consumer_root, session_id) {
|
|
|
417
378
|
if (!_pinLost(consumer_root, session_id)) {
|
|
418
379
|
return EXIT_ALLOW;
|
|
419
380
|
}
|
|
420
|
-
const previous = _loadState(
|
|
381
|
+
const previous = _loadState(path.join(consumer_root, STATE_FILE));
|
|
421
382
|
const language = previous.language;
|
|
422
383
|
const source = previous.source === "system-locale" ? "system-locale" : "prompt";
|
|
423
384
|
_clearPinLost(consumer_root, session_id);
|
|
@@ -463,7 +424,7 @@ function run(stdin_text, options) {
|
|
|
463
424
|
return EXIT_ALLOW;
|
|
464
425
|
}
|
|
465
426
|
const session_id = typeof envelope["session_id"] === "string" ? envelope["session_id"] : "";
|
|
466
|
-
const target =
|
|
427
|
+
const target = path.join(options.consumer_root, STATE_FILE);
|
|
467
428
|
const previous = _loadState(target);
|
|
468
429
|
const classification = classify(prompt);
|
|
469
430
|
const next = nextState(
|
|
@@ -515,13 +476,13 @@ function _isCliEntry() {
|
|
|
515
476
|
if (process.argv[1] === void 0) {
|
|
516
477
|
return false;
|
|
517
478
|
}
|
|
518
|
-
const argvUrl = pathToFileURL(
|
|
479
|
+
const argvUrl = pathToFileURL(path.resolve(process.argv[1])).href;
|
|
519
480
|
if (import.meta.url === argvUrl) {
|
|
520
481
|
return true;
|
|
521
482
|
}
|
|
522
483
|
try {
|
|
523
|
-
const here =
|
|
524
|
-
const argv =
|
|
484
|
+
const here = fs.realpathSync(fileURLToPath(import.meta.url));
|
|
485
|
+
const argv = fs.realpathSync(path.resolve(process.argv[1]));
|
|
525
486
|
return here === argv;
|
|
526
487
|
} catch {
|
|
527
488
|
return false;
|
|
@@ -532,11 +493,11 @@ if (_isCliEntry()) {
|
|
|
532
493
|
}
|
|
533
494
|
|
|
534
495
|
// src/scripts/git_authorization_hook.ts
|
|
535
|
-
import
|
|
536
|
-
import
|
|
496
|
+
import fs2 from "node:fs";
|
|
497
|
+
import path2 from "node:path";
|
|
537
498
|
import { fileURLToPath as fileURLToPath2, pathToFileURL as pathToFileURL2 } from "node:url";
|
|
538
499
|
var EXIT_ALLOW2 = 0;
|
|
539
|
-
var STATE_FILE2 =
|
|
500
|
+
var STATE_FILE2 = path2.join("agents", "state", "git-authorization.json");
|
|
540
501
|
function _isObject3(v) {
|
|
541
502
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
542
503
|
}
|
|
@@ -658,7 +619,7 @@ function run2(stdin_text, options) {
|
|
|
658
619
|
prompt_chars: prompt.length
|
|
659
620
|
};
|
|
660
621
|
try {
|
|
661
|
-
atomic_write_json(
|
|
622
|
+
atomic_write_json(path2.join(options.consumer_root, STATE_FILE2), ledger);
|
|
662
623
|
} catch {
|
|
663
624
|
}
|
|
664
625
|
return EXIT_ALLOW2;
|
|
@@ -684,13 +645,13 @@ function _isCliEntry2() {
|
|
|
684
645
|
if (process.argv[1] === void 0) {
|
|
685
646
|
return false;
|
|
686
647
|
}
|
|
687
|
-
const argvUrl = pathToFileURL2(
|
|
648
|
+
const argvUrl = pathToFileURL2(path2.resolve(process.argv[1])).href;
|
|
688
649
|
if (import.meta.url === argvUrl) {
|
|
689
650
|
return true;
|
|
690
651
|
}
|
|
691
652
|
try {
|
|
692
|
-
const here =
|
|
693
|
-
const argv =
|
|
653
|
+
const here = fs2.realpathSync(fileURLToPath2(import.meta.url));
|
|
654
|
+
const argv = fs2.realpathSync(path2.resolve(process.argv[1]));
|
|
694
655
|
return here === argv;
|
|
695
656
|
} catch {
|
|
696
657
|
return false;
|
|
@@ -701,8 +662,8 @@ if (_isCliEntry2()) {
|
|
|
701
662
|
}
|
|
702
663
|
|
|
703
664
|
// src/scripts/hooks/block_unauthorized_git.ts
|
|
704
|
-
import
|
|
705
|
-
import
|
|
665
|
+
import fs3 from "node:fs";
|
|
666
|
+
import path3 from "node:path";
|
|
706
667
|
import { fileURLToPath as fileURLToPath3, pathToFileURL as pathToFileURL3 } from "node:url";
|
|
707
668
|
var EXIT_ALLOW3 = 0;
|
|
708
669
|
var EXIT_BLOCK = 1;
|
|
@@ -929,7 +890,7 @@ function commandOp(command) {
|
|
|
929
890
|
var LEDGER_MAX_AGE_MS = 30 * 60 * 1e3;
|
|
930
891
|
function _loadLedger(consumer_root, session_id, now) {
|
|
931
892
|
try {
|
|
932
|
-
const raw =
|
|
893
|
+
const raw = fs3.readFileSync(path3.join(consumer_root, STATE_FILE2), "utf8");
|
|
933
894
|
const decoded = JSON.parse(raw);
|
|
934
895
|
if (_isObject4(decoded) && Array.isArray(decoded["authorized"])) {
|
|
935
896
|
const ledgerSession = typeof decoded["session_id"] === "string" ? decoded["session_id"] : "";
|
|
@@ -1020,13 +981,13 @@ function _isCliEntry3() {
|
|
|
1020
981
|
if (process.argv[1] === void 0) {
|
|
1021
982
|
return false;
|
|
1022
983
|
}
|
|
1023
|
-
const argvUrl = pathToFileURL3(
|
|
984
|
+
const argvUrl = pathToFileURL3(path3.resolve(process.argv[1])).href;
|
|
1024
985
|
if (import.meta.url === argvUrl) {
|
|
1025
986
|
return true;
|
|
1026
987
|
}
|
|
1027
988
|
try {
|
|
1028
|
-
const here =
|
|
1029
|
-
const argv =
|
|
989
|
+
const here = fs3.realpathSync(fileURLToPath3(import.meta.url));
|
|
990
|
+
const argv = fs3.realpathSync(path3.resolve(process.argv[1]));
|
|
1030
991
|
return here === argv;
|
|
1031
992
|
} catch {
|
|
1032
993
|
return false;
|
|
@@ -1037,10 +998,10 @@ if (_isCliEntry3()) {
|
|
|
1037
998
|
}
|
|
1038
999
|
|
|
1039
1000
|
// src/scripts/before_complete_hook.ts
|
|
1040
|
-
import
|
|
1041
|
-
import
|
|
1001
|
+
import fs4 from "node:fs";
|
|
1002
|
+
import path4 from "node:path";
|
|
1042
1003
|
import { fileURLToPath as fileURLToPath4, pathToFileURL as pathToFileURL4 } from "node:url";
|
|
1043
|
-
var STATE_FILE3 =
|
|
1004
|
+
var STATE_FILE3 = path4.join("agents", "state", "verify-before-complete.json");
|
|
1044
1005
|
var COMMAND_TOOLS2 = /* @__PURE__ */ new Set([
|
|
1045
1006
|
"launch-process",
|
|
1046
1007
|
"launch_process",
|
|
@@ -1082,7 +1043,7 @@ function _empty_state() {
|
|
|
1082
1043
|
function _load_state(target) {
|
|
1083
1044
|
let isFile = false;
|
|
1084
1045
|
try {
|
|
1085
|
-
isFile =
|
|
1046
|
+
isFile = fs4.statSync(target).isFile();
|
|
1086
1047
|
} catch {
|
|
1087
1048
|
isFile = false;
|
|
1088
1049
|
}
|
|
@@ -1090,7 +1051,7 @@ function _load_state(target) {
|
|
|
1090
1051
|
return _empty_state();
|
|
1091
1052
|
}
|
|
1092
1053
|
try {
|
|
1093
|
-
const decoded = JSON.parse(
|
|
1054
|
+
const decoded = JSON.parse(fs4.readFileSync(target, "utf-8"));
|
|
1094
1055
|
if (typeof decoded === "object" && decoded !== null && !Array.isArray(decoded)) {
|
|
1095
1056
|
return { ..._empty_state(), ...decoded };
|
|
1096
1057
|
}
|
|
@@ -1266,7 +1227,7 @@ function run4(stdin_text, options) {
|
|
|
1266
1227
|
}
|
|
1267
1228
|
}
|
|
1268
1229
|
const event = envelope["event"] || "";
|
|
1269
|
-
const target =
|
|
1230
|
+
const target = path4.join(consumer_root, STATE_FILE3);
|
|
1270
1231
|
let state = _load_state(target);
|
|
1271
1232
|
state = _update(state, event, envelope);
|
|
1272
1233
|
try {
|
|
@@ -1324,13 +1285,13 @@ function _isCliEntry4() {
|
|
|
1324
1285
|
if (process.argv[1] === void 0) {
|
|
1325
1286
|
return false;
|
|
1326
1287
|
}
|
|
1327
|
-
const argvUrl = pathToFileURL4(
|
|
1288
|
+
const argvUrl = pathToFileURL4(path4.resolve(process.argv[1])).href;
|
|
1328
1289
|
if (import.meta.url === argvUrl) {
|
|
1329
1290
|
return true;
|
|
1330
1291
|
}
|
|
1331
1292
|
try {
|
|
1332
|
-
const here =
|
|
1333
|
-
const argv =
|
|
1293
|
+
const here = fs4.realpathSync(fileURLToPath4(import.meta.url));
|
|
1294
|
+
const argv = fs4.realpathSync(path4.resolve(process.argv[1]));
|
|
1334
1295
|
return here === argv;
|
|
1335
1296
|
} catch {
|
|
1336
1297
|
return false;
|
|
@@ -1343,12 +1304,12 @@ if (isCliEntry) {
|
|
|
1343
1304
|
|
|
1344
1305
|
// src/scripts/hooks/evidence_independence.ts
|
|
1345
1306
|
import crypto from "node:crypto";
|
|
1346
|
-
import
|
|
1347
|
-
import
|
|
1307
|
+
import fs5 from "node:fs";
|
|
1308
|
+
import path5 from "node:path";
|
|
1348
1309
|
import { fileURLToPath as fileURLToPath5, pathToFileURL as pathToFileURL5 } from "node:url";
|
|
1349
1310
|
var EXIT_ALLOW4 = 0;
|
|
1350
1311
|
var EXIT_BLOCK2 = 1;
|
|
1351
|
-
var STATE_FILE4 =
|
|
1312
|
+
var STATE_FILE4 = path5.join("agents", "state", "evidence-dispatch.json");
|
|
1352
1313
|
function _isObject5(v) {
|
|
1353
1314
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
1354
1315
|
}
|
|
@@ -1416,8 +1377,8 @@ function extractDispatch(envelope) {
|
|
|
1416
1377
|
}
|
|
1417
1378
|
function _ledgerStamp(consumer_root) {
|
|
1418
1379
|
try {
|
|
1419
|
-
const raw =
|
|
1420
|
-
|
|
1380
|
+
const raw = fs5.readFileSync(
|
|
1381
|
+
path5.join(consumer_root, "agents", "state", "git-authorization.json"),
|
|
1421
1382
|
"utf8"
|
|
1422
1383
|
);
|
|
1423
1384
|
const d = JSON.parse(raw);
|
|
@@ -1428,7 +1389,7 @@ function _ledgerStamp(consumer_root) {
|
|
|
1428
1389
|
}
|
|
1429
1390
|
function _load(target) {
|
|
1430
1391
|
try {
|
|
1431
|
-
const decoded = JSON.parse(
|
|
1392
|
+
const decoded = JSON.parse(fs5.readFileSync(target, "utf8"));
|
|
1432
1393
|
if (_isObject5(decoded) && Array.isArray(decoded["evaluations"])) {
|
|
1433
1394
|
return decoded;
|
|
1434
1395
|
}
|
|
@@ -1483,7 +1444,7 @@ function run5(stdin_text, options) {
|
|
|
1483
1444
|
return EXIT_ALLOW4;
|
|
1484
1445
|
}
|
|
1485
1446
|
}
|
|
1486
|
-
const target =
|
|
1447
|
+
const target = path5.join(options.consumer_root, STATE_FILE4);
|
|
1487
1448
|
const state = _load(target);
|
|
1488
1449
|
const session_id = typeof envelope["session_id"] === "string" ? envelope["session_id"] : "";
|
|
1489
1450
|
const turnMarker = `${session_id}:${_ledgerStamp(options.consumer_root)}`;
|
|
@@ -1534,13 +1495,13 @@ function _isCliEntry5() {
|
|
|
1534
1495
|
if (process.argv[1] === void 0) {
|
|
1535
1496
|
return false;
|
|
1536
1497
|
}
|
|
1537
|
-
const argvUrl = pathToFileURL5(
|
|
1498
|
+
const argvUrl = pathToFileURL5(path5.resolve(process.argv[1])).href;
|
|
1538
1499
|
if (import.meta.url === argvUrl) {
|
|
1539
1500
|
return true;
|
|
1540
1501
|
}
|
|
1541
1502
|
try {
|
|
1542
|
-
const here =
|
|
1543
|
-
const argv =
|
|
1503
|
+
const here = fs5.realpathSync(fileURLToPath5(import.meta.url));
|
|
1504
|
+
const argv = fs5.realpathSync(path5.resolve(process.argv[1]));
|
|
1544
1505
|
return here === argv;
|
|
1545
1506
|
} catch {
|
|
1546
1507
|
return false;
|
|
@@ -1551,7 +1512,7 @@ if (_isCliEntry5()) {
|
|
|
1551
1512
|
}
|
|
1552
1513
|
|
|
1553
1514
|
// src/scripts/conformance_scan.ts
|
|
1554
|
-
var REPO_ROOT =
|
|
1515
|
+
var REPO_ROOT = path6.resolve(path6.dirname(fileURLToPath6(import.meta.url)), "..", "..");
|
|
1555
1516
|
var OBSERVED_BAND = { low: 9.1, high: 39.2 };
|
|
1556
1517
|
var BAND_MIN_TURNS = 1978;
|
|
1557
1518
|
function bandVerdict(rate_pct, assistant_turns) {
|
|
@@ -1560,6 +1521,46 @@ function bandVerdict(rate_pct, assistant_turns) {
|
|
|
1560
1521
|
}
|
|
1561
1522
|
return rate_pct >= OBSERVED_BAND.low && rate_pct <= OBSERVED_BAND.high ? "inside" : "outside";
|
|
1562
1523
|
}
|
|
1524
|
+
var CHECK_IDS = [
|
|
1525
|
+
"language-pin",
|
|
1526
|
+
"git-authorization",
|
|
1527
|
+
"vacuous-evidence",
|
|
1528
|
+
"evidence-steering"
|
|
1529
|
+
];
|
|
1530
|
+
var CHECK_MEANINGS = {
|
|
1531
|
+
"language-pin": "An assistant turn whose user-visible prose is not in the language that turn's own pin named. Carries provenance (turns_since_prompt, compaction_since_prompt) so a pin that was ABSENT because compaction removed it stays distinguishable from one that was present and ignored.",
|
|
1532
|
+
"git-authorization": "A gated git operation performed in a session where no authorization for that operation was observed. Authorization is per-operation and never carries from one to the next.",
|
|
1533
|
+
"vacuous-evidence": "A CI poll read as settled without ever observing an in-flight run \u2014 the poll gap that reports a green settle over a window in which nothing was pending yet.",
|
|
1534
|
+
"evidence-steering": "A self-commissioned evaluation whose prompt pre-loaded its own verdict, or a second self-scoped evaluation of the same subject within one turn."
|
|
1535
|
+
};
|
|
1536
|
+
function renderWhy(report, id) {
|
|
1537
|
+
const hits = report.per_session.flatMap((s) => s.violations.filter((v) => v.check === id));
|
|
1538
|
+
const lines = [
|
|
1539
|
+
`conformance:why \xB7 ${id} \xB7 ${report.sessions} session(s) \xB7 ${report.store}`,
|
|
1540
|
+
"",
|
|
1541
|
+
" What it detects:",
|
|
1542
|
+
` ${CHECK_MEANINGS[id]}`,
|
|
1543
|
+
""
|
|
1544
|
+
];
|
|
1545
|
+
if (hits.length === 0) {
|
|
1546
|
+
lines.push(` Did NOT fire in this window (0 hits over ${report.sessions} session(s)).`);
|
|
1547
|
+
lines.push(" A measured zero, not an unmeasured one \u2014 the check ran.");
|
|
1548
|
+
return lines.join("\n");
|
|
1549
|
+
}
|
|
1550
|
+
lines.push(` Fired ${hits.length} time(s):`);
|
|
1551
|
+
for (const v of hits) {
|
|
1552
|
+
lines.push(` \xB7 ${v.session} @ ${v.at}`);
|
|
1553
|
+
lines.push(` ${v.detail}`);
|
|
1554
|
+
const since = v.turns_since_prompt;
|
|
1555
|
+
const compacted = v.compaction_since_prompt;
|
|
1556
|
+
if (since !== void 0 || compacted !== void 0) {
|
|
1557
|
+
lines.push(
|
|
1558
|
+
` provenance: turns_since_prompt=${since ?? "\u2014"} \xB7 compaction_since_prompt=${compacted ?? "\u2014"}`
|
|
1559
|
+
);
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
return lines.join("\n");
|
|
1563
|
+
}
|
|
1563
1564
|
function _isObject6(v) {
|
|
1564
1565
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
1565
1566
|
}
|
|
@@ -1741,7 +1742,7 @@ function scanSession(sessionId, lines) {
|
|
|
1741
1742
|
}
|
|
1742
1743
|
return report;
|
|
1743
1744
|
}
|
|
1744
|
-
var DEFAULT_RATE_SERIES =
|
|
1745
|
+
var DEFAULT_RATE_SERIES = path6.join(
|
|
1745
1746
|
REPO_ROOT,
|
|
1746
1747
|
"agents",
|
|
1747
1748
|
"runtime",
|
|
@@ -1750,7 +1751,7 @@ var DEFAULT_RATE_SERIES = path7.join(
|
|
|
1750
1751
|
);
|
|
1751
1752
|
function defaultStore(projectDir) {
|
|
1752
1753
|
const slug = projectDir.replace(/[/.]/g, "-");
|
|
1753
|
-
return
|
|
1754
|
+
return path6.join(process.env["HOME"] ?? "", ".claude", "projects", slug);
|
|
1754
1755
|
}
|
|
1755
1756
|
function _tokens(chars) {
|
|
1756
1757
|
return Math.round(chars / 4);
|
|
@@ -1761,13 +1762,13 @@ function measureDelivered(projectRulesDir, globalRulesDir) {
|
|
|
1761
1762
|
return {
|
|
1762
1763
|
project: {
|
|
1763
1764
|
dir: projectRulesDir,
|
|
1764
|
-
present:
|
|
1765
|
+
present: fs6.existsSync(projectRulesDir),
|
|
1765
1766
|
files: p.files,
|
|
1766
1767
|
tokens: _tokens(p.chars)
|
|
1767
1768
|
},
|
|
1768
1769
|
global: {
|
|
1769
1770
|
dir: globalRulesDir,
|
|
1770
|
-
present:
|
|
1771
|
+
present: fs6.existsSync(globalRulesDir),
|
|
1771
1772
|
files: g.files,
|
|
1772
1773
|
tokens: _tokens(g.chars)
|
|
1773
1774
|
},
|
|
@@ -1775,13 +1776,13 @@ function measureDelivered(projectRulesDir, globalRulesDir) {
|
|
|
1775
1776
|
};
|
|
1776
1777
|
}
|
|
1777
1778
|
function storeKey(store) {
|
|
1778
|
-
return createHash("sha256").update(
|
|
1779
|
+
return createHash("sha256").update(path6.resolve(store)).digest("hex").slice(0, 12);
|
|
1779
1780
|
}
|
|
1780
1781
|
function scanStore(store, limit) {
|
|
1781
|
-
const files =
|
|
1782
|
+
const files = fs6.readdirSync(store).filter((f) => f.endsWith(".jsonl")).map((f) => ({ f, m: fs6.statSync(path6.join(store, f)).mtimeMs })).sort((a, b) => b.m - a.m).slice(0, limit).map((x) => x.f);
|
|
1782
1783
|
const per_session = [];
|
|
1783
1784
|
for (const f of files) {
|
|
1784
|
-
const lines =
|
|
1785
|
+
const lines = fs6.readFileSync(path6.join(store, f), "utf8").split("\n");
|
|
1785
1786
|
const r = scanSession(f.replace(/\.jsonl$/, "").slice(0, 8), lines);
|
|
1786
1787
|
if (r.assistant_turns > 0) {
|
|
1787
1788
|
per_session.push(r);
|
|
@@ -1802,10 +1803,10 @@ function scanStore(store, limit) {
|
|
|
1802
1803
|
const language_pin = totals["language-pin"] ?? 0;
|
|
1803
1804
|
const rate_pct = assistant_turns === 0 ? 0 : Number((100 * language_pin / assistant_turns).toFixed(1));
|
|
1804
1805
|
const delivered = measureDelivered(
|
|
1805
|
-
|
|
1806
|
-
|
|
1806
|
+
path6.join(REPO_ROOT, ".claude", "rules"),
|
|
1807
|
+
path6.join(process.env["HOME"] ?? os.homedir(), ".claude", "rules")
|
|
1807
1808
|
);
|
|
1808
|
-
const ownStore =
|
|
1809
|
+
const ownStore = path6.resolve(store) === path6.resolve(defaultStore(REPO_ROOT));
|
|
1809
1810
|
return {
|
|
1810
1811
|
scanned_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1811
1812
|
store,
|
|
@@ -1828,8 +1829,8 @@ function scanStore(store, limit) {
|
|
|
1828
1829
|
};
|
|
1829
1830
|
}
|
|
1830
1831
|
function recordRate(file, scanned_at, rate) {
|
|
1831
|
-
|
|
1832
|
-
|
|
1832
|
+
fs6.mkdirSync(path6.dirname(file), { recursive: true });
|
|
1833
|
+
fs6.appendFileSync(file, `${JSON.stringify({ measured_at: scanned_at, ...rate })}
|
|
1833
1834
|
`, "utf8");
|
|
1834
1835
|
}
|
|
1835
1836
|
function render(report) {
|
|
@@ -1893,6 +1894,7 @@ function main6(argv) {
|
|
|
1893
1894
|
let json = false;
|
|
1894
1895
|
let out = null;
|
|
1895
1896
|
let record = null;
|
|
1897
|
+
let why = null;
|
|
1896
1898
|
for (let i = 0; i < args.length; i += 1) {
|
|
1897
1899
|
const a = args[i];
|
|
1898
1900
|
if (a === "--store" && args[i + 1] !== void 0) {
|
|
@@ -1903,25 +1905,56 @@ function main6(argv) {
|
|
|
1903
1905
|
json = true;
|
|
1904
1906
|
} else if (a === "--output" && args[i + 1] !== void 0) {
|
|
1905
1907
|
out = args[++i];
|
|
1908
|
+
} else if (a === "--why" && args[i + 1] !== void 0) {
|
|
1909
|
+
why = args[++i];
|
|
1906
1910
|
} else if (a === "--record") {
|
|
1907
1911
|
record = args[i + 1] !== void 0 && !args[i + 1].startsWith("-") ? args[++i] : DEFAULT_RATE_SERIES;
|
|
1908
1912
|
}
|
|
1909
1913
|
}
|
|
1914
|
+
if (why !== null && !CHECK_IDS.includes(why)) {
|
|
1915
|
+
process.stderr.write(
|
|
1916
|
+
`conformance:why: unknown check id ${JSON.stringify(why)} \u2014 known ids: ${CHECK_IDS.join(", ")}
|
|
1917
|
+
`
|
|
1918
|
+
);
|
|
1919
|
+
return 2;
|
|
1920
|
+
}
|
|
1910
1921
|
const resolved = store ?? defaultStore(process.cwd());
|
|
1911
|
-
if (!
|
|
1922
|
+
if (!fs6.existsSync(resolved)) {
|
|
1912
1923
|
process.stderr.write(`conformance:behavior: no transcript store at ${resolved}
|
|
1913
1924
|
`);
|
|
1914
1925
|
return 1;
|
|
1915
1926
|
}
|
|
1916
1927
|
const report = scanStore(resolved, Number.isFinite(limit) && limit > 0 ? limit : 30);
|
|
1917
1928
|
if (out) {
|
|
1918
|
-
|
|
1929
|
+
fs6.writeFileSync(out, `${JSON.stringify(report, null, 2)}
|
|
1919
1930
|
`, "utf8");
|
|
1920
1931
|
}
|
|
1921
1932
|
if (record) {
|
|
1922
1933
|
recordRate(record, report.scanned_at, report.rate);
|
|
1923
1934
|
}
|
|
1924
|
-
|
|
1935
|
+
if (why !== null) {
|
|
1936
|
+
const id = why;
|
|
1937
|
+
fs6.writeSync(
|
|
1938
|
+
1,
|
|
1939
|
+
json ? `${JSON.stringify(
|
|
1940
|
+
{
|
|
1941
|
+
check: id,
|
|
1942
|
+
meaning: CHECK_MEANINGS[id],
|
|
1943
|
+
store: report.store,
|
|
1944
|
+
sessions: report.sessions,
|
|
1945
|
+
hits: report.per_session.flatMap(
|
|
1946
|
+
(s) => s.violations.filter((v) => v.check === id)
|
|
1947
|
+
)
|
|
1948
|
+
},
|
|
1949
|
+
null,
|
|
1950
|
+
2
|
|
1951
|
+
)}
|
|
1952
|
+
` : `${renderWhy(report, id)}
|
|
1953
|
+
`
|
|
1954
|
+
);
|
|
1955
|
+
return 0;
|
|
1956
|
+
}
|
|
1957
|
+
fs6.writeSync(1, json ? `${JSON.stringify(report, null, 2)}
|
|
1925
1958
|
` : `${render(report)}
|
|
1926
1959
|
`);
|
|
1927
1960
|
return 0;
|
|
@@ -1933,13 +1966,13 @@ function _isCliEntry6() {
|
|
|
1933
1966
|
if (process.argv[1] === void 0) {
|
|
1934
1967
|
return false;
|
|
1935
1968
|
}
|
|
1936
|
-
const argvUrl = pathToFileURL6(
|
|
1969
|
+
const argvUrl = pathToFileURL6(path6.resolve(process.argv[1])).href;
|
|
1937
1970
|
if (import.meta.url === argvUrl) {
|
|
1938
1971
|
return true;
|
|
1939
1972
|
}
|
|
1940
1973
|
try {
|
|
1941
|
-
const here =
|
|
1942
|
-
const argv =
|
|
1974
|
+
const here = fs6.realpathSync(fileURLToPath6(import.meta.url));
|
|
1975
|
+
const argv = fs6.realpathSync(path6.resolve(process.argv[1]));
|
|
1943
1976
|
return here === argv;
|
|
1944
1977
|
} catch {
|
|
1945
1978
|
return false;
|
|
@@ -1950,19 +1983,19 @@ if (_isCliEntry6()) {
|
|
|
1950
1983
|
}
|
|
1951
1984
|
|
|
1952
1985
|
// src/scripts/report_carrier_divergence.ts
|
|
1953
|
-
import * as
|
|
1986
|
+
import * as fs7 from "node:fs";
|
|
1954
1987
|
import * as os2 from "node:os";
|
|
1955
|
-
import * as
|
|
1988
|
+
import * as path7 from "node:path";
|
|
1956
1989
|
import process2 from "node:process";
|
|
1957
1990
|
import { fileURLToPath as fileURLToPath7, pathToFileURL as pathToFileURL7 } from "node:url";
|
|
1958
1991
|
var _HERE = fileURLToPath7(import.meta.url);
|
|
1959
|
-
var REPO_ROOT2 =
|
|
1960
|
-
var PROJECT_RULES =
|
|
1961
|
-
var PROJECTION_SOURCE =
|
|
1962
|
-
var GLOBAL_RULES =
|
|
1992
|
+
var REPO_ROOT2 = path7.resolve(path7.dirname(_HERE), "..", "..");
|
|
1993
|
+
var PROJECT_RULES = path7.join(".claude", "rules");
|
|
1994
|
+
var PROJECTION_SOURCE = path7.join("dist", "agent-src", "rules");
|
|
1995
|
+
var GLOBAL_RULES = path7.join(".claude", "rules");
|
|
1963
1996
|
function _listRules(dir) {
|
|
1964
1997
|
try {
|
|
1965
|
-
return
|
|
1998
|
+
return fs7.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
|
|
1966
1999
|
} catch {
|
|
1967
2000
|
return [];
|
|
1968
2001
|
}
|
|
@@ -1970,26 +2003,24 @@ function _listRules(dir) {
|
|
|
1970
2003
|
function _ruleType(file) {
|
|
1971
2004
|
let text;
|
|
1972
2005
|
try {
|
|
1973
|
-
text =
|
|
2006
|
+
text = fs7.readFileSync(file, "utf-8");
|
|
1974
2007
|
} catch {
|
|
1975
2008
|
return "";
|
|
1976
2009
|
}
|
|
1977
|
-
|
|
1978
|
-
const end = text.indexOf("\n---", 3);
|
|
1979
|
-
const fm = end === -1 ? text : text.slice(0, end);
|
|
1980
|
-
const m = /^type:\s*"?([a-z]+)"?/m.exec(fm);
|
|
2010
|
+
const m = /^type:\s*"?([a-z]+)"?/m.exec(splitFrontmatter(text).frontmatter);
|
|
1981
2011
|
return m === null ? "" : m[1];
|
|
1982
2012
|
}
|
|
1983
2013
|
function compareCarriers(projectDir, globalDir, sourceDir) {
|
|
1984
2014
|
const out = {
|
|
1985
2015
|
projectDir,
|
|
1986
2016
|
globalDir,
|
|
1987
|
-
globalPresent:
|
|
1988
|
-
projectPresent:
|
|
2017
|
+
globalPresent: fs7.existsSync(globalDir),
|
|
2018
|
+
projectPresent: fs7.existsSync(projectDir),
|
|
1989
2019
|
shared: 0,
|
|
1990
2020
|
identical: [],
|
|
1991
2021
|
provenanceOnly: [],
|
|
1992
2022
|
frontmatterOnly: [],
|
|
2023
|
+
pathsScopeDiff: [],
|
|
1993
2024
|
bodyDiff: [],
|
|
1994
2025
|
projectOnly: [],
|
|
1995
2026
|
globalOnly: [],
|
|
@@ -2007,19 +2038,19 @@ function compareCarriers(projectDir, globalDir, sourceDir) {
|
|
|
2007
2038
|
}
|
|
2008
2039
|
if (!inP && inG) {
|
|
2009
2040
|
out.globalOnly.push(rule);
|
|
2010
|
-
if (sourceDir !== void 0 && _ruleType(
|
|
2041
|
+
if (sourceDir !== void 0 && _ruleType(path7.join(sourceDir, rule)) === "manual") {
|
|
2011
2042
|
out.manualOnlyGlobal.push(rule);
|
|
2012
2043
|
}
|
|
2013
2044
|
continue;
|
|
2014
2045
|
}
|
|
2015
2046
|
out.shared += 1;
|
|
2016
2047
|
let verdict;
|
|
2017
|
-
let
|
|
2048
|
+
let projectCopy;
|
|
2049
|
+
let globalCopy;
|
|
2018
2050
|
try {
|
|
2019
|
-
|
|
2020
|
-
|
|
2051
|
+
projectCopy = fs7.readFileSync(path7.join(projectDir, rule));
|
|
2052
|
+
globalCopy = fs7.readFileSync(path7.join(globalDir, rule));
|
|
2021
2053
|
verdict = comparePair(projectCopy, globalCopy);
|
|
2022
|
-
proseSame = proseEqual(projectCopy.toString("utf-8"), globalCopy.toString("utf-8"));
|
|
2023
2054
|
} catch {
|
|
2024
2055
|
out.shared -= 1;
|
|
2025
2056
|
out.unreadable.push(rule);
|
|
@@ -2027,8 +2058,16 @@ function compareCarriers(projectDir, globalDir, sourceDir) {
|
|
|
2027
2058
|
}
|
|
2028
2059
|
if (verdict === "identical") out.identical.push(rule);
|
|
2029
2060
|
else if (verdict === "provenance-only") out.provenanceOnly.push(rule);
|
|
2030
|
-
else
|
|
2031
|
-
|
|
2061
|
+
else {
|
|
2062
|
+
const projectText = projectCopy.toString("utf-8");
|
|
2063
|
+
const globalText = globalCopy.toString("utf-8");
|
|
2064
|
+
if (proseEqual(projectText, globalText)) {
|
|
2065
|
+
out.frontmatterOnly.push(rule);
|
|
2066
|
+
if (frontmatterPaths(projectText) !== frontmatterPaths(globalText)) {
|
|
2067
|
+
out.pathsScopeDiff.push(rule);
|
|
2068
|
+
}
|
|
2069
|
+
} else out.bodyDiff.push(rule);
|
|
2070
|
+
}
|
|
2032
2071
|
}
|
|
2033
2072
|
return out;
|
|
2034
2073
|
}
|
|
@@ -2057,6 +2096,7 @@ function render2(d) {
|
|
|
2057
2096
|
lines.push(` byte-identical ${d.identical.length}`);
|
|
2058
2097
|
lines.push(` differ ONLY in the install stamp ${d.provenanceOnly.length}`);
|
|
2059
2098
|
lines.push(` differ ONLY in frontmatter ${d.frontmatterOnly.length}`);
|
|
2099
|
+
lines.push(` of which disagree on \`paths:\` ${d.pathsScopeDiff.length} \u2190 ACTIONABLE`);
|
|
2060
2100
|
lines.push(` differ in PROSE ${d.bodyDiff.length}`);
|
|
2061
2101
|
if (d.unreadable.length > 0) {
|
|
2062
2102
|
lines.push(` unreadable on one side ${d.unreadable.length} (${d.unreadable.join(", ")})`);
|
|
@@ -2081,16 +2121,27 @@ function render2(d) {
|
|
|
2081
2121
|
for (const r of d.bodyDiff) lines.push(` - ${r}`);
|
|
2082
2122
|
lines.push("");
|
|
2083
2123
|
}
|
|
2084
|
-
if (d.
|
|
2085
|
-
lines.push(` ${String(d.
|
|
2086
|
-
lines.push("
|
|
2087
|
-
lines.push("
|
|
2088
|
-
lines.push("
|
|
2089
|
-
lines.push("
|
|
2090
|
-
lines.push("
|
|
2091
|
-
lines.push("
|
|
2092
|
-
lines.push("
|
|
2093
|
-
|
|
2124
|
+
if (d.pathsScopeDiff.length > 0) {
|
|
2125
|
+
lines.push(` \`paths:\` SCOPE DISAGREEMENT (${String(d.pathsScopeDiff.length)}) \u2014 same prose, different load schedule.`);
|
|
2126
|
+
lines.push(" ACT ON THESE. `paths` is the one frontmatter key this host reads: with it, a");
|
|
2127
|
+
lines.push(" rule fires when a matching file is read and is NOT re-injected after");
|
|
2128
|
+
lines.push(" /compact; without it, the rule loads unconditionally at launch. So the copy");
|
|
2129
|
+
lines.push(" that lacks `paths` DEFEATS the other copy's scoping \u2014 the rule the project");
|
|
2130
|
+
lines.push(" layer meant to deliver conditionally is delivered always, and an obligation");
|
|
2131
|
+
lines.push(" a maintainer deliberately scoped is silently unscoped on any machine that");
|
|
2132
|
+
lines.push(" carries both. Identical prose does not make this inert.");
|
|
2133
|
+
for (const r of d.pathsScopeDiff) lines.push(` - ${r}`);
|
|
2134
|
+
lines.push("");
|
|
2135
|
+
}
|
|
2136
|
+
const inert = d.frontmatterOnly.length - d.pathsScopeDiff.length;
|
|
2137
|
+
if (inert > 0) {
|
|
2138
|
+
lines.push(` ${String(inert)} further pair(s) differ ONLY in frontmatter the host does not read \u2014`);
|
|
2139
|
+
lines.push(" prose byte-identical, `paths` in agreement, nothing to act on. Two writers,");
|
|
2140
|
+
lines.push(" two policies: `generate-tools` emits `paths` where a rule is path-scoped and");
|
|
2141
|
+
lines.push(" nothing otherwise; `install.ts` writes agent-config's own vocabulary plus its");
|
|
2142
|
+
lines.push(" ownership stamp, and none of those keys is one this host reads");
|
|
2143
|
+
lines.push(" (claude-code-rules-dir-contract.md). Reported as a count on purpose: naming");
|
|
2144
|
+
lines.push(" every pair would bury the two classes above, which are the actionable ones.");
|
|
2094
2145
|
lines.push("");
|
|
2095
2146
|
}
|
|
2096
2147
|
if (d.provenanceOnly.length > 0) {
|
|
@@ -2129,6 +2180,10 @@ function render2(d) {
|
|
|
2129
2180
|
if (d.bodyDiff.length === 0) {
|
|
2130
2181
|
lines.push("");
|
|
2131
2182
|
lines.push(" No prose divergence \u2014 no rule's governed text differs between the carriers.");
|
|
2183
|
+
if (d.pathsScopeDiff.length > 0) {
|
|
2184
|
+
lines.push(" NOT an all-clear: the `paths:` disagreements above are still open, and they");
|
|
2185
|
+
lines.push(" change when a rule loads rather than what it says.");
|
|
2186
|
+
}
|
|
2132
2187
|
lines.push(" The condition is transient \u2014 it returns whenever the checkout moves ahead of");
|
|
2133
2188
|
lines.push(" the installed release \u2014 so this is a reading of right now, not a property of");
|
|
2134
2189
|
lines.push(" the repo. Re-run it, do not cite it. That holds doubly here: the reading also");
|
|
@@ -2141,9 +2196,9 @@ function render2(d) {
|
|
|
2141
2196
|
}
|
|
2142
2197
|
function main7(argv) {
|
|
2143
2198
|
const args = argv ?? process2.argv.slice(2);
|
|
2144
|
-
let projectDir =
|
|
2145
|
-
let globalDir =
|
|
2146
|
-
let sourceDir =
|
|
2199
|
+
let projectDir = path7.join(REPO_ROOT2, PROJECT_RULES);
|
|
2200
|
+
let globalDir = path7.join(os2.homedir(), GLOBAL_RULES);
|
|
2201
|
+
let sourceDir = path7.join(REPO_ROOT2, PROJECTION_SOURCE);
|
|
2147
2202
|
const value = (i) => {
|
|
2148
2203
|
const v = args[i + 1];
|
|
2149
2204
|
return v === void 0 || v.startsWith("-") ? null : v;
|
|
@@ -2157,7 +2212,7 @@ function main7(argv) {
|
|
|
2157
2212
|
`);
|
|
2158
2213
|
return 1;
|
|
2159
2214
|
}
|
|
2160
|
-
const resolved =
|
|
2215
|
+
const resolved = path7.resolve(v);
|
|
2161
2216
|
if (a === "--project") projectDir = resolved;
|
|
2162
2217
|
else if (a === "--global") globalDir = resolved;
|
|
2163
2218
|
else sourceDir = resolved;
|
|
@@ -2179,9 +2234,9 @@ function main7(argv) {
|
|
|
2179
2234
|
}
|
|
2180
2235
|
function _isCliEntry7() {
|
|
2181
2236
|
if (process2.argv[1] === void 0) return false;
|
|
2182
|
-
if (import.meta.url === pathToFileURL7(
|
|
2237
|
+
if (import.meta.url === pathToFileURL7(path7.resolve(process2.argv[1])).href) return true;
|
|
2183
2238
|
try {
|
|
2184
|
-
return
|
|
2239
|
+
return fs7.realpathSync(_HERE) === fs7.realpathSync(path7.resolve(process2.argv[1]));
|
|
2185
2240
|
} catch {
|
|
2186
2241
|
return false;
|
|
2187
2242
|
}
|
|
@@ -2191,30 +2246,30 @@ if (_isCliEntry7()) {
|
|
|
2191
2246
|
}
|
|
2192
2247
|
|
|
2193
2248
|
// src/scripts/report_skill_activation.ts
|
|
2194
|
-
import * as
|
|
2249
|
+
import * as fs8 from "node:fs";
|
|
2195
2250
|
import * as os3 from "node:os";
|
|
2196
|
-
import * as
|
|
2251
|
+
import * as path8 from "node:path";
|
|
2197
2252
|
import { fileURLToPath as fileURLToPath8, pathToFileURL as pathToFileURL8 } from "node:url";
|
|
2198
2253
|
var _HERE2 = fileURLToPath8(import.meta.url);
|
|
2199
|
-
var REPO_ROOT3 =
|
|
2254
|
+
var REPO_ROOT3 = path8.resolve(path8.dirname(_HERE2), "..", "..");
|
|
2200
2255
|
var SKILLS_ROOT = "src/skills";
|
|
2201
2256
|
var TRIGGER_KEYS = ["triggers:", "trigger_description:", "file_pattern:", "path_prefix:"];
|
|
2202
2257
|
var DETERMINISTIC_RE = /^\s*(?:[-*]\s*)?(?:\*\*)?(MUST|NEVER|ALWAYS)\b/m;
|
|
2203
2258
|
function censusSkills(root) {
|
|
2204
2259
|
const out = { total: 0, withTriggerKey: [], withDeterministicObligation: [] };
|
|
2205
|
-
if (!
|
|
2260
|
+
if (!fs8.existsSync(root)) {
|
|
2206
2261
|
return out;
|
|
2207
2262
|
}
|
|
2208
|
-
for (const entry of
|
|
2263
|
+
for (const entry of fs8.readdirSync(root, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
2209
2264
|
if (!entry.isDirectory()) {
|
|
2210
2265
|
continue;
|
|
2211
2266
|
}
|
|
2212
|
-
const file =
|
|
2213
|
-
if (!
|
|
2267
|
+
const file = path8.join(root, entry.name, "SKILL.md");
|
|
2268
|
+
if (!fs8.existsSync(file)) {
|
|
2214
2269
|
continue;
|
|
2215
2270
|
}
|
|
2216
2271
|
out.total += 1;
|
|
2217
|
-
const text =
|
|
2272
|
+
const text = fs8.readFileSync(file, "utf8");
|
|
2218
2273
|
const fmEnd = text.startsWith("---") ? text.indexOf("\n---", 3) : -1;
|
|
2219
2274
|
const fm = fmEnd === -1 ? "" : text.slice(0, fmEnd);
|
|
2220
2275
|
if (TRIGGER_KEYS.some((k) => new RegExp(`^${k}`, "m").test(fm))) {
|
|
@@ -2228,17 +2283,17 @@ function censusSkills(root) {
|
|
|
2228
2283
|
return out;
|
|
2229
2284
|
}
|
|
2230
2285
|
function defaultStore2(cwd) {
|
|
2231
|
-
return
|
|
2286
|
+
return path8.join(os3.homedir(), ".claude", "projects", cwd.replace(/\//g, "-"));
|
|
2232
2287
|
}
|
|
2233
2288
|
function measureUsage(store, limit) {
|
|
2234
2289
|
const rep = { store, sessions: 0, assistantTurns: 0, invocations: 0, bySkill: {} };
|
|
2235
|
-
if (!
|
|
2290
|
+
if (!fs8.existsSync(store)) {
|
|
2236
2291
|
return rep;
|
|
2237
2292
|
}
|
|
2238
|
-
const files =
|
|
2293
|
+
const files = fs8.readdirSync(store).filter((f) => f.endsWith(".jsonl")).map((f) => path8.join(store, f)).sort((a, b) => fs8.statSync(b).mtimeMs - fs8.statSync(a).mtimeMs).slice(0, limit);
|
|
2239
2294
|
rep.sessions = files.length;
|
|
2240
2295
|
for (const file of files) {
|
|
2241
|
-
for (const line of
|
|
2296
|
+
for (const line of fs8.readFileSync(file, "utf8").split("\n")) {
|
|
2242
2297
|
if (!line.trim()) {
|
|
2243
2298
|
continue;
|
|
2244
2299
|
}
|
|
@@ -2301,7 +2356,7 @@ function render3(census, usage) {
|
|
|
2301
2356
|
}
|
|
2302
2357
|
totalInv += u.invocations;
|
|
2303
2358
|
lines.push(
|
|
2304
|
-
` ${
|
|
2359
|
+
` ${path8.basename(u.store).slice(-38).padEnd(38)} sessions=${String(u.sessions).padStart(3)} asst=${String(u.assistantTurns).padStart(6)} Skill calls=${String(u.invocations).padStart(3)}`
|
|
2305
2360
|
);
|
|
2306
2361
|
}
|
|
2307
2362
|
lines.push("");
|
|
@@ -2349,24 +2404,24 @@ function main8(argv) {
|
|
|
2349
2404
|
if (stores.length === 0) {
|
|
2350
2405
|
stores.push(defaultStore2(REPO_ROOT3));
|
|
2351
2406
|
}
|
|
2352
|
-
const census = censusSkills(
|
|
2407
|
+
const census = censusSkills(path8.join(REPO_ROOT3, SKILLS_ROOT));
|
|
2353
2408
|
const usage = stores.map((s) => measureUsage(s, limit));
|
|
2354
2409
|
process.stdout.write(`${render3(census, usage)}
|
|
2355
2410
|
`);
|
|
2356
2411
|
return 0;
|
|
2357
2412
|
}
|
|
2358
|
-
if (process.argv[1] !== void 0 && import.meta.url === pathToFileURL8(
|
|
2413
|
+
if (process.argv[1] !== void 0 && import.meta.url === pathToFileURL8(path8.resolve(process.argv[1])).href) {
|
|
2359
2414
|
process.exit(main8(process.argv.slice(2)));
|
|
2360
2415
|
}
|
|
2361
2416
|
|
|
2362
2417
|
// src/scripts/report_skill_obligation_violations.ts
|
|
2363
|
-
import * as
|
|
2418
|
+
import * as fs9 from "node:fs";
|
|
2364
2419
|
import * as os4 from "node:os";
|
|
2365
|
-
import * as
|
|
2420
|
+
import * as path9 from "node:path";
|
|
2366
2421
|
import process3 from "node:process";
|
|
2367
2422
|
import { fileURLToPath as fileURLToPath9, pathToFileURL as pathToFileURL9 } from "node:url";
|
|
2368
2423
|
var _HERE3 = fileURLToPath9(import.meta.url);
|
|
2369
|
-
var REPO_ROOT4 =
|
|
2424
|
+
var REPO_ROOT4 = path9.resolve(path9.dirname(_HERE3), "..", "..");
|
|
2370
2425
|
var OBLIGATION_LINE_RE = new RegExp(`${DETERMINISTIC_RE.source}.*`, "gm");
|
|
2371
2426
|
var PATH_RE = /`([A-Za-z0-9_./-]*\/[A-Za-z0-9_.-]+\.[a-z]{2,6})`/g;
|
|
2372
2427
|
var CMD_RE = /`([a-z][a-z0-9-]*(?: [a-z][a-z0-9:._-]*){1,3})`/g;
|
|
@@ -2404,7 +2459,7 @@ function _artefacts(line) {
|
|
|
2404
2459
|
return out;
|
|
2405
2460
|
}
|
|
2406
2461
|
function extractObligations(repoRoot) {
|
|
2407
|
-
const skillsRoot =
|
|
2462
|
+
const skillsRoot = path9.join(repoRoot, SKILLS_ROOT);
|
|
2408
2463
|
const census = censusSkills(skillsRoot);
|
|
2409
2464
|
const out = {
|
|
2410
2465
|
skills: census.withDeterministicObligation,
|
|
@@ -2418,7 +2473,7 @@ function extractObligations(repoRoot) {
|
|
|
2418
2473
|
for (const skill of census.withDeterministicObligation) {
|
|
2419
2474
|
let text;
|
|
2420
2475
|
try {
|
|
2421
|
-
text =
|
|
2476
|
+
text = fs9.readFileSync(path9.join(skillsRoot, skill, "SKILL.md"), "utf-8");
|
|
2422
2477
|
} catch {
|
|
2423
2478
|
continue;
|
|
2424
2479
|
}
|
|
@@ -2534,7 +2589,7 @@ function scanSessionForViolations(session, lines, forbidden, parsed) {
|
|
|
2534
2589
|
return flags;
|
|
2535
2590
|
}
|
|
2536
2591
|
function defaultStore3(cwd) {
|
|
2537
|
-
return
|
|
2592
|
+
return path9.join(os4.homedir(), ".claude", "projects", cwd.replace(/[/.]/g, "-"));
|
|
2538
2593
|
}
|
|
2539
2594
|
function scanStore2(repoRoot, store, limit) {
|
|
2540
2595
|
const census = extractObligations(repoRoot);
|
|
@@ -2547,14 +2602,14 @@ function scanStore2(repoRoot, store, limit) {
|
|
|
2547
2602
|
};
|
|
2548
2603
|
let files;
|
|
2549
2604
|
try {
|
|
2550
|
-
files =
|
|
2605
|
+
files = fs9.readdirSync(store).filter((f) => f.endsWith(".jsonl")).map((f) => ({ p: path9.join(store, f), m: fs9.statSync(path9.join(store, f)).mtimeMs })).sort((a, b) => b.m - a.m).slice(0, limit).map((x) => x.p);
|
|
2551
2606
|
} catch {
|
|
2552
2607
|
return report;
|
|
2553
2608
|
}
|
|
2554
2609
|
report.sessions = files.length;
|
|
2555
2610
|
for (const file of files) {
|
|
2556
|
-
const lines =
|
|
2557
|
-
const id =
|
|
2611
|
+
const lines = fs9.readFileSync(file, "utf-8").split("\n");
|
|
2612
|
+
const id = path9.basename(file).replace(/\.jsonl$/, "").slice(0, 8);
|
|
2558
2613
|
const entries = _parseSession(lines);
|
|
2559
2614
|
if (loadedSkillsFrom(entries).size > 0) report.sessionsWithASkill += 1;
|
|
2560
2615
|
report.flags.push(...scanSessionForViolations(id, lines, census.forbidden, entries));
|
|
@@ -2679,9 +2734,9 @@ function main9(argv) {
|
|
|
2679
2734
|
}
|
|
2680
2735
|
function _isCliEntry8() {
|
|
2681
2736
|
if (process3.argv[1] === void 0) return false;
|
|
2682
|
-
if (import.meta.url === pathToFileURL9(
|
|
2737
|
+
if (import.meta.url === pathToFileURL9(path9.resolve(process3.argv[1])).href) return true;
|
|
2683
2738
|
try {
|
|
2684
|
-
return
|
|
2739
|
+
return fs9.realpathSync(_HERE3) === fs9.realpathSync(path9.resolve(process3.argv[1]));
|
|
2685
2740
|
} catch {
|
|
2686
2741
|
return false;
|
|
2687
2742
|
}
|
|
@@ -2692,20 +2747,20 @@ if (_isCliEntry8()) {
|
|
|
2692
2747
|
|
|
2693
2748
|
// src/scripts/report_conformance_funnel.ts
|
|
2694
2749
|
var _HERE4 = fileURLToPath10(import.meta.url);
|
|
2695
|
-
var REPO_ROOT5 =
|
|
2750
|
+
var REPO_ROOT5 = path10.resolve(path10.dirname(_HERE4), "..", "..");
|
|
2696
2751
|
function buildFunnel(opts = {}) {
|
|
2697
2752
|
const repoRoot = opts.repoRoot ?? REPO_ROOT5;
|
|
2698
|
-
const projectRulesDir = opts.projectRulesDir ??
|
|
2699
|
-
const globalRulesDir = opts.globalRulesDir ??
|
|
2700
|
-
const sourceDir = opts.sourceDir ??
|
|
2753
|
+
const projectRulesDir = opts.projectRulesDir ?? path10.join(repoRoot, PROJECT_RULES);
|
|
2754
|
+
const globalRulesDir = opts.globalRulesDir ?? path10.join(os5.homedir(), GLOBAL_RULES);
|
|
2755
|
+
const sourceDir = opts.sourceDir ?? path10.join(repoRoot, PROJECTION_SOURCE);
|
|
2701
2756
|
const store = opts.store ?? defaultStore(repoRoot);
|
|
2702
2757
|
const limit = opts.limit ?? 30;
|
|
2703
2758
|
return {
|
|
2704
2759
|
delivered: measureDelivered(projectRulesDir, globalRulesDir),
|
|
2705
2760
|
divergence: compareCarriers(projectRulesDir, globalRulesDir, sourceDir),
|
|
2706
|
-
skills: censusSkills(
|
|
2761
|
+
skills: censusSkills(path10.join(repoRoot, SKILLS_ROOT)),
|
|
2707
2762
|
usage: measureUsage(store, limit),
|
|
2708
|
-
storePresent:
|
|
2763
|
+
storePresent: fs10.existsSync(store),
|
|
2709
2764
|
sk2: scanStore2(repoRoot, store, limit)
|
|
2710
2765
|
};
|
|
2711
2766
|
}
|
|
@@ -2736,7 +2791,7 @@ function render5(r) {
|
|
|
2736
2791
|
lines.push(" substituted with dist/, which would answer a different question.");
|
|
2737
2792
|
} else {
|
|
2738
2793
|
lines.push(
|
|
2739
|
-
` Divergence: ${d.shared} shared \xB7 ${d.bodyDiff.length} prose-diff \xB7 ${d.frontmatterOnly.length} frontmatter-only \xB7 ${d.provenanceOnly.length} provenance-only \xB7 ${d.projectOnly.length} project-only \xB7 ${d.globalOnly.length} global-only` + (d.manualOnlyGlobal.length > 0 ? ` (${d.manualOnlyGlobal.length} by design, ADR-004 manual)` : "")
|
|
2794
|
+
` Divergence: ${d.shared} shared \xB7 ${d.bodyDiff.length} prose-diff \xB7 ${d.frontmatterOnly.length} frontmatter-only (${d.pathsScopeDiff.length} on \`paths:\`) \xB7 ${d.provenanceOnly.length} provenance-only \xB7 ${d.projectOnly.length} project-only \xB7 ${d.globalOnly.length} global-only` + (d.manualOnlyGlobal.length > 0 ? ` (${d.manualOnlyGlobal.length} by design, ADR-004 manual)` : "")
|
|
2740
2795
|
);
|
|
2741
2796
|
if (d.bodyDiff.length > 0) {
|
|
2742
2797
|
lines.push(` PROSE DIVERGENCE \u2014 both copies reach the model: ${d.bodyDiff.join(", ")}`);
|
|
@@ -2745,15 +2800,41 @@ function render5(r) {
|
|
|
2745
2800
|
lines.push(" (claude-code-rules-dir-contract.md). The project copy is merely the");
|
|
2746
2801
|
lines.push(" newer one \u2014 recency, not precedence.");
|
|
2747
2802
|
}
|
|
2748
|
-
if (d.
|
|
2749
|
-
lines.push(` ${String(d.
|
|
2750
|
-
lines.push("
|
|
2803
|
+
if (d.pathsScopeDiff.length > 0) {
|
|
2804
|
+
lines.push(` \`paths:\` SCOPE DISAGREEMENT (${String(d.pathsScopeDiff.length)}) \u2014 same prose, different load`);
|
|
2805
|
+
lines.push(" schedule. `paths` is the one frontmatter key the host reads, so the copy");
|
|
2806
|
+
lines.push(" without it defeats the other copy's scoping: a deliberately scoped");
|
|
2807
|
+
lines.push(" obligation is delivered unconditionally. Act on these.");
|
|
2808
|
+
}
|
|
2809
|
+
const inertFm = d.frontmatterOnly.length - d.pathsScopeDiff.length;
|
|
2810
|
+
if (inertFm > 0) {
|
|
2811
|
+
lines.push(` ${String(inertFm)} further pair(s) differ only in frontmatter the host does not read \u2014`);
|
|
2812
|
+
lines.push(" prose byte-identical, `paths` in agreement, nothing to act on.");
|
|
2751
2813
|
}
|
|
2752
2814
|
if (d.unreadable.length > 0) {
|
|
2753
2815
|
lines.push(` Unreadable on one side (${d.unreadable.length}) \u2014 a broken install, not a disagreement.`);
|
|
2754
2816
|
}
|
|
2755
2817
|
}
|
|
2756
2818
|
lines.push("");
|
|
2819
|
+
lines.push("OPPORTUNITY \u2014 in how many sessions could a skill fire at all?");
|
|
2820
|
+
if (!r.storePresent) {
|
|
2821
|
+
lines.push(" NO DATA: no transcript store \u2014 opportunity is not measurable here.");
|
|
2822
|
+
lines.push(" An absent store is an answer, not a zero.");
|
|
2823
|
+
} else {
|
|
2824
|
+
lines.push(` sessions scanned ${r.sk2.sessions}`);
|
|
2825
|
+
lines.push(
|
|
2826
|
+
` with a skill in context ${r.sk2.sessionsWithASkill} (${_pct3(r.sk2.sessionsWithASkill, r.sk2.sessions)})`
|
|
2827
|
+
);
|
|
2828
|
+
lines.push(
|
|
2829
|
+
" Skill invocations per such session " + (r.sk2.sessionsWithASkill === 0 ? "n/a" : (r.usage.invocations / r.sk2.sessionsWithASkill).toFixed(2))
|
|
2830
|
+
);
|
|
2831
|
+
}
|
|
2832
|
+
lines.push(` Honest scope: "in context" is the SK-2 scan's reading \u2014 a skill was`);
|
|
2833
|
+
lines.push(" LOADED, not that the task needed it. So this bounds activation from");
|
|
2834
|
+
lines.push(" above; it never claims a missed invocation was a defect. Report-only and");
|
|
2835
|
+
lines.push(" deliberately without a threshold: a joined funnel with a denominator");
|
|
2836
|
+
lines.push(" invites one, and the activation red-baseline null is terminal.");
|
|
2837
|
+
lines.push("");
|
|
2757
2838
|
lines.push("ACTIVATION \u2014 are the delivered skills invoked?");
|
|
2758
2839
|
lines.push(` skills shipped ${r.skills.total}`);
|
|
2759
2840
|
lines.push(
|
|
@@ -2820,7 +2901,7 @@ function main10(argv) {
|
|
|
2820
2901
|
`);
|
|
2821
2902
|
return 1;
|
|
2822
2903
|
}
|
|
2823
|
-
const resolved =
|
|
2904
|
+
const resolved = path10.resolve(v);
|
|
2824
2905
|
if (a === "--store") opts.store = resolved;
|
|
2825
2906
|
else if (a === "--project") opts.projectRulesDir = resolved;
|
|
2826
2907
|
else if (a === "--global") opts.globalRulesDir = resolved;
|
|
@@ -2852,9 +2933,9 @@ function main10(argv) {
|
|
|
2852
2933
|
}
|
|
2853
2934
|
function _isCliEntry9() {
|
|
2854
2935
|
if (process4.argv[1] === void 0) return false;
|
|
2855
|
-
if (import.meta.url === pathToFileURL10(
|
|
2936
|
+
if (import.meta.url === pathToFileURL10(path10.resolve(process4.argv[1])).href) return true;
|
|
2856
2937
|
try {
|
|
2857
|
-
return
|
|
2938
|
+
return fs10.realpathSync(_HERE4) === fs10.realpathSync(path10.resolve(process4.argv[1]));
|
|
2858
2939
|
} catch {
|
|
2859
2940
|
return false;
|
|
2860
2941
|
}
|
|
@@ -2887,17 +2968,17 @@ function conformanceLogPath() {
|
|
|
2887
2968
|
if (override && override.trim().length > 0) {
|
|
2888
2969
|
return override;
|
|
2889
2970
|
}
|
|
2890
|
-
return
|
|
2971
|
+
return path11.join(os6.homedir(), ".event4u", "agent-config", "conformance-log.jsonl");
|
|
2891
2972
|
}
|
|
2892
2973
|
function installLogPath() {
|
|
2893
2974
|
const override = process5.env["AGENT_CONFIG_INSTALL_LOG"];
|
|
2894
2975
|
if (override && override.trim().length > 0) {
|
|
2895
2976
|
return override;
|
|
2896
2977
|
}
|
|
2897
|
-
return
|
|
2978
|
+
return path11.join(os6.homedir(), ".event4u", "agent-config", "install-log.jsonl");
|
|
2898
2979
|
}
|
|
2899
2980
|
function _check_txlog_clean(logPath = installLogPath()) {
|
|
2900
|
-
if (!
|
|
2981
|
+
if (!fs11.existsSync(logPath)) {
|
|
2901
2982
|
return {
|
|
2902
2983
|
id: "txlog-clean",
|
|
2903
2984
|
status: "ok",
|
|
@@ -2931,11 +3012,11 @@ function _check_txlog_clean(logPath = installLogPath()) {
|
|
|
2931
3012
|
};
|
|
2932
3013
|
}
|
|
2933
3014
|
function routeTargetPaths(target) {
|
|
2934
|
-
return routeTargetPathsPosix(target).map((rel) =>
|
|
3015
|
+
return routeTargetPathsPosix(target).map((rel) => path11.join(...rel.split("/")));
|
|
2935
3016
|
}
|
|
2936
3017
|
function _check_router_pointers(packageRoot = PACKAGE_ROOT) {
|
|
2937
|
-
const routerPath =
|
|
2938
|
-
if (!
|
|
3018
|
+
const routerPath = path11.join(packageRoot, "dist", "router.json");
|
|
3019
|
+
if (!fs11.existsSync(routerPath)) {
|
|
2939
3020
|
return {
|
|
2940
3021
|
id: "router-pointers",
|
|
2941
3022
|
status: "fail",
|
|
@@ -2945,7 +3026,7 @@ function _check_router_pointers(packageRoot = PACKAGE_ROOT) {
|
|
|
2945
3026
|
}
|
|
2946
3027
|
let router;
|
|
2947
3028
|
try {
|
|
2948
|
-
router = JSON.parse(
|
|
3029
|
+
router = JSON.parse(fs11.readFileSync(routerPath, "utf8"));
|
|
2949
3030
|
} catch (exc) {
|
|
2950
3031
|
return {
|
|
2951
3032
|
id: "router-pointers",
|
|
@@ -2954,13 +3035,13 @@ function _check_router_pointers(packageRoot = PACKAGE_ROOT) {
|
|
|
2954
3035
|
remedy: "reinstall the package \u2014 dist/router.json is corrupt"
|
|
2955
3036
|
};
|
|
2956
3037
|
}
|
|
2957
|
-
const rulesDir =
|
|
3038
|
+
const rulesDir = path11.join(packageRoot, "dist", "agent-src", "rules");
|
|
2958
3039
|
const broken = [];
|
|
2959
3040
|
let ids = 0;
|
|
2960
3041
|
let targets = 0;
|
|
2961
3042
|
for (const kernelId of router["kernel"] ?? []) {
|
|
2962
3043
|
ids += 1;
|
|
2963
|
-
if (!
|
|
3044
|
+
if (!fs11.existsSync(path11.join(rulesDir, `${kernelId}.md`))) {
|
|
2964
3045
|
broken.push(`kernel:${kernelId} \u2192 rules/${kernelId}.md missing`);
|
|
2965
3046
|
}
|
|
2966
3047
|
}
|
|
@@ -2968,7 +3049,7 @@ function _check_router_pointers(packageRoot = PACKAGE_ROOT) {
|
|
|
2968
3049
|
for (const entry of router[tier] ?? []) {
|
|
2969
3050
|
const ruleId = String(entry["id"] ?? "");
|
|
2970
3051
|
ids += 1;
|
|
2971
|
-
if (!
|
|
3052
|
+
if (!fs11.existsSync(path11.join(rulesDir, `${ruleId}.md`))) {
|
|
2972
3053
|
broken.push(`${tier}:${ruleId} \u2192 rules/${ruleId}.md missing`);
|
|
2973
3054
|
}
|
|
2974
3055
|
for (const target of entry["routes_to"] ?? []) {
|
|
@@ -2978,7 +3059,7 @@ function _check_router_pointers(packageRoot = PACKAGE_ROOT) {
|
|
|
2978
3059
|
broken.push(`${ruleId} \u2192 unparseable routes_to ${JSON.stringify(target)}`);
|
|
2979
3060
|
continue;
|
|
2980
3061
|
}
|
|
2981
|
-
if (!candidates.some((rel) =>
|
|
3062
|
+
if (!candidates.some((rel) => fs11.existsSync(path11.join(packageRoot, rel)))) {
|
|
2982
3063
|
broken.push(`${ruleId} \u2192 ${target} (${candidates[0]} missing)`);
|
|
2983
3064
|
}
|
|
2984
3065
|
}
|
|
@@ -3010,9 +3091,9 @@ function detectSmokePlatform(projectRoot) {
|
|
|
3010
3091
|
return "claude";
|
|
3011
3092
|
}
|
|
3012
3093
|
function dispatcherRunner(packageRoot) {
|
|
3013
|
-
const localTsx =
|
|
3014
|
-
const script =
|
|
3015
|
-
if (
|
|
3094
|
+
const localTsx = path11.join(packageRoot, "node_modules", ".bin", "tsx");
|
|
3095
|
+
const script = path11.join(packageRoot, "src", "scripts", "hooks", "dispatch_hook.ts");
|
|
3096
|
+
if (fs11.existsSync(localTsx)) {
|
|
3016
3097
|
return [localTsx, script];
|
|
3017
3098
|
}
|
|
3018
3099
|
return ["npx", "tsx", script];
|
|
@@ -3062,12 +3143,12 @@ function _check_hook_dispatcher(projectRoot, packageRoot = PACKAGE_ROOT, opts =
|
|
|
3062
3143
|
};
|
|
3063
3144
|
}
|
|
3064
3145
|
function readSettingsMode(projectRoot) {
|
|
3065
|
-
const settingsPath =
|
|
3066
|
-
if (!
|
|
3146
|
+
const settingsPath = path11.join(projectRoot, ".agent-settings.yml");
|
|
3147
|
+
if (!fs11.existsSync(settingsPath)) {
|
|
3067
3148
|
return "eager-all";
|
|
3068
3149
|
}
|
|
3069
3150
|
try {
|
|
3070
|
-
const parsed = YAML.parse(
|
|
3151
|
+
const parsed = YAML.parse(fs11.readFileSync(settingsPath, "utf8"));
|
|
3071
3152
|
const lean = parsed?.["lean_projection"] ?? null;
|
|
3072
3153
|
const mode = lean?.["mode"];
|
|
3073
3154
|
return typeof mode === "string" && mode.length > 0 ? mode : "eager-all";
|
|
@@ -3078,7 +3159,7 @@ function readSettingsMode(projectRoot) {
|
|
|
3078
3159
|
function kernelIdsFromRouter(packageRoot) {
|
|
3079
3160
|
try {
|
|
3080
3161
|
const router = JSON.parse(
|
|
3081
|
-
|
|
3162
|
+
fs11.readFileSync(path11.join(packageRoot, "dist", "router.json"), "utf8")
|
|
3082
3163
|
);
|
|
3083
3164
|
return new Set((router["kernel"] ?? []).map(String));
|
|
3084
3165
|
} catch {
|
|
@@ -3095,8 +3176,8 @@ function _check_lean_projection(projectRoot, packageRoot = PACKAGE_ROOT, project
|
|
|
3095
3176
|
remedy: "set lean_projection.mode to 'eager-all' or 'thin' in .agent-settings.yml"
|
|
3096
3177
|
};
|
|
3097
3178
|
}
|
|
3098
|
-
const rulesDir = projectedRulesDir ??
|
|
3099
|
-
if (!
|
|
3179
|
+
const rulesDir = projectedRulesDir ?? path11.join(projectRoot, ".augment", "rules");
|
|
3180
|
+
if (!fs11.existsSync(rulesDir)) {
|
|
3100
3181
|
return {
|
|
3101
3182
|
id: "lean-projection",
|
|
3102
3183
|
status: "skipped",
|
|
@@ -3105,7 +3186,7 @@ function _check_lean_projection(projectRoot, packageRoot = PACKAGE_ROOT, project
|
|
|
3105
3186
|
};
|
|
3106
3187
|
}
|
|
3107
3188
|
const kernel = kernelIdsFromRouter(packageRoot);
|
|
3108
|
-
const files =
|
|
3189
|
+
const files = fs11.readdirSync(rulesDir).filter((f) => f.endsWith(".md") && f !== "INDEX.md").sort();
|
|
3109
3190
|
const nonKernel = files.filter((f) => !kernel.has(f.replace(/\.md$/, "")));
|
|
3110
3191
|
if (nonKernel.length === 0) {
|
|
3111
3192
|
return {
|
|
@@ -3119,7 +3200,7 @@ function _check_lean_projection(projectRoot, packageRoot = PACKAGE_ROOT, project
|
|
|
3119
3200
|
for (const f of nonKernel) {
|
|
3120
3201
|
let text = "";
|
|
3121
3202
|
try {
|
|
3122
|
-
text =
|
|
3203
|
+
text = fs11.readFileSync(path11.join(rulesDir, f), "utf8");
|
|
3123
3204
|
} catch {
|
|
3124
3205
|
continue;
|
|
3125
3206
|
}
|
|
@@ -3150,8 +3231,8 @@ function _check_lean_projection(projectRoot, packageRoot = PACKAGE_ROOT, project
|
|
|
3150
3231
|
function _check_host_manifest(projectRoot) {
|
|
3151
3232
|
const detected = Object.entries(detectToolPresence(projectRoot)).filter(([, v]) => v === true).map(([k]) => k);
|
|
3152
3233
|
const detectedNote = detected.length > 0 ? `detected surfaces: ${detected.join(", ")}` : "no surfaces detected";
|
|
3153
|
-
const settingsPath =
|
|
3154
|
-
if (!
|
|
3234
|
+
const settingsPath = path11.join(projectRoot, ".agent-settings.yml");
|
|
3235
|
+
if (!fs11.existsSync(settingsPath)) {
|
|
3155
3236
|
return {
|
|
3156
3237
|
id: "host-manifest",
|
|
3157
3238
|
status: "ok",
|
|
@@ -3161,7 +3242,7 @@ function _check_host_manifest(projectRoot) {
|
|
|
3161
3242
|
}
|
|
3162
3243
|
let parsed = null;
|
|
3163
3244
|
try {
|
|
3164
|
-
parsed = YAML.parse(
|
|
3245
|
+
parsed = YAML.parse(fs11.readFileSync(settingsPath, "utf8"));
|
|
3165
3246
|
} catch (exc) {
|
|
3166
3247
|
return {
|
|
3167
3248
|
id: "host-manifest",
|
|
@@ -3335,13 +3416,13 @@ function _isCliEntry10() {
|
|
|
3335
3416
|
if (process5.argv[1] === void 0) {
|
|
3336
3417
|
return false;
|
|
3337
3418
|
}
|
|
3338
|
-
const argvUrl = pathToFileURL11(
|
|
3419
|
+
const argvUrl = pathToFileURL11(path11.resolve(process5.argv[1])).href;
|
|
3339
3420
|
if (import.meta.url === argvUrl) {
|
|
3340
3421
|
return true;
|
|
3341
3422
|
}
|
|
3342
3423
|
try {
|
|
3343
|
-
const here =
|
|
3344
|
-
const argv =
|
|
3424
|
+
const here = fs11.realpathSync(fileURLToPath11(import.meta.url));
|
|
3425
|
+
const argv = fs11.realpathSync(path11.resolve(process5.argv[1]));
|
|
3345
3426
|
return here === argv;
|
|
3346
3427
|
} catch {
|
|
3347
3428
|
return false;
|