@event4u/agent-config 14.6.0 → 14.7.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 +260 -7
- package/README.md +1 -1
- package/dist/agent-src/commands/analyze/inbox.md +264 -10
- package/dist/agent-src/commands/analyze.md +1 -1
- package/dist/agent-src/commands/roadmap/process-full.md +116 -30
- package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +31 -0
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +135 -104
- package/dist/agent-src/rules/context-hygiene.md +2 -0
- package/dist/agent-src/rules/decision-revisit-gate.md +3 -0
- package/dist/agent-src/rules/fix-what-you-see.md +108 -0
- package/dist/agent-src/rules/no-roadmap-references.md +0 -5
- package/dist/agent-src/rules/recurring-criticism.md +110 -0
- package/dist/agent-src/rules/roadmap-progress-sync.md +1 -1
- package/dist/agent-src/rules/rule-type-governance.md +0 -2
- package/dist/agent-src/rules/self-repair-loop.md +17 -0
- package/dist/agent-src/rules/skill-quality.md +0 -2
- package/dist/agent-src/rules/source-confidentiality.md +37 -7
- package/dist/agent-src/scripts/archival_sweep.ts +117 -0
- package/dist/agent-src/scripts/archive_completed_roadmaps.ts +19 -3
- package/dist/agent-src/scripts/gate_budget.ts +282 -0
- package/dist/agent-src/scripts/gate_execute.ts +72 -31
- package/dist/agent-src/scripts/roadmap_gates.ts +74 -3
- package/dist/agent-src/scripts/update_roadmap_progress.ts +251 -7
- package/dist/agent-src/skills/ai-council/SKILL.md +48 -807
- package/dist/agent-src/skills/ai-council/references/advanced-modes.md +320 -0
- package/dist/agent-src/skills/ai-council/references/cost-and-redaction.md +99 -0
- package/dist/agent-src/skills/ai-council/references/execution-modes.md +162 -0
- package/dist/agent-src/skills/ai-council/references/output-and-synthesis.md +125 -0
- package/dist/agent-src/skills/ai-council/references/procedure.md +143 -0
- package/dist/agent-src/skills/quality-tools/SKILL.md +34 -326
- package/dist/agent-src/skills/quality-tools/references/js-ts-tools.md +113 -0
- package/dist/agent-src/skills/quality-tools/references/php-tools.md +222 -0
- package/dist/agent-src/skills/roadmap-management/SKILL.md +15 -409
- package/dist/agent-src/skills/roadmap-management/references/archival.md +226 -0
- package/dist/agent-src/skills/roadmap-management/references/authoring.md +107 -0
- package/dist/agent-src/skills/roadmap-management/references/dashboard.md +47 -0
- package/dist/agent-src/skills/roadmap-management/references/lifecycle.md +58 -0
- package/dist/agent-src/skills/skill-writing/SKILL.md +34 -570
- package/dist/agent-src/skills/skill-writing/references/procedure.md +275 -0
- package/dist/agent-src/skills/skill-writing/references/read-only-scripts.md +18 -0
- package/dist/agent-src/skills/skill-writing/references/section-patterns.md +298 -0
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +45 -2
- package/dist/agent-src/templates/scripts/telemetry/flush_sender.mjs +163 -0
- package/dist/agent-src/templates/scripts/telemetry/remote.ts +160 -7
- package/dist/agent-src/templates/scripts/telemetry/transport.ts +169 -0
- package/dist/cli/registry.js +1 -1
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli-delegate/chunk-2GNWGMAL.js +172 -0
- package/dist/cli-delegate/{chunk-RLN73PR5.js → chunk-4VR4ORQ6.js} +10 -7
- package/dist/cli-delegate/chunk-6EOCNQAM.js +402 -0
- package/dist/cli-delegate/{chunk-XURJ4AQC.js → chunk-74E3TKWV.js} +381 -280
- package/dist/cli-delegate/{chunk-3UCJWMMP.js → chunk-7F3VYSM2.js} +4 -4
- package/dist/cli-delegate/{chunk-BKO2AZ7Z.js → chunk-B2ERU2VA.js} +1 -1
- package/dist/cli-delegate/{chunk-NXFWFAYV.js → chunk-G23AT6GD.js} +1 -0
- package/dist/cli-delegate/{chunk-63WSP6YZ.js → chunk-GJ5BVHXM.js} +72 -165
- package/dist/cli-delegate/{chunk-P6LQDIWK.js → chunk-JZ4NR2TW.js} +338 -0
- package/dist/cli-delegate/chunk-MWRD5YOH.js +100 -0
- package/dist/cli-delegate/{chunk-GRRPEPRN.js → chunk-T7L2QK3K.js} +24 -5
- package/dist/cli-delegate/{chunk-EVTY7ISR.js → chunk-YM4GZDJG.js} +9 -1
- package/dist/cli-delegate/cmd_conformance.js +459 -709
- package/dist/cli-delegate/cmd_doctor.js +6 -6
- package/dist/cli-delegate/cmd_explain.js +1 -1
- package/dist/cli-delegate/cmd_export.js +7 -6
- package/dist/cli-delegate/cmd_handoff.js +6 -6
- package/dist/cli-delegate/cmd_packs_active.js +1 -1
- package/dist/cli-delegate/cmd_preflight.js +2 -2
- package/dist/cli-delegate/cmd_prune.js +7 -6
- package/dist/cli-delegate/cmd_session_recycle.js +840 -30
- package/dist/cli-delegate/cmd_settings_migrate.js +7 -6
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +7 -6
- package/dist/cli-delegate/cmd_uninstall.js +9 -7
- package/dist/cli-delegate/cmd_update.js +1 -1
- package/dist/cli-delegate/cmd_upgrade.js +1 -1
- package/dist/cli-delegate/cmd_validate.js +7 -6
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +68 -25
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +4 -4
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +10 -8
- package/dist/discovery/trust-report.md +3 -3
- package/dist/discovery/workspaces.json +8 -6
- package/dist/hooks/dispatch.js +2901 -2053
- package/dist/install/claudePathsPlan.js +187 -0
- package/dist/install/claudePathsPlan.js.map +1 -0
- package/dist/install/hostLayerFingerprint.js +136 -0
- package/dist/install/hostLayerFingerprint.js.map +1 -0
- package/dist/install/install.mjs +553 -425
- package/dist/install/partitionEligibility.js +276 -0
- package/dist/install/partitionEligibility.js.map +1 -0
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +1744 -1191
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/agent_src.js +41 -0
- package/dist/scripts/_lib/agent_src.js.map +1 -1
- package/dist/scripts/_lib/install_layout.js +83 -0
- package/dist/scripts/_lib/install_layout.js.map +1 -0
- package/dist/scripts/_lib/installed_lock.js +444 -0
- package/dist/scripts/_lib/installed_lock.js.map +1 -0
- package/dist/scripts/condense.js +13 -164
- package/dist/scripts/condense.js.map +1 -1
- package/dist/server/schemas/settings.js +4 -0
- package/dist/server/schemas/settings.js.map +1 -1
- package/docs/contracts/settings-classes.md +12 -6
- package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +8 -3
- package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +26 -0
- package/docs/guidelines/agent-infra/memory-access.md +17 -0
- package/docs/guidelines/agent-infra/recurring-criticism-mechanics.md +96 -0
- package/package.json +1 -1
- package/src/agent-src/scripts/archival_sweep.ts +117 -0
- package/src/agent-src/scripts/archive_completed_roadmaps.ts +19 -3
- package/src/agent-src/scripts/gate_budget.ts +282 -0
- package/src/agent-src/scripts/gate_execute.ts +72 -31
- package/src/agent-src/scripts/roadmap_gates.ts +74 -3
- package/src/agent-src/scripts/update_roadmap_progress.ts +251 -7
- package/src/agent-src/templates/scripts/telemetry/flush_sender.mjs +163 -0
- package/src/agent-src/templates/scripts/telemetry/remote.ts +160 -7
- package/src/agent-src/templates/scripts/telemetry/transport.ts +169 -0
- package/src/config/agent-settings.template.yml +27 -2
- package/src/config/ci-local-parity.yml +18 -0
- package/src/config/estate-count-budget.json +339 -3
- package/src/config/gate-violation-baselines.json +41 -41
- package/src/config/rule-activation-census.json +14 -6
- package/src/config/rule-stub-ceilings.json +19 -6
- package/src/install/claudePathsPlan.ts +196 -0
- package/src/install/hostLayerFingerprint.ts +145 -0
- package/src/install/partitionEligibility.ts +325 -0
- package/src/scripts/_cli/cmd_session_recycle.ts +9 -1
- package/src/scripts/_dispatch.bash +6 -1
- package/src/scripts/_lib/ac_heading.ts +30 -0
- package/src/scripts/_lib/agent_src.ts +42 -0
- package/src/scripts/_lib/bench_ab_pinned_repo.ts +162 -0
- package/src/scripts/_lib/bench_ab_workspace.ts +10 -1
- package/src/scripts/_lib/envelope_grounding.ts +38 -8
- package/src/scripts/_lib/installed_lock.ts +50 -5
- package/src/scripts/_lib/md_section.ts +129 -0
- package/src/scripts/_lib/scope_guard.sh +26 -3
- package/src/scripts/_lib/self_repair.ts +19 -0
- package/src/scripts/_lib/self_repair_class_b.ts +171 -0
- package/src/scripts/ai_council/cli_help.ts +55 -0
- package/src/scripts/before_complete_hook.ts +153 -28
- package/src/scripts/bench_ab_v2_complexity.ts +27 -7
- package/src/scripts/check_references.ts +60 -0
- package/src/scripts/check_release_published.ts +32 -11
- package/src/scripts/check_single_delivery.ts +59 -15
- package/src/scripts/ci_settle.ts +170 -0
- package/src/scripts/condense.ts +20 -170
- package/src/scripts/council_cli.ts +3 -3
- package/src/scripts/dispatch_r2_reviewer.ts +6 -14
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +77 -14
- package/src/scripts/hooks/block_no_verify.ts +61 -10
- package/src/scripts/hooks/block_unauthorized_git.ts +1 -1
- package/src/scripts/hooks/concern_registry.ts +4 -0
- package/src/scripts/hooks/rtk_wrap_hook.ts +8 -3
- package/src/scripts/hooks/run_continuation_hook.ts +8 -5
- package/src/scripts/hooks/ship_diff_volume_hook.ts +81 -15
- package/src/scripts/hooks/source_first_gate_hook.ts +464 -0
- package/src/scripts/hooks/state_io.ts +782 -20
- package/src/scripts/hooks/subagent_ledger_hook.ts +44 -15
- package/src/scripts/hooks/telemetry_flush_hook.ts +139 -0
- package/src/scripts/hooks/telemetry_self_repair.ts +128 -0
- package/src/scripts/hooks/telemetry_usage_hook.ts +22 -4
- package/src/scripts/hooks/turn_end_gate_hook.ts +81 -15
- package/src/scripts/install.ts +16 -11
- package/src/scripts/language_mirror_hook.ts +561 -25
- package/src/scripts/lint_framework_leakage_allowlist.json +2 -2
- package/src/scripts/lint_plan_risk_register.ts +4 -3
- package/src/scripts/lint_skill_router_head.ts +4 -4
- package/src/scripts/mcp_server/tools.ts +2 -2
- package/src/scripts/new_roadmap.ts +136 -0
- package/src/scripts/pack_mcp_content.ts +20 -5
- package/src/scripts/release.ts +37 -38
- package/src/scripts/report_layer_overlap.ts +6 -0
- package/src/scripts/self_repair_hook.ts +37 -5
- package/src/scripts/session_register_hook.ts +11 -0
- package/src/scripts/skill_usage_collect.ts +11 -1
- package/src/scripts/skill_usage_report.ts +278 -8
- package/src/scripts/sync_pr_branch.ts +7 -0
- package/src/server/schemas/settings.ts +8 -0
- package/dist/cli-delegate/chunk-EJITJBJX.js +0 -172
- package/dist/cli-delegate/chunk-PZWRPRWP.js +0 -38
- /package/dist/cli-delegate/{chunk-RYNADUFG.js → chunk-LWTYTX6F.js} +0 -0
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
import { createRequire as __acCreateRequire } from 'node:module'; const require = globalThis.require ?? __acCreateRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
deriveSessionKey,
|
|
4
|
+
foldRefusal,
|
|
5
|
+
parseRecord,
|
|
6
|
+
readInstallBoundary,
|
|
7
|
+
sessionRefusalFile
|
|
8
|
+
} from "./chunk-2GNWGMAL.js";
|
|
5
9
|
import {
|
|
10
|
+
isCiPoll,
|
|
11
|
+
isVacuousOutput,
|
|
12
|
+
pendingCount,
|
|
13
|
+
statePathFor,
|
|
6
14
|
validateAssumption
|
|
7
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-JZ4NR2TW.js";
|
|
16
|
+
import {
|
|
17
|
+
readHookStdin
|
|
18
|
+
} from "./chunk-F7DQWYR5.js";
|
|
8
19
|
import {
|
|
9
20
|
ArgparseExit,
|
|
10
21
|
STATUS_SYMBOLS,
|
|
@@ -22,29 +33,32 @@ import {
|
|
|
22
33
|
frontmatterPaths,
|
|
23
34
|
proseEqual,
|
|
24
35
|
splitFrontmatter
|
|
25
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-7F3VYSM2.js";
|
|
26
37
|
import "./chunk-FTAISGDQ.js";
|
|
27
|
-
import {
|
|
28
|
-
atomic_write_json,
|
|
29
|
-
atomic_write_text,
|
|
30
|
-
is_replay_mode
|
|
31
|
-
} from "./chunk-EJITJBJX.js";
|
|
32
38
|
import "./chunk-Q26HT4QT.js";
|
|
33
39
|
import {
|
|
34
40
|
projectStoreSlug,
|
|
35
41
|
resolveSessionRole
|
|
36
42
|
} from "./chunk-FBKL6JWT.js";
|
|
37
|
-
import
|
|
43
|
+
import {
|
|
44
|
+
atomic_write_json,
|
|
45
|
+
atomic_write_text,
|
|
46
|
+
has_stable_session_id,
|
|
47
|
+
is_replay_mode,
|
|
48
|
+
owns_session_state,
|
|
49
|
+
prune_legacy_state_file,
|
|
50
|
+
prune_stale_session_states,
|
|
51
|
+
session_state_file
|
|
52
|
+
} from "./chunk-6EOCNQAM.js";
|
|
38
53
|
import "./chunk-M2DPGFZ4.js";
|
|
39
54
|
import {
|
|
40
55
|
atomicAppendLine,
|
|
41
56
|
manifest_path,
|
|
42
57
|
read_manifest
|
|
43
|
-
} from "./chunk-
|
|
44
|
-
import
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
import "./chunk-NXFWFAYV.js";
|
|
58
|
+
} from "./chunk-GJ5BVHXM.js";
|
|
59
|
+
import "./chunk-MWRD5YOH.js";
|
|
60
|
+
import "./chunk-T7L2QK3K.js";
|
|
61
|
+
import "./chunk-G23AT6GD.js";
|
|
48
62
|
import {
|
|
49
63
|
load_agent_settings
|
|
50
64
|
} from "./chunk-NLP54U3J.js";
|
|
@@ -64,12 +78,12 @@ import {
|
|
|
64
78
|
|
|
65
79
|
// src/scripts/_cli/cmd_conformance.ts
|
|
66
80
|
var YAML = __toESM(require_dist(), 1);
|
|
67
|
-
import * as
|
|
81
|
+
import * as fs14 from "node:fs";
|
|
68
82
|
import * as os7 from "node:os";
|
|
69
|
-
import * as
|
|
83
|
+
import * as path14 from "node:path";
|
|
70
84
|
import process6 from "node:process";
|
|
71
85
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
72
|
-
import { fileURLToPath as
|
|
86
|
+
import { fileURLToPath as fileURLToPath14, pathToFileURL as pathToFileURL14 } from "node:url";
|
|
73
87
|
|
|
74
88
|
// src/install/txlog.ts
|
|
75
89
|
import { createReadStream, createWriteStream, existsSync, readFileSync, renameSync, statSync, unlinkSync } from "node:fs";
|
|
@@ -130,18 +144,18 @@ function routeTargetPathsPosix(target) {
|
|
|
130
144
|
}
|
|
131
145
|
|
|
132
146
|
// src/scripts/report_conformance_funnel.ts
|
|
133
|
-
import * as
|
|
147
|
+
import * as fs13 from "node:fs";
|
|
134
148
|
import * as os6 from "node:os";
|
|
135
|
-
import * as
|
|
149
|
+
import * as path13 from "node:path";
|
|
136
150
|
import process5 from "node:process";
|
|
137
|
-
import { fileURLToPath as
|
|
151
|
+
import { fileURLToPath as fileURLToPath13, pathToFileURL as pathToFileURL13 } from "node:url";
|
|
138
152
|
|
|
139
153
|
// src/scripts/conformance_scan.ts
|
|
140
|
-
import { createHash as
|
|
141
|
-
import
|
|
154
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
155
|
+
import fs9 from "node:fs";
|
|
142
156
|
import os2 from "node:os";
|
|
143
|
-
import
|
|
144
|
-
import { fileURLToPath as
|
|
157
|
+
import path9 from "node:path";
|
|
158
|
+
import { fileURLToPath as fileURLToPath9, pathToFileURL as pathToFileURL9 } from "node:url";
|
|
145
159
|
|
|
146
160
|
// src/scripts/_lib/transcript_entry.ts
|
|
147
161
|
function _isObject(v) {
|
|
@@ -206,6 +220,14 @@ function humanAuthoredLead(text) {
|
|
|
206
220
|
var EXIT_ALLOW = 0;
|
|
207
221
|
var EXIT_WARN = 2;
|
|
208
222
|
var STATE_FILE = path.join("agents", "state", "language-mirror.json");
|
|
223
|
+
var STATE_DIR = path.join("agents", "state", "language-mirror");
|
|
224
|
+
var STATE_RETENTION_DAYS = 7;
|
|
225
|
+
function hasStableSessionId(session_id) {
|
|
226
|
+
return has_stable_session_id(session_id);
|
|
227
|
+
}
|
|
228
|
+
function statePathFor2(session_id) {
|
|
229
|
+
return session_state_file(STATE_DIR, session_id);
|
|
230
|
+
}
|
|
209
231
|
var PIN_LOST_DIR = path.join("agents", "state", "language-mirror.pin-lost");
|
|
210
232
|
function pinLostMarker(session_id) {
|
|
211
233
|
const safe = (session_id || "unknown-session").replace(/[^A-Za-z0-9._-]/g, "_");
|
|
@@ -312,9 +334,13 @@ function _loadState(target) {
|
|
|
312
334
|
return {};
|
|
313
335
|
}
|
|
314
336
|
}
|
|
337
|
+
function _ownsPin(previous, session_id) {
|
|
338
|
+
return owns_session_state(previous, session_id);
|
|
339
|
+
}
|
|
340
|
+
var REEMIT_AFTER_TOOL_CALLS = 150;
|
|
315
341
|
function nextState(previous, classification, prompt_chars, session_id, now, locale = "und") {
|
|
316
342
|
if (classification.language === "und") {
|
|
317
|
-
if (previous.language === "de" || previous.language === "en") {
|
|
343
|
+
if (_ownsPin(previous, session_id) && (previous.language === "de" || previous.language === "en")) {
|
|
318
344
|
return null;
|
|
319
345
|
}
|
|
320
346
|
if (locale === "und") {
|
|
@@ -327,7 +353,8 @@ function nextState(previous, classification, prompt_chars, session_id, now, loca
|
|
|
327
353
|
prompt_chars,
|
|
328
354
|
de_markers: classification.de_markers,
|
|
329
355
|
en_markers: classification.en_markers,
|
|
330
|
-
session_id
|
|
356
|
+
session_id,
|
|
357
|
+
tool_calls_since_pin: 0
|
|
331
358
|
};
|
|
332
359
|
}
|
|
333
360
|
return {
|
|
@@ -337,7 +364,8 @@ function nextState(previous, classification, prompt_chars, session_id, now, loca
|
|
|
337
364
|
prompt_chars,
|
|
338
365
|
de_markers: classification.de_markers,
|
|
339
366
|
en_markers: classification.en_markers,
|
|
340
|
-
session_id
|
|
367
|
+
session_id,
|
|
368
|
+
tool_calls_since_pin: 0
|
|
341
369
|
};
|
|
342
370
|
}
|
|
343
371
|
function _extractPrompt(payload) {
|
|
@@ -384,26 +412,162 @@ function _clearPinLost(consumer_root, session_id) {
|
|
|
384
412
|
} catch {
|
|
385
413
|
}
|
|
386
414
|
}
|
|
387
|
-
function _reEmitAfterCompaction(consumer_root, session_id) {
|
|
388
|
-
if (!
|
|
415
|
+
function _reEmitAfterCompaction(consumer_root, session_id, write_json = atomic_write_json) {
|
|
416
|
+
if (!hasStableSessionId(session_id)) {
|
|
389
417
|
return EXIT_ALLOW;
|
|
390
418
|
}
|
|
391
|
-
|
|
392
|
-
const language = previous.language;
|
|
393
|
-
const source = previous.source === "system-locale" ? "system-locale" : "prompt";
|
|
394
|
-
_clearPinLost(consumer_root, session_id);
|
|
395
|
-
if (language !== "de" && language !== "en") {
|
|
419
|
+
if (!_pinLost(consumer_root, session_id)) {
|
|
396
420
|
return EXIT_ALLOW;
|
|
397
421
|
}
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
422
|
+
return _withToolWriteLock(consumer_root, session_id, EXIT_ALLOW, () => {
|
|
423
|
+
const previous = _loadState(path.join(consumer_root, statePathFor2(session_id)));
|
|
424
|
+
const language = previous.language;
|
|
425
|
+
const source = previous.source === "system-locale" ? "system-locale" : "prompt";
|
|
426
|
+
_clearPinLost(consumer_root, session_id);
|
|
427
|
+
if (language !== "de" && language !== "en") {
|
|
428
|
+
return EXIT_ALLOW;
|
|
429
|
+
}
|
|
430
|
+
if (!_ownsPin(previous, session_id)) {
|
|
431
|
+
return EXIT_ALLOW;
|
|
432
|
+
}
|
|
433
|
+
if (!_resetDistance(consumer_root, previous, session_id, write_json)) {
|
|
434
|
+
return EXIT_ALLOW;
|
|
435
|
+
}
|
|
436
|
+
process.stdout.write(
|
|
437
|
+
`${JSON.stringify({
|
|
438
|
+
decision: "warn",
|
|
439
|
+
reason: noticeText(language, source),
|
|
440
|
+
additional_context: pinText(language, source)
|
|
441
|
+
})}
|
|
404
442
|
`
|
|
443
|
+
);
|
|
444
|
+
return EXIT_WARN;
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
function _pruneLegacyState(consumer_root) {
|
|
448
|
+
prune_legacy_state_file(path.join(consumer_root, STATE_FILE));
|
|
449
|
+
}
|
|
450
|
+
function _pruneStaleSessions(consumer_root, now_ms, mtimeOf = (target) => fs.statSync(target).mtimeMs) {
|
|
451
|
+
return prune_stale_session_states(
|
|
452
|
+
path.join(consumer_root, STATE_DIR),
|
|
453
|
+
now_ms,
|
|
454
|
+
STATE_RETENTION_DAYS,
|
|
455
|
+
mtimeOf
|
|
405
456
|
);
|
|
406
|
-
|
|
457
|
+
}
|
|
458
|
+
var LOCK_STALE_MS = 3e4;
|
|
459
|
+
function _withToolWriteLock(consumer_root, session_id, when_busy, body, now_ms = Date.now()) {
|
|
460
|
+
const lock = `${path.join(consumer_root, statePathFor2(session_id))}.lock`;
|
|
461
|
+
let fd;
|
|
462
|
+
const acquire = () => {
|
|
463
|
+
try {
|
|
464
|
+
fs.mkdirSync(path.dirname(lock), { recursive: true });
|
|
465
|
+
return fs.openSync(lock, "wx");
|
|
466
|
+
} catch (err) {
|
|
467
|
+
if (err.code !== "EEXIST") return null;
|
|
468
|
+
let age;
|
|
469
|
+
try {
|
|
470
|
+
age = now_ms - fs.statSync(lock).mtimeMs;
|
|
471
|
+
} catch {
|
|
472
|
+
return null;
|
|
473
|
+
}
|
|
474
|
+
if (age < LOCK_STALE_MS) return null;
|
|
475
|
+
try {
|
|
476
|
+
fs.rmSync(lock, { force: true });
|
|
477
|
+
return fs.openSync(lock, "wx");
|
|
478
|
+
} catch {
|
|
479
|
+
return null;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
const held = acquire();
|
|
484
|
+
if (held === null) return when_busy;
|
|
485
|
+
fd = held;
|
|
486
|
+
try {
|
|
487
|
+
return body();
|
|
488
|
+
} finally {
|
|
489
|
+
try {
|
|
490
|
+
fs.closeSync(fd);
|
|
491
|
+
} catch {
|
|
492
|
+
}
|
|
493
|
+
try {
|
|
494
|
+
fs.rmSync(lock, { force: true });
|
|
495
|
+
} catch {
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
function _writeDistance(consumer_root, expected, session_id, value, write_json = atomic_write_json) {
|
|
500
|
+
if (is_replay_mode()) return false;
|
|
501
|
+
if (!hasStableSessionId(session_id)) return false;
|
|
502
|
+
const target = path.join(consumer_root, statePathFor2(session_id));
|
|
503
|
+
const current = _loadState(target);
|
|
504
|
+
if (!_ownsPin(current, session_id)) return false;
|
|
505
|
+
if (current.detected_at !== expected.detected_at || current.language !== expected.language || current.source !== expected.source) {
|
|
506
|
+
return false;
|
|
507
|
+
}
|
|
508
|
+
try {
|
|
509
|
+
write_json(target, {
|
|
510
|
+
...current,
|
|
511
|
+
session_id: typeof current.session_id === "string" && current.session_id !== "" ? current.session_id : session_id,
|
|
512
|
+
tool_calls_since_pin: value
|
|
513
|
+
});
|
|
514
|
+
return true;
|
|
515
|
+
} catch {
|
|
516
|
+
return false;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
function _resetDistance(consumer_root, expected, session_id, write_json = atomic_write_json) {
|
|
520
|
+
return _writeDistance(consumer_root, expected, session_id, 0, write_json);
|
|
521
|
+
}
|
|
522
|
+
function _reEmitAfterDistance(consumer_root, session_id, write_json = atomic_write_json) {
|
|
523
|
+
if (is_replay_mode()) {
|
|
524
|
+
return EXIT_ALLOW;
|
|
525
|
+
}
|
|
526
|
+
if (!hasStableSessionId(session_id)) {
|
|
527
|
+
return EXIT_ALLOW;
|
|
528
|
+
}
|
|
529
|
+
return _withToolWriteLock(consumer_root, session_id, EXIT_ALLOW, () => {
|
|
530
|
+
const previous = _loadState(path.join(consumer_root, statePathFor2(session_id)));
|
|
531
|
+
const language = previous.language;
|
|
532
|
+
if (language !== "de" && language !== "en") {
|
|
533
|
+
return EXIT_ALLOW;
|
|
534
|
+
}
|
|
535
|
+
if (!_ownsPin(previous, session_id)) {
|
|
536
|
+
return EXIT_ALLOW;
|
|
537
|
+
}
|
|
538
|
+
const seen = typeof previous.tool_calls_since_pin === "number" && previous.tool_calls_since_pin >= 0 ? previous.tool_calls_since_pin : 0;
|
|
539
|
+
const advanced = seen + 1;
|
|
540
|
+
const due = advanced >= REEMIT_AFTER_TOOL_CALLS;
|
|
541
|
+
const written = _writeDistance(
|
|
542
|
+
consumer_root,
|
|
543
|
+
previous,
|
|
544
|
+
session_id,
|
|
545
|
+
due ? 0 : advanced,
|
|
546
|
+
write_json
|
|
547
|
+
);
|
|
548
|
+
if (!due) {
|
|
549
|
+
return EXIT_ALLOW;
|
|
550
|
+
}
|
|
551
|
+
if (!written) {
|
|
552
|
+
return EXIT_ALLOW;
|
|
553
|
+
}
|
|
554
|
+
const source = previous.source === "system-locale" ? "system-locale" : "prompt";
|
|
555
|
+
process.stdout.write(
|
|
556
|
+
`${JSON.stringify({
|
|
557
|
+
decision: "warn",
|
|
558
|
+
reason: noticeText(language, source),
|
|
559
|
+
additional_context: pinText(language, source)
|
|
560
|
+
})}
|
|
561
|
+
`
|
|
562
|
+
);
|
|
563
|
+
return EXIT_WARN;
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
function _onToolUse(consumer_root, session_id, write_json = atomic_write_json) {
|
|
567
|
+
if (_pinLost(consumer_root, session_id)) {
|
|
568
|
+
return _reEmitAfterCompaction(consumer_root, session_id, write_json);
|
|
569
|
+
}
|
|
570
|
+
return _reEmitAfterDistance(consumer_root, session_id, write_json);
|
|
407
571
|
}
|
|
408
572
|
function run(stdin_text, options) {
|
|
409
573
|
let envelope = {};
|
|
@@ -424,7 +588,7 @@ function run(stdin_text, options) {
|
|
|
424
588
|
return EXIT_ALLOW;
|
|
425
589
|
}
|
|
426
590
|
if (event === "post_tool_use") {
|
|
427
|
-
return
|
|
591
|
+
return _onToolUse(options.consumer_root, _sessionId(envelope), options.write_json);
|
|
428
592
|
}
|
|
429
593
|
const prompt = _extractPrompt(payload);
|
|
430
594
|
if (!prompt) {
|
|
@@ -434,8 +598,9 @@ function run(stdin_text, options) {
|
|
|
434
598
|
return EXIT_ALLOW;
|
|
435
599
|
}
|
|
436
600
|
const session_id = typeof envelope["session_id"] === "string" ? envelope["session_id"] : "";
|
|
437
|
-
const
|
|
438
|
-
const
|
|
601
|
+
const stateful = hasStableSessionId(session_id);
|
|
602
|
+
const target = stateful ? path.join(options.consumer_root, statePathFor2(session_id)) : "";
|
|
603
|
+
const previous = stateful ? _loadState(target) : {};
|
|
439
604
|
const classification = classify(prompt);
|
|
440
605
|
const next = nextState(
|
|
441
606
|
previous,
|
|
@@ -448,11 +613,14 @@ function run(stdin_text, options) {
|
|
|
448
613
|
// test that passes here and fails in CI for reasons unrelated to the diff.
|
|
449
614
|
systemLocaleVerdict(options.env ?? process.env)
|
|
450
615
|
);
|
|
451
|
-
const
|
|
616
|
+
const inherited = _ownsPin(previous, session_id) ? previous.language : void 0;
|
|
617
|
+
const effective = next?.language ?? inherited;
|
|
452
618
|
const effectiveSource = next?.source ?? (previous.source === "system-locale" ? "system-locale" : "prompt");
|
|
453
|
-
if (next) {
|
|
619
|
+
if (next && stateful) {
|
|
454
620
|
try {
|
|
455
621
|
atomic_write_json(target, next);
|
|
622
|
+
_pruneLegacyState(options.consumer_root);
|
|
623
|
+
_pruneStaleSessions(options.consumer_root, Date.now());
|
|
456
624
|
} catch {
|
|
457
625
|
}
|
|
458
626
|
}
|
|
@@ -508,7 +676,7 @@ import path2 from "node:path";
|
|
|
508
676
|
import { fileURLToPath as fileURLToPath2, pathToFileURL as pathToFileURL2 } from "node:url";
|
|
509
677
|
var EXIT_ALLOW2 = 0;
|
|
510
678
|
var STATE_FILE2 = path2.join("agents", "state", "git-authorization.json");
|
|
511
|
-
var
|
|
679
|
+
var STATE_DIR2 = path2.join("agents", "state", "git-authorization");
|
|
512
680
|
var PENDING_DIR = path2.join("agents", "state", "git-authorization-pending");
|
|
513
681
|
function sessionSlug(session_id) {
|
|
514
682
|
return session_id.replace(/[^A-Za-z0-9._-]/gu, "_").slice(0, 80);
|
|
@@ -517,7 +685,7 @@ function ledgerFileFor(session_id) {
|
|
|
517
685
|
if (!session_id) {
|
|
518
686
|
return STATE_FILE2;
|
|
519
687
|
}
|
|
520
|
-
return path2.join(
|
|
688
|
+
return path2.join(STATE_DIR2, `${sessionSlug(session_id)}.json`);
|
|
521
689
|
}
|
|
522
690
|
function pendingFileFor(session_id) {
|
|
523
691
|
if (!session_id) {
|
|
@@ -994,7 +1162,7 @@ function commandOp(command) {
|
|
|
994
1162
|
}
|
|
995
1163
|
return found;
|
|
996
1164
|
}
|
|
997
|
-
var LEDGER_MAX_AGE_MS =
|
|
1165
|
+
var LEDGER_MAX_AGE_MS = 6 * 60 * 60 * 1e3;
|
|
998
1166
|
function _loadLedger(consumer_root, session_id, now) {
|
|
999
1167
|
const candidates = [ledgerFileFor(session_id)];
|
|
1000
1168
|
if (!candidates.includes(STATE_FILE2)) {
|
|
@@ -1127,338 +1295,18 @@ if (_isCliEntry3()) {
|
|
|
1127
1295
|
process.exit(main3());
|
|
1128
1296
|
}
|
|
1129
1297
|
|
|
1130
|
-
// src/scripts/before_complete_hook.ts
|
|
1131
|
-
import fs4 from "node:fs";
|
|
1132
|
-
import path4 from "node:path";
|
|
1133
|
-
import { fileURLToPath as fileURLToPath4, pathToFileURL as pathToFileURL4 } from "node:url";
|
|
1134
|
-
var STATE_FILE3 = path4.join("agents", "state", "verify-before-complete.json");
|
|
1135
|
-
var COMMAND_TOOLS2 = /* @__PURE__ */ new Set([
|
|
1136
|
-
"launch-process",
|
|
1137
|
-
"launch_process",
|
|
1138
|
-
// Augment
|
|
1139
|
-
"Bash",
|
|
1140
|
-
"BashTool",
|
|
1141
|
-
// Claude Code
|
|
1142
|
-
"run-process",
|
|
1143
|
-
"runProcess",
|
|
1144
|
-
// variants
|
|
1145
|
-
"shell",
|
|
1146
|
-
"execute_shell",
|
|
1147
|
-
// generic / Cline
|
|
1148
|
-
"RunShellCommand"
|
|
1149
|
-
// Cursor
|
|
1150
|
-
]);
|
|
1151
|
-
var _VERIFICATION_RE = new RegExp(
|
|
1152
|
-
"(?:^|[\\s;&|`(])(task\\s+(?:ci|test|tests|lint|check|qa|phpstan|rector|ecs|pest|pytest)|(?:\\./|\\.venv/bin/|vendor/bin/)?(?:pest|phpunit|phpstan|psalm|rector|ecs)\\b|(?:python3?|\\.venv/bin/python3?)\\s+-m\\s+pytest|pytest\\b|(?:npm|pnpm|yarn|bun)\\s+(?:run\\s+)?(?:test|check|lint|typecheck|tsc)|cargo\\s+(?:test|check|clippy)|go\\s+test|make\\s+(?:test|check|lint)|composer\\s+(?:test|check|lint|phpstan)|(?:php\\s+)?artisan\\s+test)",
|
|
1153
|
-
"i"
|
|
1154
|
-
);
|
|
1155
|
-
function _now() {
|
|
1156
|
-
return (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "+00:00");
|
|
1157
|
-
}
|
|
1158
|
-
function _empty_state() {
|
|
1159
|
-
return {
|
|
1160
|
-
schema_version: 1,
|
|
1161
|
-
session_id: "",
|
|
1162
|
-
turn_started_at: null,
|
|
1163
|
-
last_verification: null,
|
|
1164
|
-
verifications_this_turn: 0,
|
|
1165
|
-
verifications_this_session: 0,
|
|
1166
|
-
last_stop_at: null,
|
|
1167
|
-
verified_this_turn: false,
|
|
1168
|
-
ci_saw_pending: false,
|
|
1169
|
-
nonevidence_this_turn: 0,
|
|
1170
|
-
// Round 7 § Phase 1 — the last CI read, SESSION-scoped on purpose. Every
|
|
1171
|
-
// other counter here is turn-scoped because a stale POSITIVE would wrongly
|
|
1172
|
-
// vouch ("I verified"). This one is a NEGATIVE ("CI was not settled"), and a
|
|
1173
|
-
// stale negative only ever refuses more often — so surviving the turn
|
|
1174
|
-
// boundary preserves the freshness invariant rather than bypassing it. It
|
|
1175
|
-
// has to survive it: the measured failure is a completion claim in a LATER
|
|
1176
|
-
// turn than the poll it rests on.
|
|
1177
|
-
ci_last: null,
|
|
1178
|
-
checked_at: _now()
|
|
1179
|
-
};
|
|
1180
|
-
}
|
|
1181
|
-
function _load_state(target) {
|
|
1182
|
-
let isFile = false;
|
|
1183
|
-
try {
|
|
1184
|
-
isFile = fs4.statSync(target).isFile();
|
|
1185
|
-
} catch {
|
|
1186
|
-
isFile = false;
|
|
1187
|
-
}
|
|
1188
|
-
if (!isFile) {
|
|
1189
|
-
return _empty_state();
|
|
1190
|
-
}
|
|
1191
|
-
try {
|
|
1192
|
-
const decoded = JSON.parse(fs4.readFileSync(target, "utf-8"));
|
|
1193
|
-
if (typeof decoded === "object" && decoded !== null && !Array.isArray(decoded)) {
|
|
1194
|
-
return { ..._empty_state(), ...decoded };
|
|
1195
|
-
}
|
|
1196
|
-
} catch {
|
|
1197
|
-
}
|
|
1198
|
-
return _empty_state();
|
|
1199
|
-
}
|
|
1200
|
-
function _extract_command(payload) {
|
|
1201
|
-
const toolRaw = payload["tool_name"] || payload["toolName"] || payload["tool"];
|
|
1202
|
-
if (!(typeof toolRaw === "string" && COMMAND_TOOLS2.has(toolRaw))) {
|
|
1203
|
-
return [typeof toolRaw === "string" ? toolRaw : null, null];
|
|
1204
|
-
}
|
|
1205
|
-
const tool = toolRaw;
|
|
1206
|
-
const ti = payload["tool_input"];
|
|
1207
|
-
if (typeof ti === "object" && ti !== null && !Array.isArray(ti)) {
|
|
1208
|
-
for (const key of ["command", "cmd", "shell_command"]) {
|
|
1209
|
-
const v = ti[key];
|
|
1210
|
-
if (typeof v === "string" && v) {
|
|
1211
|
-
return [tool, v];
|
|
1212
|
-
}
|
|
1213
|
-
}
|
|
1214
|
-
}
|
|
1215
|
-
for (const key of ["command", "cmd"]) {
|
|
1216
|
-
const v = payload[key];
|
|
1217
|
-
if (typeof v === "string" && v) {
|
|
1218
|
-
return [tool, v];
|
|
1219
|
-
}
|
|
1220
|
-
}
|
|
1221
|
-
return [tool, null];
|
|
1222
|
-
}
|
|
1223
|
-
function _is_verification(command) {
|
|
1224
|
-
return _VERIFICATION_RE.test(command) || isCiPoll(command);
|
|
1225
|
-
}
|
|
1226
|
-
var _VACUOUS_PATTERNS = [
|
|
1227
|
-
// gh pr checks / gh run — no checks registered at all.
|
|
1228
|
-
/\b0\s+(?:checks?|runs?)\b/i,
|
|
1229
|
-
// Test runners reporting an empty run.
|
|
1230
|
-
/\bno tests? (?:ran|found|to run|were run)\b/i,
|
|
1231
|
-
/\bNo test files found\b/i,
|
|
1232
|
-
/\b0\s+pass(?:ed|ing)?\b[\s,|·]*\b0\s+fail(?:ed|ing|ures)?\b/i,
|
|
1233
|
-
/\bTests?\s+0\s+passed\b/i,
|
|
1234
|
-
/\bRan 0 tests?\b/i,
|
|
1235
|
-
// Linters / scanners with an empty target set.
|
|
1236
|
-
/\bno files? (?:matched|to (?:lint|check|scan)|found)\b/i,
|
|
1237
|
-
/\b0\s+files?\s+(?:checked|scanned|linted)\b/i,
|
|
1238
|
-
/\bnothing to check\b/i
|
|
1239
|
-
];
|
|
1240
|
-
function isVacuousOutput(output) {
|
|
1241
|
-
const text = output.trim();
|
|
1242
|
-
if (!text) {
|
|
1243
|
-
return false;
|
|
1244
|
-
}
|
|
1245
|
-
const lines = text.split("\n").filter((l) => l.trim());
|
|
1246
|
-
return lines.every((l) => _VACUOUS_PATTERNS.some((re) => re.test(l)));
|
|
1247
|
-
}
|
|
1248
|
-
var _CI_POLL_RE = /\bgh\s+(?:pr\s+checks|run\s+(?:watch|list|view))\b/i;
|
|
1249
|
-
function isCiPoll(command) {
|
|
1250
|
-
return _CI_POLL_RE.test(command);
|
|
1251
|
-
}
|
|
1252
|
-
function pendingCount(output) {
|
|
1253
|
-
const m = /(\d+)\s+(?:checks? )?pending\b/i.exec(output) ?? /\bpending[:=]\s*(\d+)/i.exec(output);
|
|
1254
|
-
if (m?.[1] !== void 0) {
|
|
1255
|
-
return Number(m[1]);
|
|
1256
|
-
}
|
|
1257
|
-
const rows = output.match(/^\S.*\b(pending|in_progress|queued)\b/gim);
|
|
1258
|
-
if (rows) {
|
|
1259
|
-
return rows.length;
|
|
1260
|
-
}
|
|
1261
|
-
if (/\bno checks reported\b/i.test(output)) {
|
|
1262
|
-
return null;
|
|
1263
|
-
}
|
|
1264
|
-
if (/^\S+\s+(pass|fail|skipping|successful|failing)\b/im.test(output)) {
|
|
1265
|
-
return 0;
|
|
1266
|
-
}
|
|
1267
|
-
return null;
|
|
1268
|
-
}
|
|
1269
|
-
function _extract_output(payload) {
|
|
1270
|
-
for (const key of ["tool_response", "toolResponse", "output", "stdout", "result"]) {
|
|
1271
|
-
const v = payload[key];
|
|
1272
|
-
if (typeof v === "string") {
|
|
1273
|
-
return v;
|
|
1274
|
-
}
|
|
1275
|
-
if (v !== null && typeof v === "object") {
|
|
1276
|
-
return JSON.stringify(v);
|
|
1277
|
-
}
|
|
1278
|
-
}
|
|
1279
|
-
return null;
|
|
1280
|
-
}
|
|
1281
|
-
function _reset_turn(state, session_id) {
|
|
1282
|
-
state["session_id"] = session_id || state["session_id"] || "";
|
|
1283
|
-
state["turn_started_at"] = _now();
|
|
1284
|
-
state["verifications_this_turn"] = 0;
|
|
1285
|
-
state["verified_this_turn"] = false;
|
|
1286
|
-
state["ci_saw_pending"] = false;
|
|
1287
|
-
state["nonevidence_this_turn"] = 0;
|
|
1288
|
-
return state;
|
|
1289
|
-
}
|
|
1290
|
-
function _asInt(v) {
|
|
1291
|
-
if (!v) {
|
|
1292
|
-
return 0;
|
|
1293
|
-
}
|
|
1294
|
-
if (typeof v === "number") {
|
|
1295
|
-
return Math.trunc(v);
|
|
1296
|
-
}
|
|
1297
|
-
const n = Number(v);
|
|
1298
|
-
return Number.isFinite(n) ? Math.trunc(n) : 0;
|
|
1299
|
-
}
|
|
1300
|
-
function _update(state, event, envelope) {
|
|
1301
|
-
const session_id = envelope["session_id"] || state["session_id"] || "";
|
|
1302
|
-
if (session_id && session_id !== state["session_id"]) {
|
|
1303
|
-
state["session_id"] = session_id;
|
|
1304
|
-
state["verifications_this_session"] = 0;
|
|
1305
|
-
state["ci_last"] = null;
|
|
1306
|
-
state = _reset_turn(state, session_id);
|
|
1307
|
-
}
|
|
1308
|
-
let payload = envelope["payload"];
|
|
1309
|
-
if (!(typeof payload === "object" && payload !== null && !Array.isArray(payload))) {
|
|
1310
|
-
payload = {};
|
|
1311
|
-
}
|
|
1312
|
-
const pl = payload;
|
|
1313
|
-
if (event === "session_start" || event === "user_prompt_submit") {
|
|
1314
|
-
state = _reset_turn(state, session_id);
|
|
1315
|
-
} else if (event === "post_tool_use") {
|
|
1316
|
-
const [tool, cmd] = _extract_command(pl);
|
|
1317
|
-
if (cmd && _is_verification(cmd)) {
|
|
1318
|
-
const output = _extract_output(pl);
|
|
1319
|
-
const vacuous = output !== null && isVacuousOutput(output);
|
|
1320
|
-
let counts = !vacuous;
|
|
1321
|
-
if (isCiPoll(cmd)) {
|
|
1322
|
-
const pending = output === null ? null : pendingCount(output);
|
|
1323
|
-
if (pending !== null && pending > 0) {
|
|
1324
|
-
state["ci_saw_pending"] = true;
|
|
1325
|
-
counts = false;
|
|
1326
|
-
} else if (pending === 0) {
|
|
1327
|
-
counts = !vacuous && state["ci_saw_pending"] === true;
|
|
1328
|
-
} else {
|
|
1329
|
-
counts = false;
|
|
1330
|
-
}
|
|
1331
|
-
state["ci_last"] = {
|
|
1332
|
-
at: _now(),
|
|
1333
|
-
command: cmd.slice(0, 512),
|
|
1334
|
-
pending,
|
|
1335
|
-
settled: pending === 0 && counts === true
|
|
1336
|
-
};
|
|
1337
|
-
}
|
|
1338
|
-
state["last_verification"] = {
|
|
1339
|
-
command: cmd.slice(0, 512),
|
|
1340
|
-
tool,
|
|
1341
|
-
at: _now(),
|
|
1342
|
-
platform: envelope["platform"] || "",
|
|
1343
|
-
vacuous,
|
|
1344
|
-
counted: counts
|
|
1345
|
-
};
|
|
1346
|
-
if (counts) {
|
|
1347
|
-
state["verifications_this_turn"] = _asInt(state["verifications_this_turn"]) + 1;
|
|
1348
|
-
state["verifications_this_session"] = _asInt(state["verifications_this_session"]) + 1;
|
|
1349
|
-
state["verified_this_turn"] = true;
|
|
1350
|
-
} else {
|
|
1351
|
-
state["nonevidence_this_turn"] = _asInt(state["nonevidence_this_turn"]) + 1;
|
|
1352
|
-
}
|
|
1353
|
-
}
|
|
1354
|
-
} else if (event === "stop") {
|
|
1355
|
-
state["last_stop_at"] = _now();
|
|
1356
|
-
}
|
|
1357
|
-
state["checked_at"] = _now();
|
|
1358
|
-
return state;
|
|
1359
|
-
}
|
|
1360
|
-
function run4(stdin_text, options) {
|
|
1361
|
-
const { consumer_root } = options;
|
|
1362
|
-
const verbose = options.verbose ?? false;
|
|
1363
|
-
let envelope = {};
|
|
1364
|
-
if (stdin_text.trim()) {
|
|
1365
|
-
try {
|
|
1366
|
-
const decoded = JSON.parse(stdin_text);
|
|
1367
|
-
if (typeof decoded === "object" && decoded !== null && !Array.isArray(decoded)) {
|
|
1368
|
-
envelope = decoded;
|
|
1369
|
-
}
|
|
1370
|
-
} catch {
|
|
1371
|
-
envelope = {};
|
|
1372
|
-
}
|
|
1373
|
-
}
|
|
1374
|
-
const event = envelope["event"] || "";
|
|
1375
|
-
const target = path4.join(consumer_root, STATE_FILE3);
|
|
1376
|
-
let state = _load_state(target);
|
|
1377
|
-
state = _update(state, event, envelope);
|
|
1378
|
-
try {
|
|
1379
|
-
atomic_write_json(target, state);
|
|
1380
|
-
} catch {
|
|
1381
|
-
if (verbose) {
|
|
1382
|
-
process.stderr.write("verify-before-complete-hook: state write failed\n");
|
|
1383
|
-
}
|
|
1384
|
-
return 0;
|
|
1385
|
-
}
|
|
1386
|
-
if (verbose) {
|
|
1387
|
-
process.stderr.write(
|
|
1388
|
-
`verify-before-complete-hook: event=${event} verified_this_turn=${pyRepr(state["verified_this_turn"])} verifications_this_turn=${pyRepr(state["verifications_this_turn"])}
|
|
1389
|
-
`
|
|
1390
|
-
);
|
|
1391
|
-
}
|
|
1392
|
-
return 0;
|
|
1393
|
-
}
|
|
1394
|
-
function pyRepr(value) {
|
|
1395
|
-
if (value === null || value === void 0) {
|
|
1396
|
-
return "None";
|
|
1397
|
-
}
|
|
1398
|
-
if (typeof value === "boolean") {
|
|
1399
|
-
return value ? "True" : "False";
|
|
1400
|
-
}
|
|
1401
|
-
return String(value);
|
|
1402
|
-
}
|
|
1403
|
-
function parse_args(argv) {
|
|
1404
|
-
let platform = "generic";
|
|
1405
|
-
let verbose = false;
|
|
1406
|
-
for (let i = 0; i < argv.length; i += 1) {
|
|
1407
|
-
const arg = argv[i];
|
|
1408
|
-
if (arg === "--platform") {
|
|
1409
|
-
platform = argv[i + 1] ?? "generic";
|
|
1410
|
-
i += 1;
|
|
1411
|
-
} else if (arg !== void 0 && arg.startsWith("--platform=")) {
|
|
1412
|
-
platform = arg.slice("--platform=".length);
|
|
1413
|
-
} else if (arg === "--verbose") {
|
|
1414
|
-
verbose = true;
|
|
1415
|
-
}
|
|
1416
|
-
}
|
|
1417
|
-
return { platform, verbose };
|
|
1418
|
-
}
|
|
1419
|
-
function _readStdin() {
|
|
1420
|
-
return readHookStdin();
|
|
1421
|
-
}
|
|
1422
|
-
function main4(argv) {
|
|
1423
|
-
const args = parse_args(argv ?? process.argv.slice(2));
|
|
1424
|
-
return run4(_readStdin(), { consumer_root: process.cwd(), verbose: args.verbose });
|
|
1425
|
-
}
|
|
1426
|
-
function _isCliEntry4() {
|
|
1427
|
-
if (true) {
|
|
1428
|
-
return false;
|
|
1429
|
-
}
|
|
1430
|
-
if (process.argv[1] === void 0) {
|
|
1431
|
-
return false;
|
|
1432
|
-
}
|
|
1433
|
-
const argvUrl = pathToFileURL4(path4.resolve(process.argv[1])).href;
|
|
1434
|
-
if (import.meta.url === argvUrl) {
|
|
1435
|
-
return true;
|
|
1436
|
-
}
|
|
1437
|
-
try {
|
|
1438
|
-
const here = fs4.realpathSync(fileURLToPath4(import.meta.url));
|
|
1439
|
-
const argv = fs4.realpathSync(path4.resolve(process.argv[1]));
|
|
1440
|
-
return here === argv;
|
|
1441
|
-
} catch {
|
|
1442
|
-
return false;
|
|
1443
|
-
}
|
|
1444
|
-
}
|
|
1445
|
-
var isCliEntry = _isCliEntry4();
|
|
1446
|
-
if (isCliEntry) {
|
|
1447
|
-
process.exit(main4(process.argv.slice(2)));
|
|
1448
|
-
}
|
|
1449
|
-
|
|
1450
1298
|
// src/scripts/hooks/turn_end_gate_hook.ts
|
|
1451
|
-
import * as
|
|
1452
|
-
import * as
|
|
1453
|
-
import { fileURLToPath as
|
|
1299
|
+
import * as fs6 from "node:fs";
|
|
1300
|
+
import * as path6 from "node:path";
|
|
1301
|
+
import { fileURLToPath as fileURLToPath6, pathToFileURL as pathToFileURL6 } from "node:url";
|
|
1454
1302
|
|
|
1455
1303
|
// src/scripts/hooks/end_review_nudge_hook.ts
|
|
1456
1304
|
import { spawnSync } from "node:child_process";
|
|
1457
1305
|
import * as crypto from "node:crypto";
|
|
1458
|
-
import * as
|
|
1306
|
+
import * as fs4 from "node:fs";
|
|
1459
1307
|
import * as os from "node:os";
|
|
1460
|
-
import * as
|
|
1461
|
-
import { fileURLToPath as
|
|
1308
|
+
import * as path4 from "node:path";
|
|
1309
|
+
import { fileURLToPath as fileURLToPath4, pathToFileURL as pathToFileURL4 } from "node:url";
|
|
1462
1310
|
|
|
1463
1311
|
// src/scripts/_lib/review_skipped_record.ts
|
|
1464
1312
|
function isNonNegInt(n) {
|
|
@@ -1559,13 +1407,13 @@ function isSafeTranscriptPath(rawPath, opts = {}) {
|
|
|
1559
1407
|
const homeDir = opts.homeDir ?? os.homedir();
|
|
1560
1408
|
const maxBytes = opts.maxBytes ?? TRANSCRIPT_SCAN_MAX_BYTES;
|
|
1561
1409
|
try {
|
|
1562
|
-
const realHome =
|
|
1563
|
-
const realPath =
|
|
1564
|
-
const relative2 =
|
|
1565
|
-
if (relative2 === "" || relative2.startsWith("..") ||
|
|
1410
|
+
const realHome = fs4.realpathSync(homeDir);
|
|
1411
|
+
const realPath = fs4.realpathSync(rawPath);
|
|
1412
|
+
const relative2 = path4.relative(realHome, realPath);
|
|
1413
|
+
if (relative2 === "" || relative2.startsWith("..") || path4.isAbsolute(relative2)) {
|
|
1566
1414
|
return false;
|
|
1567
1415
|
}
|
|
1568
|
-
const { size } =
|
|
1416
|
+
const { size } = fs4.statSync(realPath);
|
|
1569
1417
|
return size <= maxBytes;
|
|
1570
1418
|
} catch {
|
|
1571
1419
|
return false;
|
|
@@ -1624,13 +1472,13 @@ var BINARY_PROBE_BYTES = 8e3;
|
|
|
1624
1472
|
var UNTRACKED_FILE_READ_CAP_BYTES = 8 * 1024 * 1024;
|
|
1625
1473
|
function untrackedFileLineCount(cwd, relPath) {
|
|
1626
1474
|
try {
|
|
1627
|
-
const abs =
|
|
1628
|
-
const size =
|
|
1475
|
+
const abs = path4.resolve(cwd, relPath);
|
|
1476
|
+
const size = fs4.statSync(abs).size;
|
|
1629
1477
|
if (size === 0) return 0;
|
|
1630
1478
|
if (size > UNTRACKED_FILE_READ_CAP_BYTES) {
|
|
1631
1479
|
return MUTATION_LINE_THRESHOLD + 1;
|
|
1632
1480
|
}
|
|
1633
|
-
const buf =
|
|
1481
|
+
const buf = fs4.readFileSync(abs);
|
|
1634
1482
|
if (buf.length === 0) return 0;
|
|
1635
1483
|
const probe = buf.subarray(0, Math.min(buf.length, BINARY_PROBE_BYTES));
|
|
1636
1484
|
if (probe.includes(0)) return 0;
|
|
@@ -1720,28 +1568,28 @@ function appendReviewSkippedTelemetry(workspaceRoot, diffLines, mutationMeasure)
|
|
|
1720
1568
|
});
|
|
1721
1569
|
if (errors.length || line === null) return;
|
|
1722
1570
|
try {
|
|
1723
|
-
const dir =
|
|
1724
|
-
|
|
1725
|
-
const file =
|
|
1726
|
-
|
|
1571
|
+
const dir = path4.join(workspaceRoot, "agents", "runtime", "state", "audit");
|
|
1572
|
+
fs4.mkdirSync(dir, { recursive: true });
|
|
1573
|
+
const file = path4.join(dir, `${ts.slice(0, 7)}.jsonl`);
|
|
1574
|
+
fs4.appendFileSync(file, `${JSON.stringify(line)}
|
|
1727
1575
|
`, "utf8");
|
|
1728
1576
|
} catch {
|
|
1729
1577
|
}
|
|
1730
1578
|
}
|
|
1731
1579
|
function sessionStateDir(workspaceRoot) {
|
|
1732
|
-
return
|
|
1580
|
+
return path4.join(workspaceRoot, "agents", "runtime", "state", "end-review-nudge");
|
|
1733
1581
|
}
|
|
1734
1582
|
function sessionStateFile(workspaceRoot, sessionKey) {
|
|
1735
|
-
return
|
|
1583
|
+
return path4.join(sessionStateDir(workspaceRoot), `${sessionKey}.json`);
|
|
1736
1584
|
}
|
|
1737
|
-
function
|
|
1585
|
+
function deriveSessionKey2(envelope, payload) {
|
|
1738
1586
|
const raw = str(envelope["session_id"]) || str(payload["transcript_path"] ?? payload["transcriptPath"]);
|
|
1739
1587
|
const material = raw || "unknown-session";
|
|
1740
1588
|
return crypto.createHash("sha256").update(material).digest("hex");
|
|
1741
1589
|
}
|
|
1742
1590
|
function hasFiredThisSession(workspaceRoot, sessionKey) {
|
|
1743
1591
|
try {
|
|
1744
|
-
return
|
|
1592
|
+
return fs4.existsSync(sessionStateFile(workspaceRoot, sessionKey));
|
|
1745
1593
|
} catch {
|
|
1746
1594
|
return false;
|
|
1747
1595
|
}
|
|
@@ -1755,7 +1603,7 @@ function markFiredThisSession(workspaceRoot, sessionKey, ts) {
|
|
|
1755
1603
|
function _read_stdin() {
|
|
1756
1604
|
return readHookStdin();
|
|
1757
1605
|
}
|
|
1758
|
-
function
|
|
1606
|
+
function main4() {
|
|
1759
1607
|
const [envelope, payload] = unwrap(_read_stdin(), "claude");
|
|
1760
1608
|
const event = String(envelope["event"] ?? "");
|
|
1761
1609
|
if (event !== "" && event !== "stop") {
|
|
@@ -1774,7 +1622,7 @@ function main5() {
|
|
|
1774
1622
|
if (diffLines <= MUTATION_LINE_THRESHOLD) {
|
|
1775
1623
|
return 0;
|
|
1776
1624
|
}
|
|
1777
|
-
const sessionKey =
|
|
1625
|
+
const sessionKey = deriveSessionKey2(envelope, payload);
|
|
1778
1626
|
if (hasFiredThisSession(workspace_root, sessionKey)) {
|
|
1779
1627
|
return 0;
|
|
1780
1628
|
}
|
|
@@ -1784,7 +1632,7 @@ function main5() {
|
|
|
1784
1632
|
let reviewerRan = false;
|
|
1785
1633
|
if (transcriptPath && isSafeTranscriptPath(transcriptPath)) {
|
|
1786
1634
|
try {
|
|
1787
|
-
reviewerRan = scanTranscriptForReviewer(
|
|
1635
|
+
reviewerRan = scanTranscriptForReviewer(fs4.readFileSync(transcriptPath, "utf-8"));
|
|
1788
1636
|
} catch {
|
|
1789
1637
|
reviewerRan = false;
|
|
1790
1638
|
}
|
|
@@ -1807,34 +1655,34 @@ function main5() {
|
|
|
1807
1655
|
);
|
|
1808
1656
|
return EXIT_WARN2;
|
|
1809
1657
|
}
|
|
1810
|
-
function
|
|
1658
|
+
function _isCliEntry4() {
|
|
1811
1659
|
if (true) {
|
|
1812
1660
|
return false;
|
|
1813
1661
|
}
|
|
1814
1662
|
if (process.argv[1] === void 0) {
|
|
1815
1663
|
return false;
|
|
1816
1664
|
}
|
|
1817
|
-
const argvUrl =
|
|
1665
|
+
const argvUrl = pathToFileURL4(path4.resolve(process.argv[1])).href;
|
|
1818
1666
|
if (import.meta.url === argvUrl) {
|
|
1819
1667
|
return true;
|
|
1820
1668
|
}
|
|
1821
1669
|
try {
|
|
1822
|
-
const here =
|
|
1823
|
-
const argv =
|
|
1670
|
+
const here = fs4.realpathSync(fileURLToPath4(import.meta.url));
|
|
1671
|
+
const argv = fs4.realpathSync(path4.resolve(process.argv[1]));
|
|
1824
1672
|
return here === argv;
|
|
1825
1673
|
} catch {
|
|
1826
1674
|
return false;
|
|
1827
1675
|
}
|
|
1828
1676
|
}
|
|
1829
|
-
if (
|
|
1830
|
-
process.exit(
|
|
1677
|
+
if (_isCliEntry4()) {
|
|
1678
|
+
process.exit(main4());
|
|
1831
1679
|
}
|
|
1832
1680
|
|
|
1833
1681
|
// src/scripts/hooks/subagent_ledger_hook.ts
|
|
1834
1682
|
import * as crypto2 from "node:crypto";
|
|
1835
|
-
import * as
|
|
1836
|
-
import * as
|
|
1837
|
-
import { fileURLToPath as
|
|
1683
|
+
import * as fs5 from "node:fs";
|
|
1684
|
+
import * as path5 from "node:path";
|
|
1685
|
+
import { fileURLToPath as fileURLToPath5, pathToFileURL as pathToFileURL5 } from "node:url";
|
|
1838
1686
|
|
|
1839
1687
|
// src/scripts/_lib/subagent_response.ts
|
|
1840
1688
|
var MAX_SUMMARY_CHARS = 2e3;
|
|
@@ -1928,7 +1776,7 @@ var EXIT_ALLOW4 = 0;
|
|
|
1928
1776
|
function isObject2(v) {
|
|
1929
1777
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
1930
1778
|
}
|
|
1931
|
-
var LEDGER_DIR =
|
|
1779
|
+
var LEDGER_DIR = path5.join("agents", "runtime", "state", "subagent-ledger");
|
|
1932
1780
|
var OPEN_SUBDIR = "open";
|
|
1933
1781
|
var OPEN_RECORD_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
1934
1782
|
function refFor(agentId) {
|
|
@@ -1956,16 +1804,16 @@ function extractParentId(payload, ownId) {
|
|
|
1956
1804
|
return null;
|
|
1957
1805
|
}
|
|
1958
1806
|
function classifyEnvelope(message) {
|
|
1959
|
-
if (message === null || !message.trim()) return { verdict: "
|
|
1807
|
+
if (message === null || !message.trim()) return { verdict: "no_message", error_count: 0 };
|
|
1960
1808
|
const candidates = _jsonObjectCandidates(message);
|
|
1961
|
-
if (candidates.length === 0) return { verdict: "
|
|
1809
|
+
if (candidates.length === 0) return { verdict: "no_envelope", error_count: 0 };
|
|
1962
1810
|
let best = null;
|
|
1963
1811
|
for (const candidate of candidates) {
|
|
1964
1812
|
const result = validateResponse(candidate);
|
|
1965
1813
|
if (result.valid) return { verdict: "ok", error_count: 0 };
|
|
1966
1814
|
if (best === null) best = { verdict: "fail", error_count: result.errors.length };
|
|
1967
1815
|
}
|
|
1968
|
-
return best ?? { verdict: "
|
|
1816
|
+
return best ?? { verdict: "no_envelope", error_count: 0 };
|
|
1969
1817
|
}
|
|
1970
1818
|
function _jsonObjectCandidates(message) {
|
|
1971
1819
|
const texts = [];
|
|
@@ -2009,10 +1857,10 @@ function _jsonObjectCandidates(message) {
|
|
|
2009
1857
|
return out;
|
|
2010
1858
|
}
|
|
2011
1859
|
function openDir(root) {
|
|
2012
|
-
return
|
|
1860
|
+
return path5.join(root, LEDGER_DIR, OPEN_SUBDIR);
|
|
2013
1861
|
}
|
|
2014
1862
|
function openFile(root, ref) {
|
|
2015
|
-
return
|
|
1863
|
+
return path5.join(openDir(root), `${ref}.json`);
|
|
2016
1864
|
}
|
|
2017
1865
|
var DEPTH_BASES = /* @__PURE__ */ new Set(["observed", "asserted-parent", "assumed-root"]);
|
|
2018
1866
|
function _asOpenRecord(value, expectedRef) {
|
|
@@ -2039,7 +1887,7 @@ function readOpenRecords(root) {
|
|
|
2039
1887
|
const out = /* @__PURE__ */ new Map();
|
|
2040
1888
|
let names;
|
|
2041
1889
|
try {
|
|
2042
|
-
names =
|
|
1890
|
+
names = fs5.readdirSync(openDir(root));
|
|
2043
1891
|
} catch {
|
|
2044
1892
|
return out;
|
|
2045
1893
|
}
|
|
@@ -2047,7 +1895,7 @@ function readOpenRecords(root) {
|
|
|
2047
1895
|
if (!name.endsWith(".json")) continue;
|
|
2048
1896
|
const expectedRef = name.slice(0, -".json".length);
|
|
2049
1897
|
try {
|
|
2050
|
-
const raw =
|
|
1898
|
+
const raw = fs5.readFileSync(path5.join(openDir(root), name), "utf8");
|
|
2051
1899
|
const rec = _asOpenRecord(JSON.parse(raw), expectedRef);
|
|
2052
1900
|
if (rec) out.set(rec.ref, rec);
|
|
2053
1901
|
} catch {
|
|
@@ -2062,13 +1910,13 @@ function resolveDepth(parentRef, open) {
|
|
|
2062
1910
|
return { depth: parent.depth + 1, depth_basis: "observed" };
|
|
2063
1911
|
}
|
|
2064
1912
|
function ledgerFileFor2(root, ts) {
|
|
2065
|
-
return
|
|
1913
|
+
return path5.join(root, LEDGER_DIR, `${ts.slice(0, 7)}.jsonl`);
|
|
2066
1914
|
}
|
|
2067
1915
|
function appendLedgerLine(root, ts, line) {
|
|
2068
1916
|
if (is_replay_mode()) return;
|
|
2069
1917
|
const file = ledgerFileFor2(root, ts);
|
|
2070
|
-
|
|
2071
|
-
|
|
1918
|
+
fs5.mkdirSync(path5.dirname(file), { recursive: true });
|
|
1919
|
+
fs5.appendFileSync(file, `${JSON.stringify(line)}
|
|
2072
1920
|
`, "utf8");
|
|
2073
1921
|
}
|
|
2074
1922
|
var WALL_CLOCK_ARMS_MS = [
|
|
@@ -2082,7 +1930,7 @@ function armsExceeded(elapsedMs) {
|
|
|
2082
1930
|
return WALL_CLOCK_ARMS_MS.filter((a) => elapsedMs >= a.ms).map((a) => a.label);
|
|
2083
1931
|
}
|
|
2084
1932
|
function openRecordStats(root, nowMs = Date.now()) {
|
|
2085
|
-
const ledgerPresent =
|
|
1933
|
+
const ledgerPresent = fs5.existsSync(path5.join(root, LEDGER_DIR));
|
|
2086
1934
|
const open = readOpenRecords(root);
|
|
2087
1935
|
let maxDepth = 0;
|
|
2088
1936
|
let counted = 0;
|
|
@@ -2110,13 +1958,13 @@ function writeOpenRecord(root, rec) {
|
|
|
2110
1958
|
function removeOpenRecord(root, ref) {
|
|
2111
1959
|
if (is_replay_mode()) return;
|
|
2112
1960
|
try {
|
|
2113
|
-
|
|
1961
|
+
fs5.unlinkSync(openFile(root, ref));
|
|
2114
1962
|
} catch {
|
|
2115
1963
|
}
|
|
2116
1964
|
}
|
|
2117
1965
|
function countOpen(root) {
|
|
2118
1966
|
try {
|
|
2119
|
-
return
|
|
1967
|
+
return fs5.readdirSync(openDir(root)).filter((n) => n.endsWith(".json")).length;
|
|
2120
1968
|
} catch {
|
|
2121
1969
|
return 0;
|
|
2122
1970
|
}
|
|
@@ -2264,7 +2112,7 @@ function resolveConsumerRoot(envelope) {
|
|
|
2264
2112
|
}
|
|
2265
2113
|
return process.cwd();
|
|
2266
2114
|
}
|
|
2267
|
-
function
|
|
2115
|
+
function main5() {
|
|
2268
2116
|
const raw = readHookStdin();
|
|
2269
2117
|
let envelope = {};
|
|
2270
2118
|
try {
|
|
@@ -2274,124 +2122,20 @@ function main6() {
|
|
|
2274
2122
|
}
|
|
2275
2123
|
return processEnvelope(envelope, resolveConsumerRoot(envelope));
|
|
2276
2124
|
}
|
|
2277
|
-
function
|
|
2125
|
+
function _isCliEntry5() {
|
|
2278
2126
|
if (true) {
|
|
2279
2127
|
return false;
|
|
2280
2128
|
}
|
|
2281
2129
|
if (process.argv[1] === void 0) return false;
|
|
2282
|
-
const argvUrl =
|
|
2130
|
+
const argvUrl = pathToFileURL5(path5.resolve(process.argv[1])).href;
|
|
2283
2131
|
if (import.meta.url === argvUrl) return true;
|
|
2284
2132
|
try {
|
|
2285
|
-
return
|
|
2133
|
+
return fs5.realpathSync(fileURLToPath5(import.meta.url)) === fs5.realpathSync(path5.resolve(process.argv[1]));
|
|
2286
2134
|
} catch {
|
|
2287
2135
|
return false;
|
|
2288
2136
|
}
|
|
2289
2137
|
}
|
|
2290
|
-
if (
|
|
2291
|
-
|
|
2292
|
-
// src/scripts/_lib/turn_end_refusals.ts
|
|
2293
|
-
import * as crypto3 from "node:crypto";
|
|
2294
|
-
import * as path7 from "node:path";
|
|
2295
|
-
var DETECTOR_IDS = [
|
|
2296
|
-
"promissory",
|
|
2297
|
-
"language",
|
|
2298
|
-
"verification",
|
|
2299
|
-
"completion"
|
|
2300
|
-
];
|
|
2301
|
-
var REFUSAL_STATE_REL = path7.join("agents", "runtime", "state", "turn-end-gate");
|
|
2302
|
-
function refusalStateDir(workspaceRoot) {
|
|
2303
|
-
return path7.join(workspaceRoot, REFUSAL_STATE_REL);
|
|
2304
|
-
}
|
|
2305
|
-
function deriveSessionKey2(sessionId) {
|
|
2306
|
-
return crypto3.createHash("sha256").update(sessionId).digest("hex").slice(0, 32);
|
|
2307
|
-
}
|
|
2308
|
-
function sessionRefusalFile(workspaceRoot, sessionKey) {
|
|
2309
|
-
return path7.join(refusalStateDir(workspaceRoot), `${sessionKey}.json`);
|
|
2310
|
-
}
|
|
2311
|
-
function emptyCounts() {
|
|
2312
|
-
return { promissory: 0, language: 0, verification: 0, completion: 0 };
|
|
2313
|
-
}
|
|
2314
|
-
function isDetector(v) {
|
|
2315
|
-
return typeof v === "string" && DETECTOR_IDS.includes(v);
|
|
2316
|
-
}
|
|
2317
|
-
function parseRecord(raw) {
|
|
2318
|
-
let decoded;
|
|
2319
|
-
try {
|
|
2320
|
-
decoded = JSON.parse(raw);
|
|
2321
|
-
} catch {
|
|
2322
|
-
return null;
|
|
2323
|
-
}
|
|
2324
|
-
if (typeof decoded !== "object" || decoded === null || Array.isArray(decoded)) return null;
|
|
2325
|
-
const o = decoded;
|
|
2326
|
-
if (typeof o["refused_at"] !== "string") return null;
|
|
2327
|
-
if (typeof o["refused_turn"] !== "number") return null;
|
|
2328
|
-
if (!isDetector(o["detector"])) return null;
|
|
2329
|
-
const rec = {
|
|
2330
|
-
refused_at: o["refused_at"],
|
|
2331
|
-
refused_turn: o["refused_turn"],
|
|
2332
|
-
detector: o["detector"]
|
|
2333
|
-
};
|
|
2334
|
-
if (typeof o["first_refused_at"] === "string") rec.first_refused_at = o["first_refused_at"];
|
|
2335
|
-
if (typeof o["agent_config_version"] === "string") {
|
|
2336
|
-
rec.agent_config_version = o["agent_config_version"];
|
|
2337
|
-
}
|
|
2338
|
-
const counts = o["counts"];
|
|
2339
|
-
if (typeof counts === "object" && counts !== null && !Array.isArray(counts)) {
|
|
2340
|
-
const parsed = {};
|
|
2341
|
-
for (const id of DETECTOR_IDS) {
|
|
2342
|
-
const n = counts[id];
|
|
2343
|
-
if (typeof n === "number" && Number.isFinite(n) && n >= 0) parsed[id] = n;
|
|
2344
|
-
}
|
|
2345
|
-
rec.counts = parsed;
|
|
2346
|
-
}
|
|
2347
|
-
return rec;
|
|
2348
|
-
}
|
|
2349
|
-
function countsOf(rec) {
|
|
2350
|
-
const out = emptyCounts();
|
|
2351
|
-
if (rec.counts === void 0) {
|
|
2352
|
-
out[rec.detector] = 1;
|
|
2353
|
-
return out;
|
|
2354
|
-
}
|
|
2355
|
-
let any = false;
|
|
2356
|
-
for (const id of DETECTOR_IDS) {
|
|
2357
|
-
const n = rec.counts[id];
|
|
2358
|
-
if (typeof n === "number" && n > 0) {
|
|
2359
|
-
out[id] = n;
|
|
2360
|
-
any = true;
|
|
2361
|
-
}
|
|
2362
|
-
}
|
|
2363
|
-
if (!any) out[rec.detector] = 1;
|
|
2364
|
-
return out;
|
|
2365
|
-
}
|
|
2366
|
-
function foldRefusal(prev, input) {
|
|
2367
|
-
const counts = prev === null ? emptyCounts() : countsOf(prev);
|
|
2368
|
-
for (const d of input.detectors) counts[d] += 1;
|
|
2369
|
-
const primary = input.detectors[0] ?? prev?.detector ?? "verification";
|
|
2370
|
-
const rec = {
|
|
2371
|
-
refused_at: input.at,
|
|
2372
|
-
refused_turn: input.turnOrdinal,
|
|
2373
|
-
detector: primary,
|
|
2374
|
-
first_refused_at: prev?.first_refused_at ?? prev?.refused_at ?? input.at,
|
|
2375
|
-
counts
|
|
2376
|
-
};
|
|
2377
|
-
if (input.version !== void 0) rec.agent_config_version = input.version;
|
|
2378
|
-
else if (prev?.agent_config_version !== void 0) {
|
|
2379
|
-
rec.agent_config_version = prev.agent_config_version;
|
|
2380
|
-
}
|
|
2381
|
-
return rec;
|
|
2382
|
-
}
|
|
2383
|
-
function readInstallBoundary() {
|
|
2384
|
-
try {
|
|
2385
|
-
const lock = read_lockfile();
|
|
2386
|
-
if (lock === null) return { version: null, installed_at: null };
|
|
2387
|
-
return {
|
|
2388
|
-
version: lock.agent_config_version ?? null,
|
|
2389
|
-
installed_at: lock.installed_at ?? null
|
|
2390
|
-
};
|
|
2391
|
-
} catch {
|
|
2392
|
-
return { version: null, installed_at: null };
|
|
2393
|
-
}
|
|
2394
|
-
}
|
|
2138
|
+
if (_isCliEntry5()) process.exit(main5());
|
|
2395
2139
|
|
|
2396
2140
|
// src/scripts/hooks/turn_end_gate_hook.ts
|
|
2397
2141
|
var EXIT_BLOCK2 = 1;
|
|
@@ -2497,10 +2241,12 @@ function detectPromissory(reply) {
|
|
|
2497
2241
|
}
|
|
2498
2242
|
return null;
|
|
2499
2243
|
}
|
|
2500
|
-
function readCiSettled(workspaceRoot) {
|
|
2244
|
+
function readCiSettled(workspaceRoot, session_id) {
|
|
2245
|
+
if (!hasStableSessionId(session_id)) return { seen: false, settled: false };
|
|
2501
2246
|
try {
|
|
2502
|
-
const raw =
|
|
2247
|
+
const raw = fs6.readFileSync(path6.join(workspaceRoot, statePathFor(session_id)), "utf-8");
|
|
2503
2248
|
const decoded = JSON.parse(raw);
|
|
2249
|
+
if (!owns_session_state(decoded, session_id)) return { seen: false, settled: false };
|
|
2504
2250
|
if (typeof decoded === "object" && decoded !== null && !Array.isArray(decoded)) {
|
|
2505
2251
|
const ci = decoded["ci_last"];
|
|
2506
2252
|
if (typeof ci === "object" && ci !== null && !Array.isArray(ci)) {
|
|
@@ -2531,10 +2277,15 @@ function detectCompletionClaim(reply, ci) {
|
|
|
2531
2277
|
reason: "a completion claim while the last CI read was not settled \u2014 read the verdict, then claim it (verify-before-complete)"
|
|
2532
2278
|
};
|
|
2533
2279
|
}
|
|
2534
|
-
function readLanguagePin(workspaceRoot) {
|
|
2280
|
+
function readLanguagePin(workspaceRoot, session_id) {
|
|
2281
|
+
if (!hasStableSessionId(session_id)) return "und";
|
|
2535
2282
|
try {
|
|
2536
|
-
const raw =
|
|
2283
|
+
const raw = fs6.readFileSync(
|
|
2284
|
+
path6.join(workspaceRoot, statePathFor2(session_id)),
|
|
2285
|
+
"utf-8"
|
|
2286
|
+
);
|
|
2537
2287
|
const decoded = JSON.parse(raw);
|
|
2288
|
+
if (!owns_session_state(decoded, session_id)) return "und";
|
|
2538
2289
|
if (typeof decoded === "object" && decoded !== null && !Array.isArray(decoded)) {
|
|
2539
2290
|
const lang = decoded["language"];
|
|
2540
2291
|
if (lang === "de" || lang === "en") return lang;
|
|
@@ -2586,7 +2337,7 @@ function sessionStateFile2(workspaceRoot, sessionKey) {
|
|
|
2586
2337
|
}
|
|
2587
2338
|
function alreadyRefusedTurn(workspaceRoot, sessionKey, turnOrdinal) {
|
|
2588
2339
|
try {
|
|
2589
|
-
const raw =
|
|
2340
|
+
const raw = fs6.readFileSync(sessionStateFile2(workspaceRoot, sessionKey), "utf-8");
|
|
2590
2341
|
const decoded = JSON.parse(raw);
|
|
2591
2342
|
if (typeof decoded === "object" && decoded !== null && !Array.isArray(decoded)) {
|
|
2592
2343
|
return decoded["refused_turn"] === turnOrdinal;
|
|
@@ -2600,7 +2351,7 @@ function markRefusedTurn(workspaceRoot, sessionKey, turnOrdinal, detectors) {
|
|
|
2600
2351
|
const file = sessionStateFile2(workspaceRoot, sessionKey);
|
|
2601
2352
|
let prev = null;
|
|
2602
2353
|
try {
|
|
2603
|
-
prev = parseRecord(
|
|
2354
|
+
prev = parseRecord(fs6.readFileSync(file, "utf-8"));
|
|
2604
2355
|
} catch {
|
|
2605
2356
|
}
|
|
2606
2357
|
let version;
|
|
@@ -2627,10 +2378,10 @@ function readTranscriptTail(transcriptPath, opts = {}) {
|
|
|
2627
2378
|
if (!transcriptPath || !isSafeTranscriptPath(transcriptPath, opts)) return empty;
|
|
2628
2379
|
let lines;
|
|
2629
2380
|
try {
|
|
2630
|
-
if (opts.maxBytes !== void 0 &&
|
|
2381
|
+
if (opts.maxBytes !== void 0 && fs6.statSync(transcriptPath).size > opts.maxBytes) {
|
|
2631
2382
|
return empty;
|
|
2632
2383
|
}
|
|
2633
|
-
lines =
|
|
2384
|
+
lines = fs6.readFileSync(transcriptPath, "utf-8").split("\n");
|
|
2634
2385
|
} catch {
|
|
2635
2386
|
return empty;
|
|
2636
2387
|
}
|
|
@@ -2706,7 +2457,7 @@ function _messageText(content) {
|
|
|
2706
2457
|
function str3(v) {
|
|
2707
2458
|
return typeof v === "string" ? v : "";
|
|
2708
2459
|
}
|
|
2709
|
-
function
|
|
2460
|
+
function main6() {
|
|
2710
2461
|
let envelope;
|
|
2711
2462
|
let payload;
|
|
2712
2463
|
try {
|
|
@@ -2728,9 +2479,8 @@ function main7() {
|
|
|
2728
2479
|
maxBytes: TRANSCRIPT_READ_MAX_BYTES
|
|
2729
2480
|
});
|
|
2730
2481
|
if (!lastAssistant) return EXIT_ALLOW5;
|
|
2731
|
-
const
|
|
2732
|
-
|
|
2733
|
-
);
|
|
2482
|
+
const rawSessionId = str3(envelope["session_id"]) || "";
|
|
2483
|
+
const sessionKey = deriveSessionKey(rawSessionId || "unknown-session");
|
|
2734
2484
|
if (alreadyRefusedTurn(workspaceRoot, sessionKey, turnOrdinal)) return EXIT_ALLOW5;
|
|
2735
2485
|
const findings = [];
|
|
2736
2486
|
for (const f of [
|
|
@@ -2738,7 +2488,7 @@ function main7() {
|
|
|
2738
2488
|
// (Phase 3 Step 2, narrowed by R2 round 2 finding 2). B and C are not
|
|
2739
2489
|
// excused by anything about a dispatch and run unchanged.
|
|
2740
2490
|
dispatchOpen ? null : detectPromissory(lastAssistant),
|
|
2741
|
-
detectLanguage(lastAssistant, readLanguagePin(workspaceRoot)),
|
|
2491
|
+
detectLanguage(lastAssistant, readLanguagePin(workspaceRoot, rawSessionId)),
|
|
2742
2492
|
detectUnverifiedEdit(toolCalls),
|
|
2743
2493
|
// Round 7 § Phase 1 — detector D. It is NOT unconditional, and this
|
|
2744
2494
|
// comment said it was while sitting one line above the `dispatchOpen`
|
|
@@ -2750,7 +2500,7 @@ function main7() {
|
|
|
2750
2500
|
// gating is where the comment above says gating belongs — inside the
|
|
2751
2501
|
// detector: no CI observed, or a settled read, or no completion claim
|
|
2752
2502
|
// ⇒ no finding.
|
|
2753
|
-
dispatchOpen ? null : detectCompletionClaim(lastAssistant, readCiSettled(workspaceRoot))
|
|
2503
|
+
dispatchOpen ? null : detectCompletionClaim(lastAssistant, readCiSettled(workspaceRoot, rawSessionId))
|
|
2754
2504
|
]) {
|
|
2755
2505
|
if (f) findings.push(f);
|
|
2756
2506
|
}
|
|
@@ -2774,37 +2524,37 @@ ${lines.join("\n")}
|
|
|
2774
2524
|
);
|
|
2775
2525
|
return EXIT_BLOCK2;
|
|
2776
2526
|
}
|
|
2777
|
-
function
|
|
2527
|
+
function _isCliEntry6() {
|
|
2778
2528
|
if (true) {
|
|
2779
2529
|
return false;
|
|
2780
2530
|
}
|
|
2781
2531
|
if (process.argv[1] === void 0) {
|
|
2782
2532
|
return false;
|
|
2783
2533
|
}
|
|
2784
|
-
const argvUrl =
|
|
2534
|
+
const argvUrl = pathToFileURL6(path6.resolve(process.argv[1])).href;
|
|
2785
2535
|
if (import.meta.url === argvUrl) {
|
|
2786
2536
|
return true;
|
|
2787
2537
|
}
|
|
2788
2538
|
try {
|
|
2789
|
-
const here =
|
|
2790
|
-
const argv =
|
|
2539
|
+
const here = fs6.realpathSync(fileURLToPath6(import.meta.url));
|
|
2540
|
+
const argv = fs6.realpathSync(path6.resolve(process.argv[1]));
|
|
2791
2541
|
return here === argv;
|
|
2792
2542
|
} catch {
|
|
2793
2543
|
return false;
|
|
2794
2544
|
}
|
|
2795
2545
|
}
|
|
2796
|
-
if (
|
|
2797
|
-
process.exit(
|
|
2546
|
+
if (_isCliEntry6()) {
|
|
2547
|
+
process.exit(main6());
|
|
2798
2548
|
}
|
|
2799
2549
|
|
|
2800
2550
|
// src/scripts/hooks/evidence_independence.ts
|
|
2801
|
-
import
|
|
2802
|
-
import
|
|
2803
|
-
import
|
|
2804
|
-
import { fileURLToPath as
|
|
2551
|
+
import crypto3 from "node:crypto";
|
|
2552
|
+
import fs7 from "node:fs";
|
|
2553
|
+
import path7 from "node:path";
|
|
2554
|
+
import { fileURLToPath as fileURLToPath7, pathToFileURL as pathToFileURL7 } from "node:url";
|
|
2805
2555
|
var EXIT_ALLOW6 = 0;
|
|
2806
2556
|
var EXIT_BLOCK3 = 1;
|
|
2807
|
-
var
|
|
2557
|
+
var STATE_FILE3 = path7.join("agents", "state", "evidence-dispatch.json");
|
|
2808
2558
|
function _isObject6(v) {
|
|
2809
2559
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
2810
2560
|
}
|
|
@@ -2872,8 +2622,8 @@ function extractDispatch(envelope) {
|
|
|
2872
2622
|
}
|
|
2873
2623
|
function _ledgerStamp(consumer_root) {
|
|
2874
2624
|
try {
|
|
2875
|
-
const raw =
|
|
2876
|
-
|
|
2625
|
+
const raw = fs7.readFileSync(
|
|
2626
|
+
path7.join(consumer_root, "agents", "state", "git-authorization.json"),
|
|
2877
2627
|
"utf8"
|
|
2878
2628
|
);
|
|
2879
2629
|
const d = JSON.parse(raw);
|
|
@@ -2884,7 +2634,7 @@ function _ledgerStamp(consumer_root) {
|
|
|
2884
2634
|
}
|
|
2885
2635
|
function _load(target) {
|
|
2886
2636
|
try {
|
|
2887
|
-
const decoded = JSON.parse(
|
|
2637
|
+
const decoded = JSON.parse(fs7.readFileSync(target, "utf8"));
|
|
2888
2638
|
if (_isObject6(decoded) && Array.isArray(decoded["evaluations"])) {
|
|
2889
2639
|
return decoded;
|
|
2890
2640
|
}
|
|
@@ -2930,7 +2680,7 @@ function decide2(tool, prompt, priorEvaluations) {
|
|
|
2930
2680
|
evaluations: priorEvaluations + 1
|
|
2931
2681
|
};
|
|
2932
2682
|
}
|
|
2933
|
-
function
|
|
2683
|
+
function run4(stdin_text, options) {
|
|
2934
2684
|
let envelope = {};
|
|
2935
2685
|
if (stdin_text.trim()) {
|
|
2936
2686
|
try {
|
|
@@ -2942,7 +2692,7 @@ function run5(stdin_text, options) {
|
|
|
2942
2692
|
return EXIT_ALLOW6;
|
|
2943
2693
|
}
|
|
2944
2694
|
}
|
|
2945
|
-
const target =
|
|
2695
|
+
const target = path7.join(options.consumer_root, STATE_FILE3);
|
|
2946
2696
|
const state = _load(target);
|
|
2947
2697
|
const session_id = typeof envelope["session_id"] === "string" ? envelope["session_id"] : "";
|
|
2948
2698
|
const turnMarker = `${session_id}:${_ledgerStamp(options.consumer_root)}`;
|
|
@@ -2956,7 +2706,7 @@ function run5(stdin_text, options) {
|
|
|
2956
2706
|
if (decision.evaluations > state.evaluations.length) {
|
|
2957
2707
|
state.evaluations.push({
|
|
2958
2708
|
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2959
|
-
digest:
|
|
2709
|
+
digest: crypto3.createHash("sha256").update(prompt).digest("hex").slice(0, 16),
|
|
2960
2710
|
prompt_chars: prompt.length
|
|
2961
2711
|
});
|
|
2962
2712
|
try {
|
|
@@ -2972,7 +2722,7 @@ function run5(stdin_text, options) {
|
|
|
2972
2722
|
}
|
|
2973
2723
|
return decision.exit;
|
|
2974
2724
|
}
|
|
2975
|
-
function
|
|
2725
|
+
function main7(argv) {
|
|
2976
2726
|
const args = argv ?? process.argv.slice(2);
|
|
2977
2727
|
let consumer_root = process.cwd();
|
|
2978
2728
|
for (let i = 0; i < args.length; i += 1) {
|
|
@@ -2984,35 +2734,35 @@ function main8(argv) {
|
|
|
2984
2734
|
consumer_root = a.slice("--project-dir=".length);
|
|
2985
2735
|
}
|
|
2986
2736
|
}
|
|
2987
|
-
return
|
|
2737
|
+
return run4(readHookStdin(), { consumer_root });
|
|
2988
2738
|
}
|
|
2989
|
-
function
|
|
2739
|
+
function _isCliEntry7() {
|
|
2990
2740
|
if (true) {
|
|
2991
2741
|
return false;
|
|
2992
2742
|
}
|
|
2993
2743
|
if (process.argv[1] === void 0) {
|
|
2994
2744
|
return false;
|
|
2995
2745
|
}
|
|
2996
|
-
const argvUrl =
|
|
2746
|
+
const argvUrl = pathToFileURL7(path7.resolve(process.argv[1])).href;
|
|
2997
2747
|
if (import.meta.url === argvUrl) {
|
|
2998
2748
|
return true;
|
|
2999
2749
|
}
|
|
3000
2750
|
try {
|
|
3001
|
-
const here =
|
|
3002
|
-
const argv =
|
|
2751
|
+
const here = fs7.realpathSync(fileURLToPath7(import.meta.url));
|
|
2752
|
+
const argv = fs7.realpathSync(path7.resolve(process.argv[1]));
|
|
3003
2753
|
return here === argv;
|
|
3004
2754
|
} catch {
|
|
3005
2755
|
return false;
|
|
3006
2756
|
}
|
|
3007
2757
|
}
|
|
3008
|
-
if (
|
|
3009
|
-
process.exit(
|
|
2758
|
+
if (_isCliEntry7()) {
|
|
2759
|
+
process.exit(main7());
|
|
3010
2760
|
}
|
|
3011
2761
|
|
|
3012
2762
|
// src/scripts/hooks/delegation_nudge_hook.ts
|
|
3013
|
-
import
|
|
3014
|
-
import
|
|
3015
|
-
import { fileURLToPath as
|
|
2763
|
+
import fs8 from "node:fs";
|
|
2764
|
+
import path8 from "node:path";
|
|
2765
|
+
import { fileURLToPath as fileURLToPath8, pathToFileURL as pathToFileURL8 } from "node:url";
|
|
3016
2766
|
|
|
3017
2767
|
// src/scripts/_lib/host_capability.ts
|
|
3018
2768
|
import process2 from "node:process";
|
|
@@ -3500,7 +3250,7 @@ function _workspaceRoot(envelope) {
|
|
|
3500
3250
|
}
|
|
3501
3251
|
return process.cwd();
|
|
3502
3252
|
}
|
|
3503
|
-
function
|
|
3253
|
+
function main8() {
|
|
3504
3254
|
let envelope = {};
|
|
3505
3255
|
try {
|
|
3506
3256
|
const raw = readHookStdin();
|
|
@@ -3539,31 +3289,31 @@ function main9() {
|
|
|
3539
3289
|
);
|
|
3540
3290
|
return EXIT_WARN3;
|
|
3541
3291
|
}
|
|
3542
|
-
function
|
|
3292
|
+
function _isCliEntry8() {
|
|
3543
3293
|
if (true) {
|
|
3544
3294
|
return false;
|
|
3545
3295
|
}
|
|
3546
3296
|
if (process.argv[1] === void 0) {
|
|
3547
3297
|
return false;
|
|
3548
3298
|
}
|
|
3549
|
-
const argvUrl =
|
|
3299
|
+
const argvUrl = pathToFileURL8(path8.resolve(process.argv[1])).href;
|
|
3550
3300
|
if (import.meta.url === argvUrl) {
|
|
3551
3301
|
return true;
|
|
3552
3302
|
}
|
|
3553
3303
|
try {
|
|
3554
|
-
const here =
|
|
3555
|
-
const argv =
|
|
3304
|
+
const here = fs8.realpathSync(fileURLToPath8(import.meta.url));
|
|
3305
|
+
const argv = fs8.realpathSync(path8.resolve(process.argv[1]));
|
|
3556
3306
|
return here === argv;
|
|
3557
3307
|
} catch {
|
|
3558
3308
|
return false;
|
|
3559
3309
|
}
|
|
3560
3310
|
}
|
|
3561
|
-
if (
|
|
3562
|
-
process.exit(
|
|
3311
|
+
if (_isCliEntry8()) {
|
|
3312
|
+
process.exit(main8());
|
|
3563
3313
|
}
|
|
3564
3314
|
|
|
3565
3315
|
// src/scripts/conformance_scan.ts
|
|
3566
|
-
var REPO_ROOT =
|
|
3316
|
+
var REPO_ROOT = path9.resolve(path9.dirname(fileURLToPath9(import.meta.url)), "..", "..");
|
|
3567
3317
|
var OBSERVED_BAND = { low: 9.1, high: 39.2 };
|
|
3568
3318
|
var BAND_MIN_TURNS = 1978;
|
|
3569
3319
|
var CARRIER_CHANGES = [
|
|
@@ -3913,7 +3663,7 @@ function scanSession(sessionId, lines) {
|
|
|
3913
3663
|
closeWindow();
|
|
3914
3664
|
return report;
|
|
3915
3665
|
}
|
|
3916
|
-
var DEFAULT_RATE_SERIES =
|
|
3666
|
+
var DEFAULT_RATE_SERIES = path9.join(
|
|
3917
3667
|
REPO_ROOT,
|
|
3918
3668
|
"agents",
|
|
3919
3669
|
"runtime",
|
|
@@ -3922,7 +3672,7 @@ var DEFAULT_RATE_SERIES = path11.join(
|
|
|
3922
3672
|
);
|
|
3923
3673
|
function defaultStore(projectDir) {
|
|
3924
3674
|
const slug = projectStoreSlug(projectDir);
|
|
3925
|
-
return
|
|
3675
|
+
return path9.join(process.env["HOME"] ?? "", ".claude", "projects", slug);
|
|
3926
3676
|
}
|
|
3927
3677
|
function _tokens(chars) {
|
|
3928
3678
|
return Math.round(chars / 4);
|
|
@@ -3933,13 +3683,13 @@ function measureDelivered(projectRulesDir, globalRulesDir) {
|
|
|
3933
3683
|
return {
|
|
3934
3684
|
project: {
|
|
3935
3685
|
dir: projectRulesDir,
|
|
3936
|
-
present:
|
|
3686
|
+
present: fs9.existsSync(projectRulesDir),
|
|
3937
3687
|
files: p.files,
|
|
3938
3688
|
tokens: _tokens(p.chars)
|
|
3939
3689
|
},
|
|
3940
3690
|
global: {
|
|
3941
3691
|
dir: globalRulesDir,
|
|
3942
|
-
present:
|
|
3692
|
+
present: fs9.existsSync(globalRulesDir),
|
|
3943
3693
|
files: g.files,
|
|
3944
3694
|
tokens: _tokens(g.chars)
|
|
3945
3695
|
},
|
|
@@ -3947,13 +3697,13 @@ function measureDelivered(projectRulesDir, globalRulesDir) {
|
|
|
3947
3697
|
};
|
|
3948
3698
|
}
|
|
3949
3699
|
function storeKey(store) {
|
|
3950
|
-
return
|
|
3700
|
+
return createHash3("sha256").update(path9.resolve(store)).digest("hex").slice(0, 12);
|
|
3951
3701
|
}
|
|
3952
3702
|
function scanStore(store, limit) {
|
|
3953
|
-
const files =
|
|
3703
|
+
const files = fs9.readdirSync(store).filter((f) => f.endsWith(".jsonl")).map((f) => ({ f, m: fs9.statSync(path9.join(store, f)).mtimeMs })).sort((a, b) => b.m - a.m).slice(0, limit).map((x) => x.f);
|
|
3954
3704
|
const per_session = [];
|
|
3955
3705
|
for (const f of files) {
|
|
3956
|
-
const lines =
|
|
3706
|
+
const lines = fs9.readFileSync(path9.join(store, f), "utf8").split("\n");
|
|
3957
3707
|
const r = scanSession(f.replace(/\.jsonl$/, "").slice(0, 8), lines);
|
|
3958
3708
|
if (r.assistant_turns > 0) {
|
|
3959
3709
|
per_session.push(r);
|
|
@@ -3981,10 +3731,10 @@ function scanStore(store, limit) {
|
|
|
3981
3731
|
const task_completeness_rate_pct = completeness_windows === 0 ? 0 : Number((100 * task_completeness / completeness_windows).toFixed(1));
|
|
3982
3732
|
const era = spansCarrierChange(per_session.map((s) => s.first_at));
|
|
3983
3733
|
const delivered = measureDelivered(
|
|
3984
|
-
|
|
3985
|
-
|
|
3734
|
+
path9.join(REPO_ROOT, ".claude", "rules"),
|
|
3735
|
+
path9.join(process.env["HOME"] ?? os2.homedir(), ".claude", "rules")
|
|
3986
3736
|
);
|
|
3987
|
-
const ownStore =
|
|
3737
|
+
const ownStore = path9.resolve(store) === path9.resolve(defaultStore(REPO_ROOT));
|
|
3988
3738
|
return {
|
|
3989
3739
|
scanned_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3990
3740
|
store,
|
|
@@ -4014,8 +3764,8 @@ function scanStore(store, limit) {
|
|
|
4014
3764
|
};
|
|
4015
3765
|
}
|
|
4016
3766
|
function recordRate(file, scanned_at, rate) {
|
|
4017
|
-
|
|
4018
|
-
|
|
3767
|
+
fs9.mkdirSync(path9.dirname(file), { recursive: true });
|
|
3768
|
+
fs9.appendFileSync(file, `${JSON.stringify({ measured_at: scanned_at, ...rate })}
|
|
4019
3769
|
`, "utf8");
|
|
4020
3770
|
}
|
|
4021
3771
|
function render(report) {
|
|
@@ -4114,7 +3864,7 @@ function render(report) {
|
|
|
4114
3864
|
lines.push(" checkbox batching \u2014 measured NOWHERE. ~5 low-severity findings.");
|
|
4115
3865
|
return lines.join("\n");
|
|
4116
3866
|
}
|
|
4117
|
-
function
|
|
3867
|
+
function main9(argv) {
|
|
4118
3868
|
const args = argv ?? process.argv.slice(2);
|
|
4119
3869
|
let store = null;
|
|
4120
3870
|
let limit = 30;
|
|
@@ -4146,14 +3896,14 @@ function main10(argv) {
|
|
|
4146
3896
|
return 2;
|
|
4147
3897
|
}
|
|
4148
3898
|
const resolved = store ?? defaultStore(process.cwd());
|
|
4149
|
-
if (!
|
|
3899
|
+
if (!fs9.existsSync(resolved)) {
|
|
4150
3900
|
process.stderr.write(`conformance:behavior: no transcript store at ${resolved}
|
|
4151
3901
|
`);
|
|
4152
3902
|
return 1;
|
|
4153
3903
|
}
|
|
4154
3904
|
const report = scanStore(resolved, Number.isFinite(limit) && limit > 0 ? limit : 30);
|
|
4155
3905
|
if (out) {
|
|
4156
|
-
|
|
3906
|
+
fs9.writeFileSync(out, `${JSON.stringify(report, null, 2)}
|
|
4157
3907
|
`, "utf8");
|
|
4158
3908
|
}
|
|
4159
3909
|
if (record) {
|
|
@@ -4161,7 +3911,7 @@ function main10(argv) {
|
|
|
4161
3911
|
}
|
|
4162
3912
|
if (why !== null) {
|
|
4163
3913
|
const id = why;
|
|
4164
|
-
|
|
3914
|
+
fs9.writeSync(
|
|
4165
3915
|
1,
|
|
4166
3916
|
json ? `${JSON.stringify(
|
|
4167
3917
|
{
|
|
@@ -4181,48 +3931,48 @@ function main10(argv) {
|
|
|
4181
3931
|
);
|
|
4182
3932
|
return 0;
|
|
4183
3933
|
}
|
|
4184
|
-
|
|
3934
|
+
fs9.writeSync(1, json ? `${JSON.stringify(report, null, 2)}
|
|
4185
3935
|
` : `${render(report)}
|
|
4186
3936
|
`);
|
|
4187
3937
|
return 0;
|
|
4188
3938
|
}
|
|
4189
|
-
function
|
|
3939
|
+
function _isCliEntry9() {
|
|
4190
3940
|
if (true) {
|
|
4191
3941
|
return false;
|
|
4192
3942
|
}
|
|
4193
3943
|
if (process.argv[1] === void 0) {
|
|
4194
3944
|
return false;
|
|
4195
3945
|
}
|
|
4196
|
-
const argvUrl =
|
|
3946
|
+
const argvUrl = pathToFileURL9(path9.resolve(process.argv[1])).href;
|
|
4197
3947
|
if (import.meta.url === argvUrl) {
|
|
4198
3948
|
return true;
|
|
4199
3949
|
}
|
|
4200
3950
|
try {
|
|
4201
|
-
const here =
|
|
4202
|
-
const argv =
|
|
3951
|
+
const here = fs9.realpathSync(fileURLToPath9(import.meta.url));
|
|
3952
|
+
const argv = fs9.realpathSync(path9.resolve(process.argv[1]));
|
|
4203
3953
|
return here === argv;
|
|
4204
3954
|
} catch {
|
|
4205
3955
|
return false;
|
|
4206
3956
|
}
|
|
4207
3957
|
}
|
|
4208
|
-
if (
|
|
4209
|
-
process.exit(
|
|
3958
|
+
if (_isCliEntry9()) {
|
|
3959
|
+
process.exit(main9());
|
|
4210
3960
|
}
|
|
4211
3961
|
|
|
4212
3962
|
// src/scripts/report_carrier_divergence.ts
|
|
4213
|
-
import * as
|
|
3963
|
+
import * as fs10 from "node:fs";
|
|
4214
3964
|
import * as os3 from "node:os";
|
|
4215
|
-
import * as
|
|
3965
|
+
import * as path10 from "node:path";
|
|
4216
3966
|
import process3 from "node:process";
|
|
4217
|
-
import { fileURLToPath as
|
|
4218
|
-
var _HERE =
|
|
4219
|
-
var REPO_ROOT2 =
|
|
4220
|
-
var PROJECT_RULES =
|
|
4221
|
-
var PROJECTION_SOURCE =
|
|
4222
|
-
var GLOBAL_RULES =
|
|
3967
|
+
import { fileURLToPath as fileURLToPath10, pathToFileURL as pathToFileURL10 } from "node:url";
|
|
3968
|
+
var _HERE = fileURLToPath10(import.meta.url);
|
|
3969
|
+
var REPO_ROOT2 = path10.resolve(path10.dirname(_HERE), "..", "..");
|
|
3970
|
+
var PROJECT_RULES = path10.join(".claude", "rules");
|
|
3971
|
+
var PROJECTION_SOURCE = path10.join("dist", "agent-src", "rules");
|
|
3972
|
+
var GLOBAL_RULES = path10.join(".claude", "rules");
|
|
4223
3973
|
function _listRules(dir) {
|
|
4224
3974
|
try {
|
|
4225
|
-
return
|
|
3975
|
+
return fs10.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
|
|
4226
3976
|
} catch {
|
|
4227
3977
|
return [];
|
|
4228
3978
|
}
|
|
@@ -4230,7 +3980,7 @@ function _listRules(dir) {
|
|
|
4230
3980
|
function _ruleType(file) {
|
|
4231
3981
|
let text;
|
|
4232
3982
|
try {
|
|
4233
|
-
text =
|
|
3983
|
+
text = fs10.readFileSync(file, "utf-8");
|
|
4234
3984
|
} catch {
|
|
4235
3985
|
return "";
|
|
4236
3986
|
}
|
|
@@ -4241,8 +3991,8 @@ function compareCarriers(projectDir, globalDir, sourceDir) {
|
|
|
4241
3991
|
const out = {
|
|
4242
3992
|
projectDir,
|
|
4243
3993
|
globalDir,
|
|
4244
|
-
globalPresent:
|
|
4245
|
-
projectPresent:
|
|
3994
|
+
globalPresent: fs10.existsSync(globalDir),
|
|
3995
|
+
projectPresent: fs10.existsSync(projectDir),
|
|
4246
3996
|
shared: 0,
|
|
4247
3997
|
identical: [],
|
|
4248
3998
|
provenanceOnly: [],
|
|
@@ -4265,7 +4015,7 @@ function compareCarriers(projectDir, globalDir, sourceDir) {
|
|
|
4265
4015
|
}
|
|
4266
4016
|
if (!inP && inG) {
|
|
4267
4017
|
out.globalOnly.push(rule);
|
|
4268
|
-
if (sourceDir !== void 0 && _ruleType(
|
|
4018
|
+
if (sourceDir !== void 0 && _ruleType(path10.join(sourceDir, rule)) === "manual") {
|
|
4269
4019
|
out.manualOnlyGlobal.push(rule);
|
|
4270
4020
|
}
|
|
4271
4021
|
continue;
|
|
@@ -4275,8 +4025,8 @@ function compareCarriers(projectDir, globalDir, sourceDir) {
|
|
|
4275
4025
|
let projectCopy;
|
|
4276
4026
|
let globalCopy;
|
|
4277
4027
|
try {
|
|
4278
|
-
projectCopy =
|
|
4279
|
-
globalCopy =
|
|
4028
|
+
projectCopy = fs10.readFileSync(path10.join(projectDir, rule));
|
|
4029
|
+
globalCopy = fs10.readFileSync(path10.join(globalDir, rule));
|
|
4280
4030
|
verdict = comparePair(projectCopy, globalCopy);
|
|
4281
4031
|
} catch {
|
|
4282
4032
|
out.shared -= 1;
|
|
@@ -4421,11 +4171,11 @@ function render2(d) {
|
|
|
4421
4171
|
}
|
|
4422
4172
|
return lines.join("\n");
|
|
4423
4173
|
}
|
|
4424
|
-
function
|
|
4174
|
+
function main10(argv) {
|
|
4425
4175
|
const args = argv ?? process3.argv.slice(2);
|
|
4426
|
-
let projectDir =
|
|
4427
|
-
let globalDir =
|
|
4428
|
-
let sourceDir =
|
|
4176
|
+
let projectDir = path10.join(REPO_ROOT2, PROJECT_RULES);
|
|
4177
|
+
let globalDir = path10.join(os3.homedir(), GLOBAL_RULES);
|
|
4178
|
+
let sourceDir = path10.join(REPO_ROOT2, PROJECTION_SOURCE);
|
|
4429
4179
|
const value = (i) => {
|
|
4430
4180
|
const v = args[i + 1];
|
|
4431
4181
|
return v === void 0 || v.startsWith("-") ? null : v;
|
|
@@ -4439,7 +4189,7 @@ function main11(argv) {
|
|
|
4439
4189
|
`);
|
|
4440
4190
|
return 1;
|
|
4441
4191
|
}
|
|
4442
|
-
const resolved =
|
|
4192
|
+
const resolved = path10.resolve(v);
|
|
4443
4193
|
if (a === "--project") projectDir = resolved;
|
|
4444
4194
|
else if (a === "--global") globalDir = resolved;
|
|
4445
4195
|
else sourceDir = resolved;
|
|
@@ -4459,44 +4209,44 @@ function main11(argv) {
|
|
|
4459
4209
|
`);
|
|
4460
4210
|
return 0;
|
|
4461
4211
|
}
|
|
4462
|
-
function
|
|
4212
|
+
function _isCliEntry10() {
|
|
4463
4213
|
if (process3.argv[1] === void 0) return false;
|
|
4464
|
-
if (import.meta.url ===
|
|
4214
|
+
if (import.meta.url === pathToFileURL10(path10.resolve(process3.argv[1])).href) return true;
|
|
4465
4215
|
try {
|
|
4466
|
-
return
|
|
4216
|
+
return fs10.realpathSync(_HERE) === fs10.realpathSync(path10.resolve(process3.argv[1]));
|
|
4467
4217
|
} catch {
|
|
4468
4218
|
return false;
|
|
4469
4219
|
}
|
|
4470
4220
|
}
|
|
4471
|
-
if (
|
|
4472
|
-
process3.exit(
|
|
4221
|
+
if (_isCliEntry10()) {
|
|
4222
|
+
process3.exit(main10());
|
|
4473
4223
|
}
|
|
4474
4224
|
|
|
4475
4225
|
// src/scripts/report_skill_activation.ts
|
|
4476
|
-
import * as
|
|
4226
|
+
import * as fs11 from "node:fs";
|
|
4477
4227
|
import * as os4 from "node:os";
|
|
4478
|
-
import * as
|
|
4479
|
-
import { fileURLToPath as
|
|
4480
|
-
var _HERE2 =
|
|
4481
|
-
var REPO_ROOT3 =
|
|
4228
|
+
import * as path11 from "node:path";
|
|
4229
|
+
import { fileURLToPath as fileURLToPath11, pathToFileURL as pathToFileURL11 } from "node:url";
|
|
4230
|
+
var _HERE2 = fileURLToPath11(import.meta.url);
|
|
4231
|
+
var REPO_ROOT3 = path11.resolve(path11.dirname(_HERE2), "..", "..");
|
|
4482
4232
|
var SKILLS_ROOT = "src/skills";
|
|
4483
4233
|
var TRIGGER_KEYS = ["triggers:", "trigger_description:", "file_pattern:", "path_prefix:"];
|
|
4484
4234
|
var DETERMINISTIC_RE = /^\s*(?:[-*]\s*)?(?:\*\*)?(MUST|NEVER|ALWAYS)\b/m;
|
|
4485
4235
|
function censusSkills(root) {
|
|
4486
4236
|
const out = { total: 0, withTriggerKey: [], withDeterministicObligation: [] };
|
|
4487
|
-
if (!
|
|
4237
|
+
if (!fs11.existsSync(root)) {
|
|
4488
4238
|
return out;
|
|
4489
4239
|
}
|
|
4490
|
-
for (const entry of
|
|
4240
|
+
for (const entry of fs11.readdirSync(root, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
4491
4241
|
if (!entry.isDirectory()) {
|
|
4492
4242
|
continue;
|
|
4493
4243
|
}
|
|
4494
|
-
const file =
|
|
4495
|
-
if (!
|
|
4244
|
+
const file = path11.join(root, entry.name, "SKILL.md");
|
|
4245
|
+
if (!fs11.existsSync(file)) {
|
|
4496
4246
|
continue;
|
|
4497
4247
|
}
|
|
4498
4248
|
out.total += 1;
|
|
4499
|
-
const text =
|
|
4249
|
+
const text = fs11.readFileSync(file, "utf8");
|
|
4500
4250
|
const fmEnd = text.startsWith("---") ? text.indexOf("\n---", 3) : -1;
|
|
4501
4251
|
const fm = fmEnd === -1 ? "" : text.slice(0, fmEnd);
|
|
4502
4252
|
if (TRIGGER_KEYS.some((k) => new RegExp(`^${k}`, "m").test(fm))) {
|
|
@@ -4510,17 +4260,17 @@ function censusSkills(root) {
|
|
|
4510
4260
|
return out;
|
|
4511
4261
|
}
|
|
4512
4262
|
function defaultStore2(cwd) {
|
|
4513
|
-
return
|
|
4263
|
+
return path11.join(os4.homedir(), ".claude", "projects", projectStoreSlug(cwd));
|
|
4514
4264
|
}
|
|
4515
4265
|
function measureUsage(store, limit) {
|
|
4516
4266
|
const rep = { store, sessions: 0, assistantTurns: 0, invocations: 0, bySkill: {} };
|
|
4517
|
-
if (!
|
|
4267
|
+
if (!fs11.existsSync(store)) {
|
|
4518
4268
|
return rep;
|
|
4519
4269
|
}
|
|
4520
|
-
const files =
|
|
4270
|
+
const files = fs11.readdirSync(store).filter((f) => f.endsWith(".jsonl")).map((f) => path11.join(store, f)).sort((a, b) => fs11.statSync(b).mtimeMs - fs11.statSync(a).mtimeMs).slice(0, limit);
|
|
4521
4271
|
rep.sessions = files.length;
|
|
4522
4272
|
for (const file of files) {
|
|
4523
|
-
for (const line of
|
|
4273
|
+
for (const line of fs11.readFileSync(file, "utf8").split("\n")) {
|
|
4524
4274
|
if (!line.trim()) {
|
|
4525
4275
|
continue;
|
|
4526
4276
|
}
|
|
@@ -4583,7 +4333,7 @@ function render3(census, usage) {
|
|
|
4583
4333
|
}
|
|
4584
4334
|
totalInv += u.invocations;
|
|
4585
4335
|
lines.push(
|
|
4586
|
-
` ${
|
|
4336
|
+
` ${path11.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)}`
|
|
4587
4337
|
);
|
|
4588
4338
|
}
|
|
4589
4339
|
lines.push("");
|
|
@@ -4608,7 +4358,7 @@ function render3(census, usage) {
|
|
|
4608
4358
|
lines.push(" catalogue once per session, then count descriptions against bare names.");
|
|
4609
4359
|
return lines.join("\n");
|
|
4610
4360
|
}
|
|
4611
|
-
function
|
|
4361
|
+
function main11(argv) {
|
|
4612
4362
|
let limit = 30;
|
|
4613
4363
|
const stores = [];
|
|
4614
4364
|
for (let i = 0; i < argv.length; i += 1) {
|
|
@@ -4631,24 +4381,24 @@ function main12(argv) {
|
|
|
4631
4381
|
if (stores.length === 0) {
|
|
4632
4382
|
stores.push(defaultStore2(REPO_ROOT3));
|
|
4633
4383
|
}
|
|
4634
|
-
const census = censusSkills(
|
|
4384
|
+
const census = censusSkills(path11.join(REPO_ROOT3, SKILLS_ROOT));
|
|
4635
4385
|
const usage = stores.map((s) => measureUsage(s, limit));
|
|
4636
4386
|
process.stdout.write(`${render3(census, usage)}
|
|
4637
4387
|
`);
|
|
4638
4388
|
return 0;
|
|
4639
4389
|
}
|
|
4640
|
-
if (process.argv[1] !== void 0 && import.meta.url ===
|
|
4641
|
-
process.exit(
|
|
4390
|
+
if (process.argv[1] !== void 0 && import.meta.url === pathToFileURL11(path11.resolve(process.argv[1])).href) {
|
|
4391
|
+
process.exit(main11(process.argv.slice(2)));
|
|
4642
4392
|
}
|
|
4643
4393
|
|
|
4644
4394
|
// src/scripts/report_skill_obligation_violations.ts
|
|
4645
|
-
import * as
|
|
4395
|
+
import * as fs12 from "node:fs";
|
|
4646
4396
|
import * as os5 from "node:os";
|
|
4647
|
-
import * as
|
|
4397
|
+
import * as path12 from "node:path";
|
|
4648
4398
|
import process4 from "node:process";
|
|
4649
|
-
import { fileURLToPath as
|
|
4650
|
-
var _HERE3 =
|
|
4651
|
-
var REPO_ROOT4 =
|
|
4399
|
+
import { fileURLToPath as fileURLToPath12, pathToFileURL as pathToFileURL12 } from "node:url";
|
|
4400
|
+
var _HERE3 = fileURLToPath12(import.meta.url);
|
|
4401
|
+
var REPO_ROOT4 = path12.resolve(path12.dirname(_HERE3), "..", "..");
|
|
4652
4402
|
var OBLIGATION_LINE_RE = new RegExp(`${DETERMINISTIC_RE.source}.*`, "gm");
|
|
4653
4403
|
var PATH_RE = /`([A-Za-z0-9_./-]*\/[A-Za-z0-9_.-]+\.[a-z]{2,6})`/g;
|
|
4654
4404
|
var CMD_RE = /`([a-z][a-z0-9-]*(?: [a-z][a-z0-9:._-]*){1,3})`/g;
|
|
@@ -4686,7 +4436,7 @@ function _artefacts(line) {
|
|
|
4686
4436
|
return out;
|
|
4687
4437
|
}
|
|
4688
4438
|
function extractObligations(repoRoot) {
|
|
4689
|
-
const skillsRoot =
|
|
4439
|
+
const skillsRoot = path12.join(repoRoot, SKILLS_ROOT);
|
|
4690
4440
|
const census = censusSkills(skillsRoot);
|
|
4691
4441
|
const out = {
|
|
4692
4442
|
skills: census.withDeterministicObligation,
|
|
@@ -4700,7 +4450,7 @@ function extractObligations(repoRoot) {
|
|
|
4700
4450
|
for (const skill of census.withDeterministicObligation) {
|
|
4701
4451
|
let text;
|
|
4702
4452
|
try {
|
|
4703
|
-
text =
|
|
4453
|
+
text = fs12.readFileSync(path12.join(skillsRoot, skill, "SKILL.md"), "utf-8");
|
|
4704
4454
|
} catch {
|
|
4705
4455
|
continue;
|
|
4706
4456
|
}
|
|
@@ -4816,7 +4566,7 @@ function scanSessionForViolations(session, lines, forbidden, parsed) {
|
|
|
4816
4566
|
return flags;
|
|
4817
4567
|
}
|
|
4818
4568
|
function defaultStore3(cwd) {
|
|
4819
|
-
return
|
|
4569
|
+
return path12.join(os5.homedir(), ".claude", "projects", projectStoreSlug(cwd));
|
|
4820
4570
|
}
|
|
4821
4571
|
function scanStore2(repoRoot, store, limit) {
|
|
4822
4572
|
const census = extractObligations(repoRoot);
|
|
@@ -4829,14 +4579,14 @@ function scanStore2(repoRoot, store, limit) {
|
|
|
4829
4579
|
};
|
|
4830
4580
|
let files;
|
|
4831
4581
|
try {
|
|
4832
|
-
files =
|
|
4582
|
+
files = fs12.readdirSync(store).filter((f) => f.endsWith(".jsonl")).map((f) => ({ p: path12.join(store, f), m: fs12.statSync(path12.join(store, f)).mtimeMs })).sort((a, b) => b.m - a.m).slice(0, limit).map((x) => x.p);
|
|
4833
4583
|
} catch {
|
|
4834
4584
|
return report;
|
|
4835
4585
|
}
|
|
4836
4586
|
report.sessions = files.length;
|
|
4837
4587
|
for (const file of files) {
|
|
4838
|
-
const lines =
|
|
4839
|
-
const id =
|
|
4588
|
+
const lines = fs12.readFileSync(file, "utf-8").split("\n");
|
|
4589
|
+
const id = path12.basename(file).replace(/\.jsonl$/, "").slice(0, 8);
|
|
4840
4590
|
const entries = _parseSession(lines);
|
|
4841
4591
|
if (loadedSkillsFrom(entries).size > 0) report.sessionsWithASkill += 1;
|
|
4842
4592
|
report.flags.push(...scanSessionForViolations(id, lines, census.forbidden, entries));
|
|
@@ -4906,7 +4656,7 @@ function render4(r) {
|
|
|
4906
4656
|
lines.push(" ships as detection-only, and this one says so.");
|
|
4907
4657
|
return lines.join("\n");
|
|
4908
4658
|
}
|
|
4909
|
-
function
|
|
4659
|
+
function main12(argv) {
|
|
4910
4660
|
const args = argv ?? process4.argv.slice(2);
|
|
4911
4661
|
let limit = 30;
|
|
4912
4662
|
let json = false;
|
|
@@ -4959,35 +4709,35 @@ function main13(argv) {
|
|
|
4959
4709
|
}
|
|
4960
4710
|
return 0;
|
|
4961
4711
|
}
|
|
4962
|
-
function
|
|
4712
|
+
function _isCliEntry11() {
|
|
4963
4713
|
if (process4.argv[1] === void 0) return false;
|
|
4964
|
-
if (import.meta.url ===
|
|
4714
|
+
if (import.meta.url === pathToFileURL12(path12.resolve(process4.argv[1])).href) return true;
|
|
4965
4715
|
try {
|
|
4966
|
-
return
|
|
4716
|
+
return fs12.realpathSync(_HERE3) === fs12.realpathSync(path12.resolve(process4.argv[1]));
|
|
4967
4717
|
} catch {
|
|
4968
4718
|
return false;
|
|
4969
4719
|
}
|
|
4970
4720
|
}
|
|
4971
|
-
if (
|
|
4972
|
-
process4.exit(
|
|
4721
|
+
if (_isCliEntry11()) {
|
|
4722
|
+
process4.exit(main12());
|
|
4973
4723
|
}
|
|
4974
4724
|
|
|
4975
4725
|
// src/scripts/report_conformance_funnel.ts
|
|
4976
|
-
var _HERE4 =
|
|
4977
|
-
var REPO_ROOT5 =
|
|
4726
|
+
var _HERE4 = fileURLToPath13(import.meta.url);
|
|
4727
|
+
var REPO_ROOT5 = path13.resolve(path13.dirname(_HERE4), "..", "..");
|
|
4978
4728
|
function buildFunnel(opts = {}) {
|
|
4979
4729
|
const repoRoot = opts.repoRoot ?? REPO_ROOT5;
|
|
4980
|
-
const projectRulesDir = opts.projectRulesDir ??
|
|
4981
|
-
const globalRulesDir = opts.globalRulesDir ??
|
|
4982
|
-
const sourceDir = opts.sourceDir ??
|
|
4730
|
+
const projectRulesDir = opts.projectRulesDir ?? path13.join(repoRoot, PROJECT_RULES);
|
|
4731
|
+
const globalRulesDir = opts.globalRulesDir ?? path13.join(os6.homedir(), GLOBAL_RULES);
|
|
4732
|
+
const sourceDir = opts.sourceDir ?? path13.join(repoRoot, PROJECTION_SOURCE);
|
|
4983
4733
|
const store = opts.store ?? defaultStore(repoRoot);
|
|
4984
4734
|
const limit = opts.limit ?? 30;
|
|
4985
4735
|
return {
|
|
4986
4736
|
delivered: measureDelivered(projectRulesDir, globalRulesDir),
|
|
4987
4737
|
divergence: compareCarriers(projectRulesDir, globalRulesDir, sourceDir),
|
|
4988
|
-
skills: censusSkills(
|
|
4738
|
+
skills: censusSkills(path13.join(repoRoot, SKILLS_ROOT)),
|
|
4989
4739
|
usage: measureUsage(store, limit),
|
|
4990
|
-
storePresent:
|
|
4740
|
+
storePresent: fs13.existsSync(store),
|
|
4991
4741
|
sk2: scanStore2(repoRoot, store, limit)
|
|
4992
4742
|
};
|
|
4993
4743
|
}
|
|
@@ -5112,7 +4862,7 @@ function render5(r) {
|
|
|
5112
4862
|
lines.push("workflow without a measured false-positive rate first (locked policy).");
|
|
5113
4863
|
return lines.join("\n");
|
|
5114
4864
|
}
|
|
5115
|
-
function
|
|
4865
|
+
function main13(argv) {
|
|
5116
4866
|
const args = argv ?? process5.argv.slice(2);
|
|
5117
4867
|
const opts = {};
|
|
5118
4868
|
const value = (i) => {
|
|
@@ -5128,7 +4878,7 @@ function main14(argv) {
|
|
|
5128
4878
|
`);
|
|
5129
4879
|
return 1;
|
|
5130
4880
|
}
|
|
5131
|
-
const resolved =
|
|
4881
|
+
const resolved = path13.resolve(v);
|
|
5132
4882
|
if (a === "--store") opts.store = resolved;
|
|
5133
4883
|
else if (a === "--project") opts.projectRulesDir = resolved;
|
|
5134
4884
|
else if (a === "--global") opts.globalRulesDir = resolved;
|
|
@@ -5158,21 +4908,21 @@ function main14(argv) {
|
|
|
5158
4908
|
`);
|
|
5159
4909
|
return 0;
|
|
5160
4910
|
}
|
|
5161
|
-
function
|
|
4911
|
+
function _isCliEntry12() {
|
|
5162
4912
|
if (process5.argv[1] === void 0) return false;
|
|
5163
|
-
if (import.meta.url ===
|
|
4913
|
+
if (import.meta.url === pathToFileURL13(path13.resolve(process5.argv[1])).href) return true;
|
|
5164
4914
|
try {
|
|
5165
|
-
return
|
|
4915
|
+
return fs13.realpathSync(_HERE4) === fs13.realpathSync(path13.resolve(process5.argv[1]));
|
|
5166
4916
|
} catch {
|
|
5167
4917
|
return false;
|
|
5168
4918
|
}
|
|
5169
4919
|
}
|
|
5170
|
-
if (
|
|
5171
|
-
process5.exit(
|
|
4920
|
+
if (_isCliEntry12()) {
|
|
4921
|
+
process5.exit(main13());
|
|
5172
4922
|
}
|
|
5173
4923
|
|
|
5174
4924
|
// src/scripts/_cli/cmd_conformance.ts
|
|
5175
|
-
var _HERE5 =
|
|
4925
|
+
var _HERE5 = fileURLToPath14(import.meta.url);
|
|
5176
4926
|
var PACKAGE_ROOT = resolvePackageRoot(import.meta.url);
|
|
5177
4927
|
var CONFORMANCE_CHECK_IDS = [
|
|
5178
4928
|
"txlog-clean",
|
|
@@ -5195,17 +4945,17 @@ function conformanceLogPath() {
|
|
|
5195
4945
|
if (override && override.trim().length > 0) {
|
|
5196
4946
|
return override;
|
|
5197
4947
|
}
|
|
5198
|
-
return
|
|
4948
|
+
return path14.join(os7.homedir(), ".event4u", "agent-config", "conformance-log.jsonl");
|
|
5199
4949
|
}
|
|
5200
4950
|
function installLogPath() {
|
|
5201
4951
|
const override = process6.env["AGENT_CONFIG_INSTALL_LOG"];
|
|
5202
4952
|
if (override && override.trim().length > 0) {
|
|
5203
4953
|
return override;
|
|
5204
4954
|
}
|
|
5205
|
-
return
|
|
4955
|
+
return path14.join(os7.homedir(), ".event4u", "agent-config", "install-log.jsonl");
|
|
5206
4956
|
}
|
|
5207
4957
|
function _check_txlog_clean(logPath = installLogPath()) {
|
|
5208
|
-
if (!
|
|
4958
|
+
if (!fs14.existsSync(logPath)) {
|
|
5209
4959
|
return {
|
|
5210
4960
|
id: "txlog-clean",
|
|
5211
4961
|
status: "ok",
|
|
@@ -5239,11 +4989,11 @@ function _check_txlog_clean(logPath = installLogPath()) {
|
|
|
5239
4989
|
};
|
|
5240
4990
|
}
|
|
5241
4991
|
function routeTargetPaths(target) {
|
|
5242
|
-
return routeTargetPathsPosix(target).map((rel) =>
|
|
4992
|
+
return routeTargetPathsPosix(target).map((rel) => path14.join(...rel.split("/")));
|
|
5243
4993
|
}
|
|
5244
4994
|
function _check_router_pointers(packageRoot = PACKAGE_ROOT) {
|
|
5245
|
-
const routerPath =
|
|
5246
|
-
if (!
|
|
4995
|
+
const routerPath = path14.join(packageRoot, "dist", "router.json");
|
|
4996
|
+
if (!fs14.existsSync(routerPath)) {
|
|
5247
4997
|
return {
|
|
5248
4998
|
id: "router-pointers",
|
|
5249
4999
|
status: "fail",
|
|
@@ -5253,7 +5003,7 @@ function _check_router_pointers(packageRoot = PACKAGE_ROOT) {
|
|
|
5253
5003
|
}
|
|
5254
5004
|
let router;
|
|
5255
5005
|
try {
|
|
5256
|
-
router = JSON.parse(
|
|
5006
|
+
router = JSON.parse(fs14.readFileSync(routerPath, "utf8"));
|
|
5257
5007
|
} catch (exc) {
|
|
5258
5008
|
return {
|
|
5259
5009
|
id: "router-pointers",
|
|
@@ -5262,13 +5012,13 @@ function _check_router_pointers(packageRoot = PACKAGE_ROOT) {
|
|
|
5262
5012
|
remedy: "reinstall the package \u2014 dist/router.json is corrupt"
|
|
5263
5013
|
};
|
|
5264
5014
|
}
|
|
5265
|
-
const rulesDir =
|
|
5015
|
+
const rulesDir = path14.join(packageRoot, "dist", "agent-src", "rules");
|
|
5266
5016
|
const broken = [];
|
|
5267
5017
|
let ids = 0;
|
|
5268
5018
|
let targets = 0;
|
|
5269
5019
|
for (const kernelId of router["kernel"] ?? []) {
|
|
5270
5020
|
ids += 1;
|
|
5271
|
-
if (!
|
|
5021
|
+
if (!fs14.existsSync(path14.join(rulesDir, `${kernelId}.md`))) {
|
|
5272
5022
|
broken.push(`kernel:${kernelId} \u2192 rules/${kernelId}.md missing`);
|
|
5273
5023
|
}
|
|
5274
5024
|
}
|
|
@@ -5276,7 +5026,7 @@ function _check_router_pointers(packageRoot = PACKAGE_ROOT) {
|
|
|
5276
5026
|
for (const entry of router[tier] ?? []) {
|
|
5277
5027
|
const ruleId = String(entry["id"] ?? "");
|
|
5278
5028
|
ids += 1;
|
|
5279
|
-
if (!
|
|
5029
|
+
if (!fs14.existsSync(path14.join(rulesDir, `${ruleId}.md`))) {
|
|
5280
5030
|
broken.push(`${tier}:${ruleId} \u2192 rules/${ruleId}.md missing`);
|
|
5281
5031
|
}
|
|
5282
5032
|
for (const target of entry["routes_to"] ?? []) {
|
|
@@ -5286,7 +5036,7 @@ function _check_router_pointers(packageRoot = PACKAGE_ROOT) {
|
|
|
5286
5036
|
broken.push(`${ruleId} \u2192 unparseable routes_to ${JSON.stringify(target)}`);
|
|
5287
5037
|
continue;
|
|
5288
5038
|
}
|
|
5289
|
-
if (!candidates.some((rel) =>
|
|
5039
|
+
if (!candidates.some((rel) => fs14.existsSync(path14.join(packageRoot, rel)))) {
|
|
5290
5040
|
broken.push(`${ruleId} \u2192 ${target} (${candidates[0]} missing)`);
|
|
5291
5041
|
}
|
|
5292
5042
|
}
|
|
@@ -5318,9 +5068,9 @@ function detectSmokePlatform(projectRoot) {
|
|
|
5318
5068
|
return "claude";
|
|
5319
5069
|
}
|
|
5320
5070
|
function dispatcherRunner(packageRoot) {
|
|
5321
|
-
const localTsx =
|
|
5322
|
-
const script =
|
|
5323
|
-
if (
|
|
5071
|
+
const localTsx = path14.join(packageRoot, "node_modules", ".bin", "tsx");
|
|
5072
|
+
const script = path14.join(packageRoot, "src", "scripts", "hooks", "dispatch_hook.ts");
|
|
5073
|
+
if (fs14.existsSync(localTsx)) {
|
|
5324
5074
|
return [localTsx, script];
|
|
5325
5075
|
}
|
|
5326
5076
|
return ["npx", "tsx", script];
|
|
@@ -5370,12 +5120,12 @@ function _check_hook_dispatcher(projectRoot, packageRoot = PACKAGE_ROOT, opts =
|
|
|
5370
5120
|
};
|
|
5371
5121
|
}
|
|
5372
5122
|
function readSettingsMode(projectRoot) {
|
|
5373
|
-
const settingsPath =
|
|
5374
|
-
if (!
|
|
5123
|
+
const settingsPath = path14.join(projectRoot, ".agent-settings.yml");
|
|
5124
|
+
if (!fs14.existsSync(settingsPath)) {
|
|
5375
5125
|
return "eager-all";
|
|
5376
5126
|
}
|
|
5377
5127
|
try {
|
|
5378
|
-
const parsed = YAML.parse(
|
|
5128
|
+
const parsed = YAML.parse(fs14.readFileSync(settingsPath, "utf8"));
|
|
5379
5129
|
const lean = parsed?.["lean_projection"] ?? null;
|
|
5380
5130
|
const mode = lean?.["mode"];
|
|
5381
5131
|
return typeof mode === "string" && mode.length > 0 ? mode : "eager-all";
|
|
@@ -5386,7 +5136,7 @@ function readSettingsMode(projectRoot) {
|
|
|
5386
5136
|
function kernelIdsFromRouter(packageRoot) {
|
|
5387
5137
|
try {
|
|
5388
5138
|
const router = JSON.parse(
|
|
5389
|
-
|
|
5139
|
+
fs14.readFileSync(path14.join(packageRoot, "dist", "router.json"), "utf8")
|
|
5390
5140
|
);
|
|
5391
5141
|
return new Set((router["kernel"] ?? []).map(String));
|
|
5392
5142
|
} catch {
|
|
@@ -5403,8 +5153,8 @@ function _check_lean_projection(projectRoot, packageRoot = PACKAGE_ROOT, project
|
|
|
5403
5153
|
remedy: "set lean_projection.mode to 'eager-all' or 'thin' in .agent-settings.yml"
|
|
5404
5154
|
};
|
|
5405
5155
|
}
|
|
5406
|
-
const rulesDir = projectedRulesDir ??
|
|
5407
|
-
if (!
|
|
5156
|
+
const rulesDir = projectedRulesDir ?? path14.join(projectRoot, ".augment", "rules");
|
|
5157
|
+
if (!fs14.existsSync(rulesDir)) {
|
|
5408
5158
|
return {
|
|
5409
5159
|
id: "lean-projection",
|
|
5410
5160
|
status: "skipped",
|
|
@@ -5413,7 +5163,7 @@ function _check_lean_projection(projectRoot, packageRoot = PACKAGE_ROOT, project
|
|
|
5413
5163
|
};
|
|
5414
5164
|
}
|
|
5415
5165
|
const kernel = kernelIdsFromRouter(packageRoot);
|
|
5416
|
-
const files =
|
|
5166
|
+
const files = fs14.readdirSync(rulesDir).filter((f) => f.endsWith(".md") && f !== "INDEX.md").sort();
|
|
5417
5167
|
const nonKernel = files.filter((f) => !kernel.has(f.replace(/\.md$/, "")));
|
|
5418
5168
|
if (nonKernel.length === 0) {
|
|
5419
5169
|
return {
|
|
@@ -5427,7 +5177,7 @@ function _check_lean_projection(projectRoot, packageRoot = PACKAGE_ROOT, project
|
|
|
5427
5177
|
for (const f of nonKernel) {
|
|
5428
5178
|
let text = "";
|
|
5429
5179
|
try {
|
|
5430
|
-
text =
|
|
5180
|
+
text = fs14.readFileSync(path14.join(rulesDir, f), "utf8");
|
|
5431
5181
|
} catch {
|
|
5432
5182
|
continue;
|
|
5433
5183
|
}
|
|
@@ -5458,8 +5208,8 @@ function _check_lean_projection(projectRoot, packageRoot = PACKAGE_ROOT, project
|
|
|
5458
5208
|
function _check_host_manifest(projectRoot) {
|
|
5459
5209
|
const detected = Object.entries(detectToolPresence(projectRoot)).filter(([, v]) => v === true).map(([k]) => k);
|
|
5460
5210
|
const detectedNote = detected.length > 0 ? `detected surfaces: ${detected.join(", ")}` : "no surfaces detected";
|
|
5461
|
-
const settingsPath =
|
|
5462
|
-
if (!
|
|
5211
|
+
const settingsPath = path14.join(projectRoot, ".agent-settings.yml");
|
|
5212
|
+
if (!fs14.existsSync(settingsPath)) {
|
|
5463
5213
|
return {
|
|
5464
5214
|
id: "host-manifest",
|
|
5465
5215
|
status: "ok",
|
|
@@ -5469,7 +5219,7 @@ function _check_host_manifest(projectRoot) {
|
|
|
5469
5219
|
}
|
|
5470
5220
|
let parsed = null;
|
|
5471
5221
|
try {
|
|
5472
|
-
parsed = YAML.parse(
|
|
5222
|
+
parsed = YAML.parse(fs14.readFileSync(settingsPath, "utf8"));
|
|
5473
5223
|
} catch (exc) {
|
|
5474
5224
|
return {
|
|
5475
5225
|
id: "host-manifest",
|
|
@@ -5568,7 +5318,7 @@ function _parse(argv) {
|
|
|
5568
5318
|
}
|
|
5569
5319
|
return opts;
|
|
5570
5320
|
}
|
|
5571
|
-
function
|
|
5321
|
+
function main14(argv = null) {
|
|
5572
5322
|
const opts = _parse(argv !== null ? Array.from(argv) : process6.argv.slice(2));
|
|
5573
5323
|
if (opts.funnel) {
|
|
5574
5324
|
print(render5(buildFunnel()));
|
|
@@ -5639,25 +5389,25 @@ function main15(argv = null) {
|
|
|
5639
5389
|
}
|
|
5640
5390
|
return failed ? 1 : 0;
|
|
5641
5391
|
}
|
|
5642
|
-
function
|
|
5392
|
+
function _isCliEntry13() {
|
|
5643
5393
|
if (process6.argv[1] === void 0) {
|
|
5644
5394
|
return false;
|
|
5645
5395
|
}
|
|
5646
|
-
const argvUrl =
|
|
5396
|
+
const argvUrl = pathToFileURL14(path14.resolve(process6.argv[1])).href;
|
|
5647
5397
|
if (import.meta.url === argvUrl) {
|
|
5648
5398
|
return true;
|
|
5649
5399
|
}
|
|
5650
5400
|
try {
|
|
5651
|
-
const here =
|
|
5652
|
-
const argv =
|
|
5401
|
+
const here = fs14.realpathSync(fileURLToPath14(import.meta.url));
|
|
5402
|
+
const argv = fs14.realpathSync(path14.resolve(process6.argv[1]));
|
|
5653
5403
|
return here === argv;
|
|
5654
5404
|
} catch {
|
|
5655
5405
|
return false;
|
|
5656
5406
|
}
|
|
5657
5407
|
}
|
|
5658
|
-
if (
|
|
5408
|
+
if (_isCliEntry13() || process6.argv[1] === _HERE5) {
|
|
5659
5409
|
try {
|
|
5660
|
-
process6.exitCode =
|
|
5410
|
+
process6.exitCode = main14(process6.argv.slice(2));
|
|
5661
5411
|
} catch (e) {
|
|
5662
5412
|
if (e instanceof ArgparseExit) {
|
|
5663
5413
|
process6.exitCode = e.code;
|
|
@@ -5680,7 +5430,7 @@ export {
|
|
|
5680
5430
|
conformanceLogPath,
|
|
5681
5431
|
detectSmokePlatform,
|
|
5682
5432
|
installLogPath,
|
|
5683
|
-
|
|
5433
|
+
main14 as main,
|
|
5684
5434
|
routeTargetPaths,
|
|
5685
5435
|
runConformanceChecks
|
|
5686
5436
|
};
|