@sema-agent/core 5.57.0 → 5.58.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/CHANGELOG.md +48 -0
- package/dist/agents/cascade.d.ts +1 -1
- package/dist/agents/cumulative-stats.d.ts +1 -1
- package/dist/agents/observer.d.ts +2 -2
- package/dist/agents/peer-admission.d.ts +1 -1
- package/dist/agents/retain-ledger.d.ts +2 -2
- package/dist/agents/roster-store.d.ts +8 -8
- package/dist/agents/send-message-tool.d.ts +2 -2
- package/dist/agents/subagent-steps.d.ts +1 -1
- package/dist/agents/subagent.d.ts +13 -13
- package/dist/agents/team.d.ts +5 -5
- package/dist/agents/tool-filter.d.ts +2 -2
- package/dist/agents/verify.d.ts +1 -1
- package/dist/bench/metrics.d.ts +35 -35
- package/dist/brain/degrading.d.ts +1 -1
- package/dist/brain/errors.d.ts +3 -3
- package/dist/brain/reasoning.d.ts +2 -2
- package/dist/brain/repetition.d.ts +1 -1
- package/dist/brain/status-sink.d.ts +2 -2
- package/dist/brain/stream-shared.d.ts +1 -1
- package/dist/config/catalog.d.ts +5 -5
- package/dist/core/arg-summary.d.ts +4 -4
- package/dist/core/ask-class.d.ts +2 -2
- package/dist/core/ask-question.d.ts +1 -1
- package/dist/core/auto-compaction.d.ts +15 -15
- package/dist/core/auto-mode.d.ts +5 -5
- package/dist/core/background-agent-store.d.ts +20 -20
- package/dist/core/background-shell.d.ts +4 -4
- package/dist/core/checkpoint-store.d.ts +35 -27
- package/dist/core/context-edit.d.ts +1 -1
- package/dist/core/context-guard.d.ts +1 -1
- package/dist/core/exec-output-tail.d.ts +6 -6
- package/dist/core/file-snapshot-store.d.ts +8 -8
- package/dist/core/git-worktree-env.d.ts +3 -3
- package/dist/core/governance-codes.js +2 -0
- package/dist/core/hooks.d.ts +73 -33
- package/dist/core/hooks.js +87 -25
- package/dist/core/image-downsample.d.ts +1 -1
- package/dist/core/locked-config.d.ts +1 -1
- package/dist/core/lsp.d.ts +1 -1
- package/dist/core/mailbox-store.d.ts +1 -1
- package/dist/core/mcp.d.ts +3 -3
- package/dist/core/memory-engine/consolidation-driver.d.ts +207 -0
- package/dist/core/memory-engine/consolidation-driver.js +378 -0
- package/dist/core/memory-engine/consolidation.d.ts +46 -2
- package/dist/core/memory-engine/consolidation.js +1 -0
- package/dist/core/memory-engine/data-plane.d.ts +1 -1
- package/dist/core/memory-engine/distiller.d.ts +550 -0
- package/dist/core/memory-engine/distiller.js +598 -0
- package/dist/core/memory-engine/dual-root.d.ts +1 -1
- package/dist/core/memory-engine/engine.d.ts +47 -3
- package/dist/core/memory-engine/engine.js +37 -3
- package/dist/core/memory-engine/file-backend.d.ts +1 -1
- package/dist/core/memory-engine/index.d.ts +4 -2
- package/dist/core/memory-engine/index.js +4 -2
- package/dist/core/memory-engine/origin-clearance.d.ts +1 -1
- package/dist/core/memory-engine/scope-contract.d.ts +4 -4
- package/dist/core/memory-engine/sync-client.d.ts +16 -16
- package/dist/core/memory-engine/sync.d.ts +4 -4
- package/dist/core/memory-recall.d.ts +1 -1
- package/dist/core/memory.d.ts +2 -2
- package/dist/core/permission-rule-consent.d.ts +185 -36
- package/dist/core/permission-rule-consent.js +219 -44
- package/dist/core/permission-rule-model.d.ts +194 -31
- package/dist/core/permission-rule-model.js +93 -35
- package/dist/core/permission-rules.d.ts +9 -9
- package/dist/core/remote-env.d.ts +8 -8
- package/dist/core/roles.d.ts +3 -3
- package/dist/core/roles.js +1 -0
- package/dist/core/runner/assemble-result.d.ts +2 -2
- package/dist/core/runner/compaction-call-options.d.ts +3 -3
- package/dist/core/runner/memory-consolidation-driver.d.ts +49 -0
- package/dist/core/runner/memory-consolidation-driver.js +60 -0
- package/dist/core/runner/memory-consolidation.d.ts +1 -1
- package/dist/core/runner/prepare-config-doors.d.ts +3 -3
- package/dist/core/runner/prepare-task.d.ts +21 -21
- package/dist/core/runner/prepare-task.js +21 -14
- package/dist/core/runner/prepare-workspace-restore.d.ts +2 -2
- package/dist/core/runner/runtask.d.ts +11 -11
- package/dist/core/runner/session-rule-policy.d.ts +1 -1
- package/dist/core/runner/teardown-bounded.d.ts +1 -1
- package/dist/core/runner/tool-disclosure.d.ts +2 -2
- package/dist/core/runner/turn-attachments.d.ts +11 -11
- package/dist/core/scheduler.d.ts +5 -5
- package/dist/core/secret-env.d.ts +1 -1
- package/dist/core/sensitive-path-policy.d.ts +1 -1
- package/dist/core/session-policy-store.d.ts +2 -2
- package/dist/core/session-reconcile.d.ts +2 -2
- package/dist/core/session-store.d.ts +3 -3
- package/dist/core/session.d.ts +1 -1
- package/dist/core/shutdown-debug.d.ts +2 -2
- package/dist/core/side-query.d.ts +2 -2
- package/dist/core/spec-contract.d.ts +1 -1
- package/dist/core/store-contracts/contract-harness.d.ts +2 -2
- package/dist/core/store-contracts/contract-kit-version.d.ts +2 -2
- package/dist/core/store-contracts/mailbox-store-contract.d.ts +1 -1
- package/dist/core/store-contracts/mailbox-store-contract.js +1 -1
- package/dist/core/task-notification.d.ts +5 -5
- package/dist/core/task-registry-agent.d.ts +12 -12
- package/dist/core/task-registry-monitor.d.ts +1 -1
- package/dist/core/task-registry-shared.d.ts +41 -41
- package/dist/core/task-registry.d.ts +12 -12
- package/dist/core/tool-detach.d.ts +2 -2
- package/dist/core/tool-errors.d.ts +3 -3
- package/dist/core/tool-policy.d.ts +55 -28
- package/dist/core/tool-result-budget.d.ts +1 -1
- package/dist/core/tool-result-store.d.ts +2 -2
- package/dist/core/tools.d.ts +1 -1
- package/dist/core/trace.d.ts +26 -23
- package/dist/core/types.d.ts +123 -70
- package/dist/core/untrusted-egress.d.ts +1 -1
- package/dist/core/untrusted-text.d.ts +7 -7
- package/dist/core/wiring-manifest.d.ts +5 -5
- package/dist/core/workflow-journal-store.d.ts +14 -14
- package/dist/core/workflow-run-store-contract.d.ts +1 -1
- package/dist/core/workflow-run-store-contract.js +1 -1
- package/dist/core/workflow-run-store.d.ts +4 -4
- package/dist/engine/compaction/compaction.d.ts +3 -3
- package/dist/engine/compaction/utils.d.ts +2 -2
- package/dist/engine/execution-env/kill-tree.d.ts +1 -1
- package/dist/engine/execution-env/node-execution-env.d.ts +8 -8
- package/dist/engine/harness/agent-harness.d.ts +6 -6
- package/dist/engine/harness/messages.d.ts +1 -1
- package/dist/engine/harness/types.d.ts +10 -10
- package/dist/engine/llm/types.d.ts +14 -14
- package/dist/engine/loop/agent-loop.d.ts +3 -3
- package/dist/engine/loop/types.d.ts +4 -4
- package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
- package/dist/engine/session/import-validate.d.ts +1 -1
- package/dist/engine/session/log-digest.d.ts +1 -1
- package/dist/engine/session/memory-repo.d.ts +2 -2
- package/dist/engine/session/session.d.ts +4 -4
- package/dist/fixtures/index.d.ts +4 -4
- package/dist/index.d.ts +5 -4
- package/dist/index.js +3 -2
- package/dist/orchestration/goal.d.ts +1 -1
- package/dist/orchestration/run-spec.d.ts +1 -1
- package/dist/orchestration/run-workflow-tool.d.ts +12 -12
- package/dist/orchestration/workflow-governance.d.ts +4 -4
- package/dist/orchestration/workflow-observe.d.ts +1 -1
- package/dist/orchestration/workflow-script-runner.d.ts +1 -1
- package/dist/orchestration/workflow-script-store.d.ts +9 -9
- package/dist/orchestration/workflow-size-guideline.d.ts +1 -1
- package/dist/orchestration/workflow-types.d.ts +5 -5
- package/dist/orchestration/workflow.d.ts +10 -10
- package/dist/prompt-assembly/artifact-store.d.ts +1 -1
- package/dist/prompt-assembly/artifact.d.ts +1 -1
- package/dist/prompt-assembly/assemble.d.ts +1 -1
- package/dist/prompt-assembly/composer.d.ts +2 -2
- package/dist/prompt-assembly/epoch.d.ts +2 -2
- package/dist/prompt-assembly/event-registry.d.ts +1 -1
- package/dist/prompt-assembly/explain.d.ts +3 -3
- package/dist/prompt-assembly/tool-catalog.d.ts +1 -1
- package/dist/prompt-assembly/turn-snapshot.d.ts +4 -4
- package/dist/prompt-assembly/types.d.ts +12 -12
- package/dist/prompts/coordinator.d.ts +1 -1
- package/dist/prompts/default.d.ts +8 -8
- package/dist/prompts/simple-sections.d.ts +3 -3
- package/dist/prompts/supervisor.d.ts +2 -2
- package/dist/scenarios/full-body.d.ts +3 -3
- package/dist/scenarios/scenario-registry.d.ts +1 -1
- package/dist/stores/cc/sidecar-transcript.d.ts +3 -3
- package/dist/stores/file/fs-atomic.d.ts +2 -2
- package/dist/stores/file/index.d.ts +1 -1
- package/dist/stores/file/session-store.d.ts +2 -2
- package/dist/stores/file/workflow-journal-store.d.ts +4 -4
- package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -1
- package/dist/tools/fs/encoding.d.ts +4 -4
- package/dist/tools/fs/fs-bash.d.ts +3 -3
- package/dist/tools/fs/fs-pdf.d.ts +1 -1
- package/dist/tools/fs/fs-shared.d.ts +6 -6
- package/dist/tools/fs/index.d.ts +2 -2
- package/dist/tools/fs/notebook.d.ts +1 -1
- package/dist/tools/fs/pdf.d.ts +1 -1
- package/dist/tools/fs/read-deny.d.ts +1 -1
- package/dist/tools/fs/safety.d.ts +9 -9
- package/dist/tools/fs/search.d.ts +2 -2
- package/dist/tools/monitor.d.ts +3 -3
- package/dist/tools/task-list.d.ts +2 -2
- package/dist/tools/web.d.ts +4 -4
- package/dist/tools/worktree.d.ts +5 -5
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +56 -3
package/dist/core/hooks.js
CHANGED
|
@@ -253,17 +253,7 @@ export function normalizeOrgGateVerdict(answer, unreadable) {
|
|
|
253
253
|
return clean({ status: "unavailable", disclosures: [unreadable] });
|
|
254
254
|
return clean({ status: "available", verdict: clean({ behavior: behavior, rule }), ...revisionCell });
|
|
255
255
|
}
|
|
256
|
-
|
|
257
|
-
if (typeof hit === "string")
|
|
258
|
-
return { hit: { rule: hit } };
|
|
259
|
-
if (!isPlainOwnRecord(hit))
|
|
260
|
-
return {};
|
|
261
|
-
if (ownDataValue(hit, "unreadable") === true)
|
|
262
|
-
return { unreadable: true };
|
|
263
|
-
const rule = ownDataValue(hit, "rule");
|
|
264
|
-
if (typeof rule !== "string")
|
|
265
|
-
return {};
|
|
266
|
-
const dots = ownDataValue(hit, "dots");
|
|
256
|
+
function copiedUsableDots(dots) {
|
|
267
257
|
let copied;
|
|
268
258
|
try {
|
|
269
259
|
if (Array.isArray(dots)) {
|
|
@@ -279,7 +269,53 @@ export function normalizePersistedRuleHit(hit) {
|
|
|
279
269
|
copied = undefined;
|
|
280
270
|
}
|
|
281
271
|
const usable = copied?.every((d) => typeof d.actor === "string" && typeof d.counter === "number" && Number.isFinite(d.counter)) === true && copied.length > 0;
|
|
282
|
-
return
|
|
272
|
+
return usable ? { dots: copied } : {};
|
|
273
|
+
}
|
|
274
|
+
export function normalizePersistedRuleHit(hit) {
|
|
275
|
+
if (typeof hit === "string")
|
|
276
|
+
return { hit: { rules: [{ rule: hit }] } };
|
|
277
|
+
if (!isPlainOwnRecord(hit))
|
|
278
|
+
return {};
|
|
279
|
+
if (ownDataValue(hit, "unreadable") === true)
|
|
280
|
+
return { unreadable: true };
|
|
281
|
+
const rulesRaw = ownDataValue(hit, "rules");
|
|
282
|
+
if (rulesRaw === undefined) {
|
|
283
|
+
const coverageRaw = ownDataValue(hit, "segmentCoverage");
|
|
284
|
+
let rows;
|
|
285
|
+
try {
|
|
286
|
+
if (Array.isArray(coverageRaw)) {
|
|
287
|
+
const walked = [];
|
|
288
|
+
for (let i = 0; i < coverageRaw.length; i++) {
|
|
289
|
+
const r = coverageRaw[i];
|
|
290
|
+
walked.push(isPlainOwnRecord(r) ? { segment: ownDataValue(r, "segment"), covered: ownDataValue(r, "covered") } : { segment: undefined, covered: undefined });
|
|
291
|
+
}
|
|
292
|
+
rows = walked.every((r) => typeof r.segment === "string" && typeof r.covered === "boolean") ? walked : undefined;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
catch {
|
|
296
|
+
rows = undefined;
|
|
297
|
+
}
|
|
298
|
+
return rows !== undefined && rows.length > 0 ? { coverage: rows.map((r) => ({ segment: r.segment, covered: r.covered })) } : {};
|
|
299
|
+
}
|
|
300
|
+
let members;
|
|
301
|
+
try {
|
|
302
|
+
if (Array.isArray(rulesRaw)) {
|
|
303
|
+
const walked = [];
|
|
304
|
+
for (let i = 0; i < rulesRaw.length; i++) {
|
|
305
|
+
const m = rulesRaw[i];
|
|
306
|
+
walked.push(isPlainOwnRecord(m) ? { rule: ownDataValue(m, "rule"), dots: ownDataValue(m, "dots") } : { rule: undefined, dots: undefined });
|
|
307
|
+
}
|
|
308
|
+
members = walked;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
catch {
|
|
312
|
+
members = undefined;
|
|
313
|
+
}
|
|
314
|
+
if (members === undefined || members.length === 0)
|
|
315
|
+
return {};
|
|
316
|
+
if (!members.every((m) => typeof m.rule === "string"))
|
|
317
|
+
return {};
|
|
318
|
+
return { hit: { rules: members.map((m) => ({ rule: m.rule, ...copiedUsableDots(m.dots) })) } };
|
|
283
319
|
}
|
|
284
320
|
function preToolUseCrashReason(subject, err) {
|
|
285
321
|
const raw = err instanceof Error ? err.message.trim() || err.name : String(err);
|
|
@@ -672,6 +708,7 @@ export async function runToolGate(input) {
|
|
|
672
708
|
}
|
|
673
709
|
const persistedRuleMandate = persistedRuleMandateOf(input);
|
|
674
710
|
let personalEvidence = { dotsAbsent: input.persistedRules === undefined ? "not_wired" : "not_adjudicated" };
|
|
711
|
+
let laneCoverage;
|
|
675
712
|
if (input.persistedRules &&
|
|
676
713
|
!orgRealApprovalRequired &&
|
|
677
714
|
decision.action === "ask" &&
|
|
@@ -689,21 +726,44 @@ export async function runToolGate(input) {
|
|
|
689
726
|
}
|
|
690
727
|
return await settleOrgVerdictWithin(pendingHit.then(normalizePersistedRuleHit).catch(() => ({ unreadable: true })), { unreadable: true }, { ...(input.abortSignal !== undefined ? { signal: input.abortSignal } : {}), timeoutMs: ORG_ADJUDICATION_TIMEOUT_MS });
|
|
691
728
|
})();
|
|
692
|
-
const
|
|
693
|
-
|
|
729
|
+
const hitRules = answer.hit?.rules;
|
|
730
|
+
laneCoverage = answer.coverage;
|
|
694
731
|
personalEvidence = { dotsAbsent: answer.unreadable === true ? "unavailable" : "no_match" };
|
|
695
|
-
|
|
732
|
+
const disclosedRuleSet = (rules) => {
|
|
733
|
+
const shown = rules.slice(0, 5).map((r) => inlineUntrusted(r.rule, 200));
|
|
734
|
+
const rest = rules.length - shown.length;
|
|
735
|
+
return rest > 0 ? `${shown.join(", ")} and ${rest} more` : shown.join(", ");
|
|
736
|
+
};
|
|
737
|
+
const unionDotsOf = (rules) => {
|
|
738
|
+
const seen = new Set();
|
|
739
|
+
const union = [];
|
|
740
|
+
for (const r of rules) {
|
|
741
|
+
if (r.dots === undefined || r.dots.length === 0)
|
|
742
|
+
return { dotsAbsent: "not_reported" };
|
|
743
|
+
for (const d of r.dots) {
|
|
744
|
+
const key = JSON.stringify([d.actor, d.counter]);
|
|
745
|
+
if (!seen.has(key)) {
|
|
746
|
+
seen.add(key);
|
|
747
|
+
union.push(d);
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
return { dots: union };
|
|
752
|
+
};
|
|
753
|
+
if (hitRules !== undefined && persistedRuleMandate === undefined && decision.matchedAskRule === undefined) {
|
|
696
754
|
decision = {
|
|
697
755
|
action: "allow",
|
|
698
|
-
message:
|
|
756
|
+
message: hitRules.length === 1
|
|
757
|
+
? `a persisted allow rule (${disclosedRuleSet(hitRules)}) covers this call`
|
|
758
|
+
: `persisted allow rules (${disclosedRuleSet(hitRules)}) cover every segment of this call`,
|
|
699
759
|
decisionReason: "persisted_rule",
|
|
700
760
|
...(policyRewrite !== undefined ? { updatedInput: policyRewrite } : {}),
|
|
701
761
|
};
|
|
702
|
-
await notifier.notifyAsync(() => input.persistedRules?.onResolved?.({ toolName: req.toolName, toolCallId,
|
|
762
|
+
await notifier.notifyAsync(() => input.persistedRules?.onResolved?.({ toolName: req.toolName, toolCallId, rules: hitRules.map((r) => r.rule) }), "toolGate.persistedRuleResolved");
|
|
703
763
|
}
|
|
704
|
-
else if (
|
|
705
|
-
personalEvidence =
|
|
706
|
-
const shownRule =
|
|
764
|
+
else if (hitRules !== undefined) {
|
|
765
|
+
personalEvidence = unionDotsOf(hitRules);
|
|
766
|
+
const shownRule = disclosedRuleSet(hitRules);
|
|
707
767
|
const mandateNoun = persistedRuleMandate === "operator_always"
|
|
708
768
|
? "this deployment mandates per-call confirmation for shell commands (shellGate: always)"
|
|
709
769
|
: persistedRuleMandate !== undefined
|
|
@@ -712,12 +772,14 @@ export async function runToolGate(input) {
|
|
|
712
772
|
decision = {
|
|
713
773
|
...decision,
|
|
714
774
|
persistedRuleShadowed: shownRule,
|
|
715
|
-
message:
|
|
775
|
+
message: hitRules.length === 1
|
|
776
|
+
? `${decision.message !== undefined ? `${decision.message} ` : ""}(a persisted allow rule (${shownRule}) matches this call but does not clear the ask — ${mandateNoun})`
|
|
777
|
+
: `${decision.message !== undefined ? `${decision.message} ` : ""}(persisted allow rules (${shownRule}) match this call but do not clear the ask — ${mandateNoun})`,
|
|
716
778
|
};
|
|
717
779
|
}
|
|
718
780
|
}
|
|
719
781
|
if (decision.action === "ask") {
|
|
720
|
-
decision = { ...decision, ruleEvidence: mintRuleEvidence(personalEvidence) };
|
|
782
|
+
decision = { ...decision, ruleEvidence: mintRuleEvidence(personalEvidence), ...(laneCoverage !== undefined ? { segmentCoverage: laneCoverage } : {}) };
|
|
721
783
|
}
|
|
722
784
|
if (input.autoMode &&
|
|
723
785
|
!orgRealApprovalRequired &&
|
|
@@ -779,7 +841,7 @@ export async function runToolGate(input) {
|
|
|
779
841
|
? { origin: orgAskOrigin !== undefined ? `org_${orgAskOrigin}` : "policy" }
|
|
780
842
|
: undefined;
|
|
781
843
|
if (suspendAsk && decision.action === "ask") {
|
|
782
|
-
const suspended = await suspendAsk(req, currentInput, safety, undefined, realApprovalOf(decision), decision.action === "ask" ? decision.persistedRuleShadowed : undefined, decision.action === "ask" ? decision.decisionReason : undefined, decision.action === "ask" ? decision.probeReason : undefined, decision.action === "ask" ? decision.probeCause : undefined);
|
|
844
|
+
const suspended = await suspendAsk(req, currentInput, safety, undefined, realApprovalOf(decision), decision.action === "ask" ? decision.persistedRuleShadowed : undefined, decision.action === "ask" ? decision.decisionReason : undefined, decision.action === "ask" ? decision.probeReason : undefined, decision.action === "ask" ? decision.probeCause : undefined, decision.action === "ask" ? decision.segmentCoverage : undefined);
|
|
783
845
|
if (suspended) {
|
|
784
846
|
if ("parkFailed" in suspended)
|
|
785
847
|
parkFailed = suspended.parkFailed;
|
|
@@ -798,7 +860,7 @@ export async function runToolGate(input) {
|
|
|
798
860
|
req.args = outcome.presentedInput;
|
|
799
861
|
}
|
|
800
862
|
if (suspendAsk && outcome.parkDeclined && parkFailed === undefined) {
|
|
801
|
-
const suspended = await suspendAsk(req, currentInput, safety, true, realApprovalOf(decision), decision.action === "ask" ? decision.persistedRuleShadowed : undefined, decision.action === "ask" ? decision.decisionReason : undefined, decision.action === "ask" ? decision.probeReason : undefined, decision.action === "ask" ? decision.probeCause : undefined);
|
|
863
|
+
const suspended = await suspendAsk(req, currentInput, safety, true, realApprovalOf(decision), decision.action === "ask" ? decision.persistedRuleShadowed : undefined, decision.action === "ask" ? decision.decisionReason : undefined, decision.action === "ask" ? decision.probeReason : undefined, decision.action === "ask" ? decision.probeCause : undefined, decision.action === "ask" ? decision.segmentCoverage : undefined);
|
|
802
864
|
if (suspended) {
|
|
803
865
|
if ("parkFailed" in suspended)
|
|
804
866
|
parkFailed = suspended.parkFailed;
|
|
@@ -830,7 +892,7 @@ export async function runToolGate(input) {
|
|
|
830
892
|
askDenyResolution = resolved.resolution;
|
|
831
893
|
decision = resolved;
|
|
832
894
|
if (resolved.action === "deny" && resolved.approverUnavailable === true && suspendAsk && parkFailed === undefined) {
|
|
833
|
-
const suspended = await suspendAsk(req, currentInput, safety, true, realApprovalOf(askBeforeResolve), askBeforeResolve.action === "ask" ? askBeforeResolve.persistedRuleShadowed : undefined, askBeforeResolve.action === "ask" ? askBeforeResolve.decisionReason : undefined, askBeforeResolve.action === "ask" ? askBeforeResolve.probeReason : undefined, askBeforeResolve.action === "ask" ? askBeforeResolve.probeCause : undefined);
|
|
895
|
+
const suspended = await suspendAsk(req, currentInput, safety, true, realApprovalOf(askBeforeResolve), askBeforeResolve.action === "ask" ? askBeforeResolve.persistedRuleShadowed : undefined, askBeforeResolve.action === "ask" ? askBeforeResolve.decisionReason : undefined, askBeforeResolve.action === "ask" ? askBeforeResolve.probeReason : undefined, askBeforeResolve.action === "ask" ? askBeforeResolve.probeCause : undefined, askBeforeResolve.action === "ask" ? askBeforeResolve.segmentCoverage : undefined);
|
|
834
896
|
if (suspended) {
|
|
835
897
|
if ("parkFailed" in suspended)
|
|
836
898
|
parkFailed = suspended.parkFailed;
|
|
@@ -36,7 +36,7 @@ export declare const IMAGE_MAX_HEIGHT = 2000;
|
|
|
36
36
|
* replaced by an explanatory text block with the size + path; a within-limit image passes through unchanged.
|
|
37
37
|
*/
|
|
38
38
|
/**
|
|
39
|
-
* Optional image-resize seam (design/116 review CONFIRM-1,
|
|
39
|
+
* Optional image-resize seam (design/116 review CONFIRM-1, 裁定 2026-07-02 加 seam 保体验): given an
|
|
40
40
|
* over-limit image, return a smaller re-encoded one — or undefined when it can't. CC resizes with sharp
|
|
41
41
|
* (imageResizer.ts: fit within 2000x2000, JPEG quality ladder) so the model still SEES a degraded image;
|
|
42
42
|
* core must not hard-depend on a native image library, so the capability is injected (or auto-detected).
|
|
@@ -46,7 +46,7 @@ export interface LockedPreflight {
|
|
|
46
46
|
* always enforced, resolved ONCE here. With `toolPolicy` locked, the deployment's own
|
|
47
47
|
* `deps.toolPolicy` is the whole answer (a spec-supplied policy has already been refused). */
|
|
48
48
|
toolPolicy: ToolPolicy | undefined;
|
|
49
|
-
/** F-012
|
|
49
|
+
/** F-012: the effective resume-edit re-adjudication OVERRIDE, resolved lock-aware in
|
|
50
50
|
* the SAME slot as {@link toolPolicy}. With `toolPolicy` locked, a spec-supplied
|
|
51
51
|
* `basePolicyForResumeEdit` has already been refused wholesale, so this is the deployment's own
|
|
52
52
|
* `deps.basePolicyForResumeEdit` (or undefined — the caller-policy fallback then applies at the use
|
package/dist/core/lsp.d.ts
CHANGED
|
@@ -50,7 +50,7 @@ export interface LspSymbolInfo {
|
|
|
50
50
|
positionUnknown?: boolean;
|
|
51
51
|
}
|
|
52
52
|
/**
|
|
53
|
-
* RB-232
|
|
53
|
+
* RB-232: WHY a "none" result was "none". Absent `reason` = a GENUINE empty answer (the server
|
|
54
54
|
* answered null/[] — today's behavior byte-for-byte, and what an external manager returning bare
|
|
55
55
|
* `{kind:"none"}` keeps getting). The failure reasons exist because one literal "No results." used to cover
|
|
56
56
|
* both real emptiness and every transport-level fault — a findReferences that TIMED OUT read as "no
|
|
@@ -110,7 +110,7 @@ export interface MailboxStore {
|
|
|
110
110
|
maxAgeMs?: number;
|
|
111
111
|
}): Promise<number>;
|
|
112
112
|
}
|
|
113
|
-
/** RB-250② (2026-07-28
|
|
113
|
+
/** RB-250② (2026-07-28) class fix — the box age for `reap` is the MAX `sentAt`, not the
|
|
114
114
|
* last array element: `sentAt` is caller-supplied, so append order need not be time order, and taking
|
|
115
115
|
* the tail let a box whose freshest message was mid-array be swept — both bundled backends discarded
|
|
116
116
|
* a brand-new message while the CC adapter (stores/cc/mailbox-store.ts, the in-package reference)
|
package/dist/core/mcp.d.ts
CHANGED
|
@@ -209,7 +209,7 @@ export interface MaterializedMcp {
|
|
|
209
209
|
*/
|
|
210
210
|
statuses: McpServerStatus[];
|
|
211
211
|
/**
|
|
212
|
-
*
|
|
212
|
+
* RefreshMcpTools (CC 2.1.218 parity, anchored to the CLI form) — re-read the tool list of one server (or
|
|
213
213
|
* every CONNECTED server when `server` is omitted) over the EXISTING connection. NEVER dials or
|
|
214
214
|
* re-dials: a dead/never-connected server reports `not_connected`; a live listTools failure
|
|
215
215
|
* reports `failed` (the connection is left as-is). A refreshed entry carries the NEW intake
|
|
@@ -225,7 +225,7 @@ export interface MaterializedMcp {
|
|
|
225
225
|
refresh: (server?: string) => Promise<McpRefreshResult[]>;
|
|
226
226
|
dispose: () => Promise<void>;
|
|
227
227
|
}
|
|
228
|
-
/**
|
|
228
|
+
/** One per-server entry of {@link MaterializedMcp.refresh}. `added`/`removed` are namespaced
|
|
229
229
|
* (`mcp__<server>__<tool>`) names; `tools`/`axes`/`dropped` are present only on `"refreshed"`.
|
|
230
230
|
* The model-facing refresh receipt renders each `dropped` entry with ITS OWN `reason` (schema
|
|
231
231
|
* gate, same-listing name collision, …) — never a blanket label; a consumer matching that receipt
|
|
@@ -654,7 +654,7 @@ export declare function listEntryFingerprint(entry: unknown): string | undefined
|
|
|
654
654
|
* page cap — a bounded multiplier, not a new unbounded surface. Per-entry admission stays where it
|
|
655
655
|
* already is (the intake schema gate, which also drops a name a later page repeats).
|
|
656
656
|
*
|
|
657
|
-
* TIME, the reason `budgetMs` exists (
|
|
657
|
+
* TIME, the reason `budgetMs` exists (confirmed): the page cap bounds REQUESTS, not
|
|
658
658
|
* latency. Giving every page its own full request timeout would let a server that stalls each page hold
|
|
659
659
|
* a connect (or a refresh) for up to twenty timeouts — twenty minutes at the SDK's 60s default, where
|
|
660
660
|
* an unpaginated listing cost one. So the WALK gets the budget a single listing used to have: page one
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* design/376 片② — the host CONSOLIDATION DRIVER verb: one call that takes a long-accumulated,
|
|
3
|
+
* never-consolidated library to its fold fixpoint through the four engine verbs, as a PERSISTENT
|
|
4
|
+
* MULTI-CYCLE RUN.
|
|
5
|
+
*
|
|
6
|
+
* Why a run is a first-class object: under factory defaults a cold-start consolidation is a
|
|
7
|
+
* dozen-plus cycles with a hard 60-second throttle floor between them — a persistent job measured
|
|
8
|
+
* in minutes, not a call. The engine deliberately keeps NO driver state (its gate row settles per
|
|
9
|
+
* plan and clears the session count), so without a durable run account a process exit between two
|
|
10
|
+
* cycles would strand the work: no open plan to reconcile, no session edge to re-arm, and a naive
|
|
11
|
+
* re-entry would re-mint the whole plan at full model cost. The run row under the control plane is
|
|
12
|
+
* the resume seat: `runMemoryConsolidation` first looks for a PENDING run of the scope and
|
|
13
|
+
* CONTINUES it (same plan cache, same force requestId, zero new mint) — the idempotent re-entry
|
|
14
|
+
* GD-15 pins.
|
|
15
|
+
*
|
|
16
|
+
* Boundary reminders (design/339 §1.1, unchanged by this module):
|
|
17
|
+
* - the engine adjudicates and commits; this driver only proposes and schedules — every write
|
|
18
|
+
* goes through `commitConsolidationPlan`, nothing here touches the store;
|
|
19
|
+
* - the engine holds no model seat; the model reaches this module as an explicit chat function;
|
|
20
|
+
* - core still owns no timer: the throttle waits here run INSIDE a host's explicit call (or the
|
|
21
|
+
* auto lane's task-boundary tick), never on a background schedule of core's own.
|
|
22
|
+
*/
|
|
23
|
+
import type { EngineNotice } from "../types.js";
|
|
24
|
+
import { type ConsolidationGateRow, type ConsolidationRunStopReason, type MemoryConsolidationOptions } from "./consolidation.js";
|
|
25
|
+
import { type ConsolidationPlanSummary } from "./engine.js";
|
|
26
|
+
import { mintLlmConsolidationPlan, type ConsolidationDriveCycleRow, type ConsolidationDriveEngine, type ConsolidationFoldState, type DistillerChatFn, type LlmConsolidationPlan, type LlmConsolidationPlanProduct, type LlmDistillerContract } from "./distiller.js";
|
|
27
|
+
export declare const CONSOLIDATION_DRIVER_RUNS_FILE = "distiller-runs.json";
|
|
28
|
+
/** §1.6-4 — the mint archive: what was shown to the model and what it answered, verbatim, per run
|
|
29
|
+
* (the fold law's audit other-half; strict-family placement beside the plan workbook). */
|
|
30
|
+
export declare const CONSOLIDATION_DRIVER_PLANS_DIR = "distiller-plans";
|
|
31
|
+
export interface ConsolidationDriverRunRow {
|
|
32
|
+
runId: string;
|
|
33
|
+
scope: string;
|
|
34
|
+
/** The WRITER claim: every open/resume bumps this under the run
|
|
35
|
+
* store's lock, and every later write of the row is conditional on (runId, attempt) still
|
|
36
|
+
* standing — of two invocations that raced onto one scope, exactly one keeps writing; the
|
|
37
|
+
* superseded one stops with a coded error instead of silently clobbering the winner's counters
|
|
38
|
+
* or terminal state. (Model spend under a genuine concurrent double-call is still at-least-once
|
|
39
|
+
* — the claim serializes the ACCOUNT; the engine's plan-seat CAS serializes the store, and
|
|
40
|
+
* cross-node cost suppression is the engine lease seat's job.) */
|
|
41
|
+
attempt: number;
|
|
42
|
+
/** The run-scoped force credential: ONE requestId across every forced snapshot of the run (the
|
|
43
|
+
* engine dedups the FORCED audit announcement on it — one line per run). */
|
|
44
|
+
requestId: string;
|
|
45
|
+
/** The contract version of the run's surviving MINT — stamped at open, RE-stamped (with
|
|
46
|
+
* {@link model}) by a resume that re-mints. */
|
|
47
|
+
contractVersion: string;
|
|
48
|
+
/** The id that minted the run's surviving plan: stamped at open; RE-stamped on a resume that
|
|
49
|
+
* re-mints (the plan cache absent — nothing of the opening mint survived, so the current seat
|
|
50
|
+
* mints every byte this run commits). The per-attempt plan archive is the byte-level anchor
|
|
51
|
+
* either way. */
|
|
52
|
+
model: string;
|
|
53
|
+
startedAt: number;
|
|
54
|
+
state: "pending" | "settled";
|
|
55
|
+
/** Terminal only; the ONE closed set the receipt and the `_incomplete` notice share. */
|
|
56
|
+
outcome?: ConsolidationRunStopReason;
|
|
57
|
+
settledAt?: number;
|
|
58
|
+
stopDetail?: string;
|
|
59
|
+
/** The minted plan's replayable half (mint ONCE per run; each cycle filters, never re-mints). */
|
|
60
|
+
planCache?: {
|
|
61
|
+
maxInputsPerProduct: number;
|
|
62
|
+
products: LlmConsolidationPlanProduct[];
|
|
63
|
+
};
|
|
64
|
+
/** The archived mint transcript's file name under {@link CONSOLIDATION_DRIVER_PLANS_DIR}. */
|
|
65
|
+
planArchive?: string;
|
|
66
|
+
/** COMMITTED cycles only (the store moved): a refused/fuse-blocked/zero-delta cycle row does
|
|
67
|
+
* not count — the receipt's "committed cycle(s)" label and the incomplete notice's zero-cycle
|
|
68
|
+
* branch both read this number as writes. */
|
|
69
|
+
cyclesDone: number;
|
|
70
|
+
/** Store-delta superseded total across EVERY invocation of this run (the conservation wall's
|
|
71
|
+
* evidence half — see the convergence check in the verb). Accumulated per cycle AFTER the
|
|
72
|
+
* commit, so a crash between a cycle's commit and its row write loses that cycle's delta —
|
|
73
|
+
* {@link foldBaseline} is the wall's immune second witness for exactly that window. */
|
|
74
|
+
entriesSuperseded: number;
|
|
75
|
+
/** The scope's fold-state `superseded` count at run OPEN (fresh claim; absent on rows opened
|
|
76
|
+
* before the field existed). The conservation wall's STORE anchor: `final.superseded − this`
|
|
77
|
+
* attests the run's folds even when a crash lands between a cycle's commit and its account
|
|
78
|
+
* write — the seat serializes this scope's folds, so the since-open delta is this run's. */
|
|
79
|
+
foldBaseline?: {
|
|
80
|
+
superseded: number;
|
|
81
|
+
};
|
|
82
|
+
planIds: string[];
|
|
83
|
+
usage: {
|
|
84
|
+
calls: number;
|
|
85
|
+
promptTokens: number;
|
|
86
|
+
completionTokens: number;
|
|
87
|
+
retries: number;
|
|
88
|
+
truncations: number;
|
|
89
|
+
};
|
|
90
|
+
repairs: {
|
|
91
|
+
hallucinatedMembers: number;
|
|
92
|
+
duplicateMembers: number;
|
|
93
|
+
nonIntegerMembers: number;
|
|
94
|
+
emptyGroups: number;
|
|
95
|
+
oversizeGroups: number;
|
|
96
|
+
};
|
|
97
|
+
writeFailures: Array<{
|
|
98
|
+
key: string;
|
|
99
|
+
members: number;
|
|
100
|
+
reason: string | null;
|
|
101
|
+
}>;
|
|
102
|
+
residue?: Array<{
|
|
103
|
+
name: string;
|
|
104
|
+
targets: number;
|
|
105
|
+
}>;
|
|
106
|
+
/** The next moment a snapshot can pass the hard throttle (resume scheduling hint). */
|
|
107
|
+
nextEligibleAt?: number;
|
|
108
|
+
}
|
|
109
|
+
/** Host read face: the scope's latest driver run row (pending = resumable; settled = audit). */
|
|
110
|
+
export declare function readConsolidationDriverRun(controlDir: string, scope: string): ConsolidationDriverRunRow | undefined;
|
|
111
|
+
/** Archive one mint (prompts + transcript verbatim) beside the run account. The name carries the
|
|
112
|
+
* CLAIM (`attempt`): two invocations that raced onto one run each archive
|
|
113
|
+
* under their own name, so a superseded worker can never overwrite the winning transcript — the
|
|
114
|
+
* run row's `planArchive` (written under the attempt guard) names the one that counts. */
|
|
115
|
+
export declare function distillerPlanArchiveName(runId: string, attempt: number): string;
|
|
116
|
+
export declare function archiveDistillerPlan(controlDir: string, runId: string, plan: LlmConsolidationPlan, attempt?: number): string;
|
|
117
|
+
/** The engine face this verb consumes — `MemoryEngine` satisfies it structurally. */
|
|
118
|
+
export interface ConsolidationDriverEngine extends ConsolidationDriveEngine {
|
|
119
|
+
readConsolidationGate(scope: string): ConsolidationGateRow | undefined;
|
|
120
|
+
listConsolidationPlans(): ConsolidationPlanSummary[];
|
|
121
|
+
readConsolidationFoldState(scope: string): Promise<ConsolidationFoldState>;
|
|
122
|
+
readonly controlPlaneRoot: string;
|
|
123
|
+
}
|
|
124
|
+
export interface RunMemoryConsolidationOptions {
|
|
125
|
+
/** The explicit model seat (design/339 §1.1: the ENGINE holds none). Build one with
|
|
126
|
+
* `openAiCompatChatSeat` or hand any JSON-only completion function. */
|
|
127
|
+
chat: DistillerChatFn;
|
|
128
|
+
/** The explicit model id, recorded into the run and the archive (alias spellings refuse). */
|
|
129
|
+
model: string;
|
|
130
|
+
/** Audit locator recorded into the archive when the seat is endpoint-shaped. */
|
|
131
|
+
baseUrl?: string;
|
|
132
|
+
/** The frozen prompt contract; default = the product v1 (dl-3 byte-identical). A different
|
|
133
|
+
* version here is a deployment's explicit measured choice. */
|
|
134
|
+
contract?: LlmDistillerContract;
|
|
135
|
+
/** The PROTOCOL knobs — pass the same object the engine was constructed with
|
|
136
|
+
* (`MemoryEngineOptions.consolidation`); the driver derives its throttle window and per-plan
|
|
137
|
+
* caps from it. Defaults = the factory defaults. */
|
|
138
|
+
consolidation?: MemoryConsolidationOptions;
|
|
139
|
+
/** Abort the run after this many cycles in THIS call (the run row stays pending only on crash;
|
|
140
|
+
* a reached bound settles `max_cycles`). Positive integer; default 64. */
|
|
141
|
+
maxCycles?: number;
|
|
142
|
+
/** R2 — the structural-repair budget over the mint's member references: the ratio of member
|
|
143
|
+
* claims the sanitiser had to DROP (hallucinated + duplicate + non-integer) to all member
|
|
144
|
+
* claims the model made. Above this, the plan does not represent the model's intent and the
|
|
145
|
+
* run aborts with zero writes rather than committing a harness-repaired fold. In [0, 1];
|
|
146
|
+
* default 0.10. (Empty groups are the same drops counted at group grain; oversize groups are
|
|
147
|
+
* not repairs — they ride on, named, and the schedule reports them infeasible. Format repairs
|
|
148
|
+
* and retries are disclosed separately and bounded by the contract's own retry count.) */
|
|
149
|
+
mintRepairBudget?: number;
|
|
150
|
+
/** The run's force credential; defaults to a minted id. A RESUMED run keeps its original. */
|
|
151
|
+
requestId?: string;
|
|
152
|
+
/** Host seams for the throttle waits (tests and hosts with their own clocks). */
|
|
153
|
+
now?: () => number;
|
|
154
|
+
sleep?: (ms: number) => Promise<void>;
|
|
155
|
+
onProgress?: Parameters<typeof mintLlmConsolidationPlan>[0]["onProgress"];
|
|
156
|
+
}
|
|
157
|
+
export interface ConsolidationRunReceipt {
|
|
158
|
+
runId: string;
|
|
159
|
+
scope: string;
|
|
160
|
+
/** Whether this call CONTINUED a pending run (no new mint) instead of starting one. */
|
|
161
|
+
resumed: boolean;
|
|
162
|
+
outcome: ConsolidationRunStopReason;
|
|
163
|
+
converged: boolean;
|
|
164
|
+
stopDetail?: string;
|
|
165
|
+
/** This call's cycles (store-delta accounted); `cyclesDone` is the run total across resumes. */
|
|
166
|
+
cycles: ConsolidationDriveCycleRow[];
|
|
167
|
+
cyclesDone: number;
|
|
168
|
+
productsCommitted: number;
|
|
169
|
+
entriesSuperseded: number;
|
|
170
|
+
planIds: string[];
|
|
171
|
+
model: string;
|
|
172
|
+
contractVersion: string;
|
|
173
|
+
usage: ConsolidationDriverRunRow["usage"];
|
|
174
|
+
repairs: ConsolidationDriverRunRow["repairs"];
|
|
175
|
+
writeFailures: ConsolidationDriverRunRow["writeFailures"];
|
|
176
|
+
residue: Array<{
|
|
177
|
+
name: string;
|
|
178
|
+
targets: number;
|
|
179
|
+
}>;
|
|
180
|
+
planArchive?: string;
|
|
181
|
+
/** Advisory notices minted for this run (the `_incomplete` disclosure when not converged). */
|
|
182
|
+
notices: EngineNotice[];
|
|
183
|
+
/** A failed announcement enqueue is disclosed, never allowed to fail the settled run. */
|
|
184
|
+
announceFailures?: string[];
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Run (or RESUME) one scope's consolidation as a persistent multi-cycle job. See the module note
|
|
188
|
+
* for the shape; the per-refusal behavior implements the design/376 §1.2 failure table:
|
|
189
|
+
*
|
|
190
|
+
* - `_disabled` / a corrupt gate / an unreadable governance account BEFORE any commit: the coded
|
|
191
|
+
* error is rethrown (a configuration/store fault the host must repair — a pending run row, if
|
|
192
|
+
* one exists, stays resumable after the repair);
|
|
193
|
+
* - `_gated` (time/session gate): retried under the run's force requestId — the run-level force
|
|
194
|
+
* the design names; the FORCED audit line is engine-deduplicated to once per run;
|
|
195
|
+
* - `_gated` (hard throttle): the driver WAITS the window out (`min(minRunIntervalMs, 60s)`) and
|
|
196
|
+
* continues — a throttled cycle is scheduling, not a terminal;
|
|
197
|
+
* - `_busy`: never a blind snapshot retry (the seat refuses snapshots too — a blind loop spins
|
|
198
|
+
* forever): `reconcileConsolidation` first; a conflict/corrupt plan parks the run for the host
|
|
199
|
+
* valve; a live competing worker is waited out briefly, then reported;
|
|
200
|
+
* - model failures / a mint over the repair budget: the run settles `driver_failed` with ZERO
|
|
201
|
+
* writes — the mint sits between snapshot and commit, so no seat was taken, `lastRunAt` never
|
|
202
|
+
* moved and the time gate is not burned (the failure is free to retry);
|
|
203
|
+
* - a conflict plan mid-run parks (`parked`); fuse residue and the cycle bound settle
|
|
204
|
+
* `fuse_residue` / `max_cycles` with the residue named — the next run's FULL snapshot
|
|
205
|
+
* re-distills the shrunken library (cross-run = re-mint; in-run = plan cache).
|
|
206
|
+
*/
|
|
207
|
+
export declare function runMemoryConsolidationDriver(engine: ConsolidationDriverEngine, scope: string, opts: RunMemoryConsolidationOptions): Promise<ConsolidationRunReceipt>;
|