@event4u/agent-config 17.0.0 → 17.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.augment-plugin/marketplace.json +3 -3
- package/.augment-plugin/plugin.json +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +104 -485
- package/README.md +2 -1
- package/dist/agent-src/contexts/execution/host-capability-manifest.md +5 -3
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +5 -1
- package/dist/cli-delegate/{chunk-IROAQ77A.js → chunk-3PK3VZHB.js} +107 -9
- package/dist/cli-delegate/{chunk-2SFOOFJJ.js → chunk-BZJ4Y3CI.js} +1 -1
- package/dist/cli-delegate/{chunk-CAL76ADI.js → chunk-CMZEKSNN.js} +52 -10
- package/dist/cli-delegate/{chunk-ESUNQ5XR.js → chunk-E3CFULNX.js} +22 -4
- package/dist/cli-delegate/{chunk-GOMILC3O.js → chunk-QBHEI5N4.js} +4 -3
- package/dist/cli-delegate/{chunk-SIOMDAKL.js → chunk-VYZGJLCA.js} +29 -39
- package/dist/cli-delegate/chunk-W5JXMF2T.js +77 -0
- package/dist/cli-delegate/{chunk-4SHNERBL.js → chunk-XIAPY44N.js} +1 -1
- package/dist/cli-delegate/{chunk-JHMMWNJ2.js → chunk-YHAPONWV.js} +1 -1
- package/dist/cli-delegate/cmd_conformance.js +9 -8
- package/dist/cli-delegate/cmd_doctor.js +4 -4
- package/dist/cli-delegate/cmd_doctor_neighbours.js +2 -2
- package/dist/cli-delegate/cmd_explain.js +1 -1
- package/dist/cli-delegate/cmd_export.js +6 -6
- package/dist/cli-delegate/cmd_fleet.js +3 -3
- package/dist/cli-delegate/cmd_preflight.js +3 -3
- package/dist/cli-delegate/cmd_prune.js +6 -6
- package/dist/cli-delegate/cmd_settings_migrate.js +6 -6
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +6 -6
- package/dist/cli-delegate/cmd_uninstall.js +6 -6
- package/dist/cli-delegate/cmd_update.js +9 -13
- package/dist/cli-delegate/cmd_validate.js +6 -6
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +4 -4
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +1 -1
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +2 -2
- package/dist/discovery/trust-report.md +1 -1
- package/dist/discovery/workspaces.json +2 -2
- package/dist/hooks/dispatch.js +98 -74
- package/dist/hooks/dispatch.sha256 +1 -1
- package/dist/install/claudeRuleRewrite.js +10 -3
- package/dist/install/conflict.js +24 -2
- package/dist/install/conflictTracker.js +14 -3
- package/dist/install/install.mjs +222 -117
- package/dist/install/installThinLayer.js +1 -0
- package/dist/install/loggedWrites.js +142 -0
- package/dist/install/paths.js +12 -2
- package/dist/install/preserve.js +25 -4
- package/dist/install/txlog.js +10 -6
- package/dist/mcp/registry-manifest.json +2 -2
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +845 -294
- package/dist/scripts/_lib/egress_rules.js +4 -1
- package/dist/scripts/_lib/identifier_redaction.js +35 -2
- package/dist/scripts/ai_council/seat_policy.js +7 -1
- package/dist/server/schemas/settings.js +1 -1
- package/package.json +1 -1
- package/src/config/ci-local-parity.yml +1 -1
- package/src/config/gate-coverage.yml +27 -7
- package/src/config/gate-violation-baselines.json +8 -2
- package/src/config/hook-bundle-budget.json +2 -2
- package/src/config/production-entries.json +18 -0
- package/src/config/release-gate-locality.yml +0 -7
- package/src/install/claudeRuleRewrite.ts +10 -1
- package/src/install/conflict.ts +24 -1
- package/src/install/conflictTracker.ts +18 -2
- package/src/install/installThinLayer.ts +6 -0
- package/src/install/loggedWrites.ts +148 -0
- package/src/install/paths.ts +11 -2
- package/src/install/preserve.ts +40 -4
- package/src/install/txlog.ts +10 -6
- package/src/scripts/_cli/cmd_conformance.ts +3 -2
- package/src/scripts/_cli/cmd_update.ts +15 -17
- package/src/scripts/_lib/council_settings_block.ts +9 -2
- package/src/scripts/_lib/egress_rules.ts +4 -1
- package/src/scripts/_lib/host_capability.ts +10 -5
- package/src/scripts/_lib/identifier_redaction.ts +38 -2
- package/src/scripts/_lib/price_freshness.ts +112 -0
- package/src/scripts/_lib/production_reach.ts +194 -0
- package/src/scripts/_lib/quota_parked.ts +17 -28
- package/src/scripts/_lib/release_findings_ingest.ts +13 -335
- package/src/scripts/_lib/tier_downshift_verdict.ts +81 -35
- package/src/scripts/ai_council/chairman.ts +5 -2
- package/src/scripts/ai_council/clients.ts +4 -3
- package/src/scripts/ai_council/free_hand_shadow.ts +24 -12
- package/src/scripts/ai_council/free_route_catalog.ts +142 -5
- package/src/scripts/ai_council/free_route_client.ts +4 -0
- package/src/scripts/ai_council/hand_payload.ts +115 -7
- package/src/scripts/ai_council/orchestrator.ts +7 -10
- package/src/scripts/ai_council/route_chooser.ts +1 -1
- package/src/scripts/ai_council/route_member.ts +66 -4
- package/src/scripts/ai_council/seat_policy.ts +8 -1
- package/src/scripts/ai_council/self_hosted_probe.ts +327 -0
- package/src/scripts/ai_council/status_surface.ts +2 -0
- package/src/scripts/ask_transport.ts +137 -15
- package/src/scripts/check_finding_dispositions.ts +25 -71
- package/src/scripts/check_release_pr_shape.ts +3 -3
- package/src/scripts/check_step_production_reach.ts +257 -0
- package/src/scripts/council_cli.ts +10 -8
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +3 -0
- package/src/scripts/hooks/dispatch_hook.ts +2 -2
- package/src/scripts/hooks/payload_stub.ts +27 -0
- package/src/scripts/hooks/spawn_guard_shadow_hook.ts +29 -70
- package/src/scripts/hooks/subagent_ledger_hook.ts +80 -0
- package/src/scripts/install.ts +2 -2
- package/src/scripts/lint_decision_classes.ts +34 -0
- package/src/scripts/lint_hook_manifest.ts +24 -0
- package/src/scripts/lint_roadmap_blockers.ts +52 -3
- package/src/scripts/release.ts +5 -9
- package/src/scripts/release_drill.ts +11 -165
- package/src/scripts/release_publication.ts +0 -9
- package/src/scripts/report_production_reach.ts +35 -0
- package/src/scripts/worker_reuse_shadow_report.ts +399 -1
- package/src/server/schemas/settings.ts +1 -1
- package/dist/cli-delegate/chunk-A4QJ6ENT.js +0 -50
- /package/dist/cli-delegate/{chunk-E6XNBVE4.js → chunk-KR5ZIFPO.js} +0 -0
package/dist/hooks/dispatch.js
CHANGED
|
@@ -21044,6 +21044,23 @@ function _concern_body_classes(concern) {
|
|
|
21044
21044
|
}
|
|
21045
21045
|
return parseBodyClasses(concern["needs_payload_bodies"]);
|
|
21046
21046
|
}
|
|
21047
|
+
function applyPayloadFields(concern, env) {
|
|
21048
|
+
const fields = concern["payload_fields"];
|
|
21049
|
+
const payload = env["payload"];
|
|
21050
|
+
if (!Array.isArray(fields) || !isObject2(payload) || concern["fail_closed"] === true || concern["severity"] === "blocking") {
|
|
21051
|
+
return env;
|
|
21052
|
+
}
|
|
21053
|
+
const keep = new Set(fields);
|
|
21054
|
+
const out = { ...payload };
|
|
21055
|
+
for (const cls of BODY_CLASSES) {
|
|
21056
|
+
for (const key of BODY_KEYS[cls]) {
|
|
21057
|
+
const v = payload[key];
|
|
21058
|
+
if (v === void 0 || v === null || isPayloadStub(v)) continue;
|
|
21059
|
+
out[key] = isObject2(v) ? Object.fromEntries(Object.entries(v).filter(([k]) => keep.has(k))) : makePayloadStub(key, cls, v, /* @__PURE__ */ new Map([[key, bodyBytes(v)]]));
|
|
21060
|
+
}
|
|
21061
|
+
}
|
|
21062
|
+
return { ...env, payload: out };
|
|
21063
|
+
}
|
|
21047
21064
|
function planPayloadShapes(envelope, keepSets, placeholder) {
|
|
21048
21065
|
const present = presentBodyClasses(envelope);
|
|
21049
21066
|
const stubbedSomewhere = /* @__PURE__ */ new Set();
|
|
@@ -33030,7 +33047,8 @@ function probeHostCapabilities(hostId) {
|
|
|
33030
33047
|
const base2 = resolveHostCapabilities(hostId);
|
|
33031
33048
|
const flag = process9.env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS;
|
|
33032
33049
|
const probedAgentTeams = typeof flag === "string" && flag !== "";
|
|
33033
|
-
|
|
33050
|
+
const probedResume = probedAgentTeams && hostId === "claude";
|
|
33051
|
+
return { ...base2, agent_teams: base2.agent_teams || probedAgentTeams, worker_resume: base2.worker_resume || probedResume };
|
|
33034
33052
|
}
|
|
33035
33053
|
|
|
33036
33054
|
// src/scripts/_lib/auto_dispatch.ts
|
|
@@ -37601,6 +37619,7 @@ function openSvgObligation(workspaceRoot3, toolCalls, recordedRaw = null) {
|
|
|
37601
37619
|
}
|
|
37602
37620
|
|
|
37603
37621
|
// src/scripts/hooks/subagent_ledger_hook.ts
|
|
37622
|
+
import { execFileSync as execFileSync9 } from "node:child_process";
|
|
37604
37623
|
import * as crypto12 from "node:crypto";
|
|
37605
37624
|
import * as fs112 from "node:fs";
|
|
37606
37625
|
import * as path117 from "node:path";
|
|
@@ -37861,6 +37880,51 @@ function appendLedgerLine(root, ts, line) {
|
|
|
37861
37880
|
fs112.appendFileSync(file, `${JSON.stringify(line)}
|
|
37862
37881
|
`, "utf8");
|
|
37863
37882
|
}
|
|
37883
|
+
var INDEX_SUBDIR = "index";
|
|
37884
|
+
function writeIndexEntry(root, ts, key, value) {
|
|
37885
|
+
if (is_replay_mode()) return;
|
|
37886
|
+
const dir = path117.join(root, LEDGER_DIR, INDEX_SUBDIR, ts.slice(0, 7));
|
|
37887
|
+
fs112.mkdirSync(dir, { recursive: true });
|
|
37888
|
+
const tmp = path117.join(dir, `.${key}.${process.pid}.tmp`);
|
|
37889
|
+
try {
|
|
37890
|
+
fs112.writeFileSync(tmp, value, "utf8");
|
|
37891
|
+
fs112.renameSync(tmp, path117.join(dir, key));
|
|
37892
|
+
} finally {
|
|
37893
|
+
fs112.rmSync(tmp, { force: true });
|
|
37894
|
+
}
|
|
37895
|
+
}
|
|
37896
|
+
function readIndexEntry(root, key, now2) {
|
|
37897
|
+
const prev = new Date(Date.UTC(now2.getUTCFullYear(), now2.getUTCMonth() - 1, 1));
|
|
37898
|
+
for (const month of [now2.toISOString().slice(0, 7), prev.toISOString().slice(0, 7)]) {
|
|
37899
|
+
try {
|
|
37900
|
+
return fs112.readFileSync(path117.join(root, LEDGER_DIR, INDEX_SUBDIR, month, key), "utf8");
|
|
37901
|
+
} catch {
|
|
37902
|
+
}
|
|
37903
|
+
}
|
|
37904
|
+
return null;
|
|
37905
|
+
}
|
|
37906
|
+
function headOf(dir) {
|
|
37907
|
+
try {
|
|
37908
|
+
const env = Object.fromEntries(Object.entries(process.env).filter(([k]) => !k.startsWith("GIT_")));
|
|
37909
|
+
return execFileSync9("git", ["-C", dir, "rev-parse", "HEAD"], { encoding: "utf8", timeout: 2e3, stdio: ["ignore", "pipe", "ignore"], env }).trim() || null;
|
|
37910
|
+
} catch {
|
|
37911
|
+
return null;
|
|
37912
|
+
}
|
|
37913
|
+
}
|
|
37914
|
+
function stateStamp(cwd) {
|
|
37915
|
+
let epoch = null;
|
|
37916
|
+
try {
|
|
37917
|
+
epoch = fs112.statSync(fileURLToPath59(import.meta.url)).mtimeMs;
|
|
37918
|
+
} catch {
|
|
37919
|
+
}
|
|
37920
|
+
return typeof cwd === "string" && cwd ? { head: headOf(cwd), cwd_key: refFor(cwd), epoch } : { head: null, cwd_key: null, epoch };
|
|
37921
|
+
}
|
|
37922
|
+
function stopIndexKey(sessionId3, ref) {
|
|
37923
|
+
return refFor(`subagent-stop\0${sessionId3}\0${ref}`);
|
|
37924
|
+
}
|
|
37925
|
+
function recordStopIndex(root, ts, sessionId3, ref) {
|
|
37926
|
+
writeIndexEntry(root, ts, stopIndexKey(sessionId3, ref), "");
|
|
37927
|
+
}
|
|
37864
37928
|
var WALL_CLOCK_ARMS_MS = [
|
|
37865
37929
|
{ label: "5m", ms: 5 * 60 * 1e3 },
|
|
37866
37930
|
{ label: "15m", ms: 15 * 60 * 1e3 },
|
|
@@ -38028,8 +38092,13 @@ function handleStop(root, payload, nowIso, sessionId3) {
|
|
|
38028
38092
|
// Beside the count, never instead of it: the count says how wrong the
|
|
38029
38093
|
// candidate was, this says whether it was aimed at the envelope.
|
|
38030
38094
|
envelope_field_hits: parse.field_hits,
|
|
38031
|
-
concurrent_open: countOpen(root)
|
|
38095
|
+
concurrent_open: countOpen(root),
|
|
38096
|
+
...stateStamp(payload["cwd"])
|
|
38032
38097
|
});
|
|
38098
|
+
try {
|
|
38099
|
+
if (sessionId3 !== null) recordStopIndex(root, nowIso, sessionId3, ref);
|
|
38100
|
+
} catch {
|
|
38101
|
+
}
|
|
38033
38102
|
}
|
|
38034
38103
|
function processEnvelope3(envelope, consumerRoot) {
|
|
38035
38104
|
try {
|
|
@@ -40819,12 +40888,13 @@ function markerFile(repoRoot, runId) {
|
|
|
40819
40888
|
function writeQuotaParked(repoRoot, runId, providers, now2 = () => /* @__PURE__ */ new Date(), source = "council") {
|
|
40820
40889
|
const file = markerFile(repoRoot, runId);
|
|
40821
40890
|
const existing = readMarker(file);
|
|
40891
|
+
const host2 = source === "host";
|
|
40822
40892
|
const merged = [.../* @__PURE__ */ new Set([...existing?.providers ?? [], ...providers])].sort();
|
|
40823
40893
|
const marker = {
|
|
40824
40894
|
run_id: runId,
|
|
40825
40895
|
providers: merged,
|
|
40826
|
-
parked_at: existing?.parked_at ?? now2().toISOString(),
|
|
40827
|
-
source: existing?.source ?? source
|
|
40896
|
+
parked_at: (host2 ? null : existing?.parked_at) ?? now2().toISOString(),
|
|
40897
|
+
source: host2 ? source : existing?.source ?? source
|
|
40828
40898
|
};
|
|
40829
40899
|
fs126.mkdirSync(path130.dirname(file), { recursive: true });
|
|
40830
40900
|
fs126.writeFileSync(file, `${JSON.stringify(marker, null, 2)}
|
|
@@ -40833,20 +40903,18 @@ function writeQuotaParked(repoRoot, runId, providers, now2 = () => /* @__PURE__
|
|
|
40833
40903
|
}
|
|
40834
40904
|
var HOST_RATE_WINDOW_MS = 5 * 36e5;
|
|
40835
40905
|
function recentHostMarker(repoRoot, nowMs = Date.now(), windowMs = HOST_RATE_WINDOW_MS) {
|
|
40836
|
-
|
|
40906
|
+
return allMarkers(repoRoot).some((m) => {
|
|
40907
|
+
const age = nowMs - Date.parse(m.parked_at);
|
|
40908
|
+
return m.source === "host" && age >= 0 && age < windowMs;
|
|
40909
|
+
});
|
|
40910
|
+
}
|
|
40911
|
+
function allMarkers(repoRoot) {
|
|
40912
|
+
const dir = path130.join(repoRoot, QUOTA_PARKED_DIR_REL);
|
|
40837
40913
|
try {
|
|
40838
|
-
|
|
40914
|
+
return fs126.readdirSync(dir).flatMap((n) => n.endsWith(".json") ? readMarker(path130.join(dir, n)) ?? [] : []);
|
|
40839
40915
|
} catch {
|
|
40840
|
-
return
|
|
40841
|
-
}
|
|
40842
|
-
for (const name of names) {
|
|
40843
|
-
if (!name.endsWith(".json")) continue;
|
|
40844
|
-
const m = readMarker(path130.join(repoRoot, QUOTA_PARKED_DIR_REL, name));
|
|
40845
|
-
if (m === null || m.source !== "host") continue;
|
|
40846
|
-
const at = Date.parse(m.parked_at);
|
|
40847
|
-
if (Number.isFinite(at) && nowMs - at >= 0 && nowMs - at < windowMs) return true;
|
|
40916
|
+
return [];
|
|
40848
40917
|
}
|
|
40849
|
-
return false;
|
|
40850
40918
|
}
|
|
40851
40919
|
function readMarker(file) {
|
|
40852
40920
|
try {
|
|
@@ -40916,72 +40984,19 @@ function isObject23(v) {
|
|
|
40916
40984
|
}
|
|
40917
40985
|
var DISPATCH_TOOL_NAMES2 = /* @__PURE__ */ new Set(["Agent", "Task"]);
|
|
40918
40986
|
var RESUME_TOOL_NAMES = /* @__PURE__ */ new Set(["SendMessage"]);
|
|
40919
|
-
var STOP_SCAN_BYTES = 1024 * 1024;
|
|
40920
|
-
function tailOf(file) {
|
|
40921
|
-
let fd;
|
|
40922
|
-
try {
|
|
40923
|
-
fd = fs127.openSync(file, "r");
|
|
40924
|
-
} catch {
|
|
40925
|
-
return "";
|
|
40926
|
-
}
|
|
40927
|
-
try {
|
|
40928
|
-
const size = fs127.fstatSync(fd).size;
|
|
40929
|
-
const length = Math.min(size, STOP_SCAN_BYTES);
|
|
40930
|
-
const buf = Buffer.alloc(length);
|
|
40931
|
-
fs127.readSync(fd, buf, 0, length, size - length);
|
|
40932
|
-
return buf.toString("utf8");
|
|
40933
|
-
} finally {
|
|
40934
|
-
fs127.closeSync(fd);
|
|
40935
|
-
}
|
|
40936
|
-
}
|
|
40937
|
-
function stoppedInSession(root, ref, sessionId3, now2) {
|
|
40938
|
-
const prev = new Date(Date.UTC(now2.getUTCFullYear(), now2.getUTCMonth() - 1, 1));
|
|
40939
|
-
for (const month of [now2.toISOString().slice(0, 7), prev.toISOString().slice(0, 7)]) {
|
|
40940
|
-
for (const line of tailOf(path131.join(root, LEDGER_DIR, `${month}.jsonl`)).split("\n")) {
|
|
40941
|
-
if (!line.includes(ref)) continue;
|
|
40942
|
-
try {
|
|
40943
|
-
const rec = JSON.parse(line);
|
|
40944
|
-
if (rec["event"] === "subagent_stop" && rec["ref"] === ref && rec["session_id"] === sessionId3) {
|
|
40945
|
-
return true;
|
|
40946
|
-
}
|
|
40947
|
-
} catch {
|
|
40948
|
-
}
|
|
40949
|
-
}
|
|
40950
|
-
}
|
|
40951
|
-
return false;
|
|
40952
|
-
}
|
|
40953
40987
|
var NAME_MAX = 128;
|
|
40954
40988
|
function nameKey(sessionId3, name) {
|
|
40955
40989
|
return refFor(`subagent-name\0${sessionId3}\0${name}`);
|
|
40956
40990
|
}
|
|
40957
|
-
function refForName(root, name, sessionId3, now2) {
|
|
40958
|
-
if (name.length > NAME_MAX) return null;
|
|
40959
|
-
const key = nameKey(sessionId3, name);
|
|
40960
|
-
let found = null;
|
|
40961
|
-
const prev = new Date(Date.UTC(now2.getUTCFullYear(), now2.getUTCMonth() - 1, 1));
|
|
40962
|
-
for (const month of [prev.toISOString().slice(0, 7), now2.toISOString().slice(0, 7)]) {
|
|
40963
|
-
for (const line of tailOf(path131.join(root, LEDGER_DIR, `${month}.jsonl`)).split("\n")) {
|
|
40964
|
-
if (!line.includes("subagent_named")) continue;
|
|
40965
|
-
try {
|
|
40966
|
-
const rec = JSON.parse(line);
|
|
40967
|
-
if (rec["event"] === "subagent_named" && rec["name_key"] === key && typeof rec["ref"] === "string") {
|
|
40968
|
-
found = rec["ref"];
|
|
40969
|
-
}
|
|
40970
|
-
} catch {
|
|
40971
|
-
}
|
|
40972
|
-
}
|
|
40973
|
-
}
|
|
40974
|
-
return found;
|
|
40975
|
-
}
|
|
40976
40991
|
function classifySend(root, toolInput, sessionId3, now2 = /* @__PURE__ */ new Date()) {
|
|
40977
40992
|
const input = isObject23(toolInput) ? toolInput : {};
|
|
40978
40993
|
const recipient = input["to"];
|
|
40979
40994
|
if (typeof recipient !== "string" || recipient === "") return "message_or_resume";
|
|
40980
40995
|
if (sessionId3 === null || sessionId3 === "") return "message_or_resume";
|
|
40981
|
-
const ref = input["recipient_kind"]
|
|
40982
|
-
if (ref
|
|
40996
|
+
const ref = input["recipient_kind"] !== "name" ? refFor(recipient) : recipient.length > NAME_MAX ? null : readIndexEntry(root, nameKey(sessionId3, recipient), now2);
|
|
40997
|
+
if (!ref) return "message_or_resume";
|
|
40983
40998
|
if (readOpenRecords(root).has(ref)) return "message_running";
|
|
40984
|
-
return
|
|
40999
|
+
return readIndexEntry(root, stopIndexKey(sessionId3, ref), now2) === null ? "message_or_resume" : "resume";
|
|
40985
41000
|
}
|
|
40986
41001
|
function recordNamedSpawn(root, payload, sessionId3, nowIso) {
|
|
40987
41002
|
const input = isObject23(payload["tool_input"]) ? payload["tool_input"] : {};
|
|
@@ -40989,8 +41004,10 @@ function recordNamedSpawn(root, payload, sessionId3, nowIso) {
|
|
|
40989
41004
|
const name = input["name"];
|
|
40990
41005
|
const agentId = result["agentId"];
|
|
40991
41006
|
if (typeof name !== "string" || name === "" || name.length > NAME_MAX || typeof agentId !== "string" || agentId === "") return;
|
|
40992
|
-
if (sessionId3
|
|
40993
|
-
|
|
41007
|
+
if (!sessionId3) return;
|
|
41008
|
+
const key = nameKey(sessionId3, name);
|
|
41009
|
+
appendLedgerLine(root, nowIso, { event: "subagent_named", ts: nowIso, ref: refFor(agentId), name_key: key, session_id: sessionId3 });
|
|
41010
|
+
writeIndexEntry(root, nowIso, key, refFor(agentId));
|
|
40994
41011
|
}
|
|
40995
41012
|
var RESUME_ADMISSION_OBSERVED = /* @__PURE__ */ new Set(["claude"]);
|
|
40996
41013
|
var CANDIDATES = [
|
|
@@ -41034,6 +41051,12 @@ function processEnvelope5(envelope, consumerRoot, deps = {}) {
|
|
|
41034
41051
|
const sessionRaw = payload["session_id"] ?? envelope["session_id"];
|
|
41035
41052
|
const sessionId3 = typeof sessionRaw === "string" ? sessionRaw : null;
|
|
41036
41053
|
const sendKind = isResume ? classifySend(consumerRoot, toolInput, sessionId3) : null;
|
|
41054
|
+
const reqName = toolInput["name"];
|
|
41055
|
+
const spawnFacts = isResume ? {} : {
|
|
41056
|
+
...stateStamp(payload["cwd"]),
|
|
41057
|
+
agent_type: typeof toolInput["subagent_type"] === "string" ? toolInput["subagent_type"] : null,
|
|
41058
|
+
...typeof reqName === "string" && reqName && reqName.length <= NAME_MAX && sessionId3 ? { name_key: nameKey(sessionId3, reqName) } : {}
|
|
41059
|
+
};
|
|
41037
41060
|
const reuse = isResume ? null : shadowReuseVerdict({
|
|
41038
41061
|
host_resume: deps.host_resume ?? probeHostCapabilities(platform).worker_resume,
|
|
41039
41062
|
workers: deps.workers ?? null,
|
|
@@ -41064,6 +41087,7 @@ function processEnvelope5(envelope, consumerRoot, deps = {}) {
|
|
|
41064
41087
|
// against a threshold that counts runs.
|
|
41065
41088
|
...sendKind === "message_running" ? {} : { candidates: verdicts.map((v) => ({ label: v.label, would_deny: v.would_deny, on: v.on })) },
|
|
41066
41089
|
dispatch_kind: sendKind ?? "spawn",
|
|
41090
|
+
...spawnFacts,
|
|
41067
41091
|
resume_admission: platform !== null && RESUME_ADMISSION_OBSERVED.has(platform) ? "counted" : "unobserved",
|
|
41068
41092
|
...reuse === null ? {} : { reuse },
|
|
41069
41093
|
// A recent host-sourced rate marker: a new spawn would have waited.
|
|
@@ -44050,7 +44074,7 @@ function main71(argv) {
|
|
|
44050
44074
|
if (!_concern_matches_tool(concern, tool_name)) {
|
|
44051
44075
|
continue;
|
|
44052
44076
|
}
|
|
44053
|
-
const concern_envelope = shapes.shapeFor(keep_classes, egressViewFor(concern));
|
|
44077
|
+
const concern_envelope = applyPayloadFields(concern, shapes.shapeFor(keep_classes, egressViewFor(concern)));
|
|
44054
44078
|
const stubs_served = shapes.stubsFor(keep_classes);
|
|
44055
44079
|
const served_classes = shapes.servedBy(keep_classes);
|
|
44056
44080
|
const concern_started = _now_iso3();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
886ab561301c6376b605aeed89a965b978dae593df52a5c774ba27349860d298 dispatch.js
|
|
@@ -46,6 +46,9 @@
|
|
|
46
46
|
import * as fs from 'node:fs';
|
|
47
47
|
import * as path from 'node:path';
|
|
48
48
|
import { _claude_paths_plan } from './claudePathsPlan.js';
|
|
49
|
+
// Re-exported for `install.ts`, which sits past the source-size ceiling and so
|
|
50
|
+
// reaches it through the namespace it already imports instead of a new line.
|
|
51
|
+
export { onlyDeployed } from './loggedWrites.js';
|
|
49
52
|
import { parseFrontmatter } from './ruleInScope.js';
|
|
50
53
|
/**
|
|
51
54
|
* Frontmatter keys the rewrite must carry across, and why each one.
|
|
@@ -109,8 +112,8 @@ export function _withPreservedKeys(rendered, original) {
|
|
|
109
112
|
* extraction and never up through a baseline raise. So the caller gets one call
|
|
110
113
|
* and a list of strings.
|
|
111
114
|
*/
|
|
112
|
-
export function rewriteAndReport(rulesDir, quiet, info, warn, wrappers, preserved = new Set()) {
|
|
113
|
-
const result = rewriteClaudeRules(rulesDir, preserved);
|
|
115
|
+
export function rewriteAndReport(rulesDir, quiet, info, warn, wrappers, preserved = new Set(), onWrite) {
|
|
116
|
+
const result = rewriteClaudeRules(rulesDir, preserved, onWrite);
|
|
114
117
|
// The flat-command wrapper report rides along rather than sitting at the
|
|
115
118
|
// call site: `install.ts` is thousands of lines past
|
|
116
119
|
// `check_source_size_budget`'s ceiling, and this module is the one place
|
|
@@ -205,8 +208,11 @@ export function renderClaudeRule(sourceText) {
|
|
|
205
208
|
* disappearing from the frontmatter.
|
|
206
209
|
*
|
|
207
210
|
* Returns counts rather than printing. The caller owns the reporting surface.
|
|
211
|
+
* `onWrite` receives each rewritten path, so the installer can log it: the
|
|
212
|
+
* transaction log is read back as proof the bytes on disk are ours, and a
|
|
213
|
+
* write it never saw would leave every rewritten rule unprovable.
|
|
208
214
|
*/
|
|
209
|
-
export function rewriteClaudeRules(rulesDir, preserved = new Set()) {
|
|
215
|
+
export function rewriteClaudeRules(rulesDir, preserved = new Set(), onWrite) {
|
|
210
216
|
const result = { rewritten: 0, scoped: [], dropped: [], failed: [] };
|
|
211
217
|
let entries;
|
|
212
218
|
try {
|
|
@@ -258,6 +264,7 @@ export function rewriteClaudeRules(rulesDir, preserved = new Set()) {
|
|
|
258
264
|
});
|
|
259
265
|
continue;
|
|
260
266
|
}
|
|
267
|
+
onWrite?.(full);
|
|
261
268
|
result.rewritten += 1;
|
|
262
269
|
}
|
|
263
270
|
const stem = name.slice(0, -3);
|
package/dist/install/conflict.js
CHANGED
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import { existsSync } from 'node:fs';
|
|
18
18
|
import { sha256File } from './plan.js';
|
|
19
|
-
import {
|
|
19
|
+
import { loggedWriteDigests, wroteTheseBytes } from './loggedWrites.js';
|
|
20
|
+
import { isLedgerMigration, logProofApplies, sidecarPathFor } from './preserve.js';
|
|
20
21
|
import { classifyOwnership, ledgerListedPaths, recordedHashesWithLedger, } from './recordedOwnership.js';
|
|
21
22
|
/**
|
|
22
23
|
* Decide what to do with a single planned target.
|
|
@@ -161,8 +162,10 @@ export const CONFLICT_BATCH_THRESHOLD = 5;
|
|
|
161
162
|
*
|
|
162
163
|
* `recorded` is injectable for tests; by default it is read from the
|
|
163
164
|
* manifest at `plan.root`, with the user-scoped ownership ledger laid over it.
|
|
165
|
+
* `logged` likewise; by default it is the install transaction log, opened only
|
|
166
|
+
* for an entry `logProofApplies` to.
|
|
164
167
|
*/
|
|
165
|
-
export function computeConflicts(plan, recordedOverride) {
|
|
168
|
+
export function computeConflicts(plan, recordedOverride, loggedOverride) {
|
|
166
169
|
// Force returns before the manifest is read. As a default parameter the
|
|
167
170
|
// map was built at call entry and discarded on the next line, so every
|
|
168
171
|
// force-mode plan paid a read and a YAML parse for nothing.
|
|
@@ -173,6 +176,7 @@ export function computeConflicts(plan, recordedOverride) {
|
|
|
173
176
|
// digests never reaches the branch that needs this, and an unconditional
|
|
174
177
|
// read would charge every plan for an answer most of them discard.
|
|
175
178
|
let ledgerFiles = null;
|
|
179
|
+
let logged;
|
|
176
180
|
const ledgerLists = (p) => {
|
|
177
181
|
ledgerFiles ??= ledgerListedPaths();
|
|
178
182
|
return ledgerFiles.has(p);
|
|
@@ -197,6 +201,24 @@ export function computeConflicts(plan, recordedOverride) {
|
|
|
197
201
|
const ownership = classifyOwnership(recorded.get(entry.path), onDisk);
|
|
198
202
|
if (ownership === 'recorded-unchanged')
|
|
199
203
|
continue;
|
|
204
|
+
// The writer's transaction-log proof, under the writer's own
|
|
205
|
+
// condition (`logProofApplies`): where it holds and the log records
|
|
206
|
+
// these bytes, the writer replaces the file, so the preview must
|
|
207
|
+
// not name it.
|
|
208
|
+
const recordedSha = recorded.get(entry.path);
|
|
209
|
+
const unproven = {
|
|
210
|
+
exists: true,
|
|
211
|
+
recordedSha256: recordedSha,
|
|
212
|
+
onDiskSha256: onDisk,
|
|
213
|
+
force: false,
|
|
214
|
+
ledgerListed: ledgerLists(entry.path),
|
|
215
|
+
recordedIsStaged: typeof recordedSha === 'string' && recordedSha === recorded.get(sidecarPathFor(entry.path)),
|
|
216
|
+
};
|
|
217
|
+
if (logProofApplies(unproven)) {
|
|
218
|
+
logged ??= loggedOverride ?? loggedWriteDigests();
|
|
219
|
+
if (wroteTheseBytes(entry.path, onDisk, logged))
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
200
222
|
if (ownership === 'unknown' && plan.policy.knownPaths.has(entry.path))
|
|
201
223
|
continue;
|
|
202
224
|
// CANDIDACY, not the verdict, and it is computed BEFORE the
|
|
@@ -21,7 +21,8 @@ import * as fs from 'node:fs';
|
|
|
21
21
|
import * as os from 'node:os';
|
|
22
22
|
import * as path from 'node:path';
|
|
23
23
|
import { mkdirp, pathExists, resolvePath, sha256OfFile } from './fsPrimitives.js';
|
|
24
|
-
import { EXIT_COMPLETED_WITH_CONFLICTS, conflictSummaryMessage, decideDeployWrite, foreignSidecarMessage, isLedgerMigration, migrationPreservedMessage, preservedFileMessage, sidecarPathFor, } from './preserve.js';
|
|
24
|
+
import { EXIT_COMPLETED_WITH_CONFLICTS, conflictSummaryMessage, decideDeployWrite, foreignSidecarMessage, isLedgerMigration, logProofApplies, migrationPreservedMessage, preservedFileMessage, sidecarPathFor, } from './preserve.js';
|
|
25
|
+
import { loggedWriteDigests, wroteTheseBytes } from './loggedWrites.js';
|
|
25
26
|
import { ledgerListedPaths, recordedHashesWithLedger } from './recordedOwnership.js';
|
|
26
27
|
/**
|
|
27
28
|
* Build a tracker bound to one installer's reporting surface.
|
|
@@ -37,6 +38,7 @@ export function createConflictTracker(host) {
|
|
|
37
38
|
root: null,
|
|
38
39
|
recorded: null,
|
|
39
40
|
ledgerFiles: null,
|
|
41
|
+
logged: null,
|
|
40
42
|
preserved: [],
|
|
41
43
|
migrated: new Set(),
|
|
42
44
|
staged: new Map(),
|
|
@@ -210,6 +212,7 @@ export function createConflictTracker(host) {
|
|
|
210
212
|
conflictState.root = root;
|
|
211
213
|
conflictState.recorded = null;
|
|
212
214
|
conflictState.ledgerFiles = null;
|
|
215
|
+
conflictState.logged = null;
|
|
213
216
|
conflictState.preserved = [];
|
|
214
217
|
conflictState.migrated = new Set();
|
|
215
218
|
conflictState.staged = new Map();
|
|
@@ -222,13 +225,21 @@ export function createConflictTracker(host) {
|
|
|
222
225
|
*/
|
|
223
226
|
resolve(target, force, would) {
|
|
224
227
|
const exists = pathExists(target);
|
|
225
|
-
const
|
|
228
|
+
const recordedSha256 = exists ? recordedHashFor(target) : undefined;
|
|
229
|
+
const unproven = {
|
|
226
230
|
exists,
|
|
227
|
-
recordedSha256
|
|
231
|
+
recordedSha256,
|
|
228
232
|
onDiskSha256: exists ? sha256OfFile(target) : null,
|
|
229
233
|
force,
|
|
230
234
|
ledgerListed: exists && ledgerLists(target),
|
|
235
|
+
recordedIsStaged: typeof recordedSha256 === 'string' && recordedSha256 === recordedHashFor(sidecarPathFor(target)),
|
|
231
236
|
};
|
|
237
|
+
// The log is opened only where the record alone would preserve
|
|
238
|
+
// without cause, and read once per run: this run's own appends
|
|
239
|
+
// cannot prove a file it has not reached yet.
|
|
240
|
+
const loggedWrite = logProofApplies(unproven) &&
|
|
241
|
+
wroteTheseBytes(target, unproven.onDiskSha256, (conflictState.logged ??= loggedWriteDigests()));
|
|
242
|
+
const base = { ...unproven, loggedWrite };
|
|
232
243
|
// The packaged digest costs a temp write and a tag, so it is
|
|
233
244
|
// computed only for the targets that can consume it. On a tree
|
|
234
245
|
// where every ledger-listed path carries a digest — which is every
|