dsh-completion-guard 0.4.3 → 0.5.1
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 +42 -0
- package/CHANGELOG.zh-CN.md +42 -0
- package/README.md +20 -12
- package/README.zh-CN.md +20 -12
- package/bin/dsh-completion-guard-host-lock.mjs +16 -0
- package/dist/domain/index.d.ts +2 -2
- package/dist/domain/index.js +2 -2
- package/dist/{domain-DebMrpyX.js → domain-BqmJLHcu.js} +3835 -1055
- package/dist/{index-BZYtgqlu.d.ts → index-Dcee_NYF.d.ts} +765 -43
- package/dist/index.d.ts +3 -2
- package/dist/index.js +441 -34
- package/docs/ARCHITECTURE.md +29 -2
- package/docs/COMPATIBILITY.md +73 -4
- package/docs/HOST_LOCK_UPGRADE.md +53 -5
- package/docs/LOCAL_ACCEPTANCE.md +10 -2
- package/docs/PORTING_NOTES.md +22 -0
- package/docs/SEMANTIC_COMPATIBILITY.md +24 -0
- package/docs/upstream-deltas.json +30 -4
- package/manifests/supported-host.v1.json +173 -578
- package/package.json +34 -31
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { $ as
|
|
1
|
+
import { $ as parseShellCommand, $n as requestedTargetMatchesResolved, $t as latestRootInstruction, A as createGitPrestateEnvelope, An as isInformationalMessage, At as authorityCaptureCounts, B as CAPTURE_V042_NOTICE, Bn as statefulActionsOfScope, Bt as evidenceCoverage, C as SESSION_EVENT_ENVELOPE_INVALID, Cn as relevantEvidence, Ct as evaluateMinimumHostVersion, D as GIT_COMMAND_TEMPLATES, Dn as extractArtifactPaths, Dt as RC015_HOST_PACKAGES, E as GIT_COMMAND_MANIFEST_IDS, En as classifyClause, Et as RC015_RC2_HOST_PACKAGES, F as verifiedLinearCommitReadback, Fn as isOpenObligation, Ft as closingHint, G as evidenceFromPersistedToolResult, Gn as CERTIFICATE_VERSION, Gt as NO_PROGRESS_TURNS_BEFORE_STOP, H as PROTOCOL_V4_NOTICE, Hn as npmEscapedPackageName, Ht as isVerifyingCapability, I as FIRST_STEP_GUIDANCE, In as kindOfScope, It as openItems, J as isDeterministicCheck, Jn as STOP_PROTOCOL_VERSION, Jt as decideTurnStopping, K as extractTextContent, Kn as SEMANTIC_ACTIONS, Kt as classifyCompletionClaim, L as claimedBatchHasRealRootInput, Ln as maskCodeSpans, Lt as recoveryDigest, M as gitCommandMatchesTarget, Mn as interpretClause, Mt as certifyCheckpoint, N as parseGitCommandManifest, Nn as interpretMessage, Nt as DEFAULT_RECOVERY_CHAR_BUDGET, O as commitIndexSnapshotDigest, On as extractMethod, Ot as RC1_HOST_PACKAGES, P as revalidateGitPrestate, Pn as isExecutableItem, Pt as MIN_RECOVERY_CHAR_BUDGET, Q as parsePwshCommand, Qn as requestedTargetAuthorizesMutation, Qt as latestAssistantText, R as lifecyclePhase, Rn as namedActions, Rt as renderRecoveryPacket, S as SESSION_API_UNSUPPORTED, Sn as itemDiagnosis, St as compareHostVersions, T as snapshotSessionEvents, Tn as captureItem, Tt as satisfiesSupportedHostRange, U as deriveProjection, Un as ACTION_MANIFEST, Ut as CONTROL_RECORD_PREFIX, V as PROTOCOL_V3_NOTICE, Vn as canonicalRegistryBase, Vt as evidenceMatchesItem, W as supersedeItem, Wn as ACTION_MANIFEST_VERSION, Wt as NO_PROGRESS_RECORD_PREFIX, X as canonicalArgvFromCommand, Xn as actionCompatible, Xt as isRootPauseRequest, Y as withDurability, Yn as SUPPORTED_EVIDENCE_ADAPTERS, Yt as decisionBoundaryKey, Z as isRunExecutable, Zn as isStatefulAction, Zt as isWholeTaskCompletionClaim, _ as packageRowsFromPnpmLock, _n as CONFIRM_LINE_PATTERN, _t as evaluateToolSurfaceCapability, a as createProofManifest, an as effectuateBoundary, ar as validateManifest, at as BASE_HOST_PACKAGES, b as resolveInstalledHostLock, bn as deriveItemDiagnosis, bt as MIN_SUPPORTED_HOST_VERSION, c as sessionQuery, cn as currentContractDigest, cr as canonicalizePath, ct as GOAL_HOST_PACKAGES, d as combineHostPolicy, dn as proposeRebind, dr as sanitizeClauseText, dt as LEGACY_HOST_COHORTS, en as observeAssistantOutcome, er as semanticActionFromCommand, et as ACTIVE_HOST_COHORT_ID, f as hostLockContextFromComposedDump, fn as proposeRebindOutcome, fr as sanitizeUrl, ft as bindExecutableIdentity, g as packageRowsFromActiveGraph, gn as replayRebindResult, gt as evaluateHostLock, h as inspectTargetHostGraph, hn as rebindResponse, ht as evaluateHostCapability, i as canonicalProjection, in as availableBoundaryQualifications, ir as COMMAND_SURFACE_MANIFEST, it as ALPHA2_HOST_PACKAGES, j as executeRevalidatedGitEffect, jn as segmentClauses, jt as segmentAuthorityBlocks, k as commitTreeSnapshotDigest, kn as extractOperation, kt as ALPHA3_HOST_PACKAGES, l as validateProofManifest, ln as createProjection, lr as digestStrings, lt as HOST_CAPABILITY_PACKAGE_GROUPS, m as injectActiveProfileHostLock, mn as rebindAttemptKey, mt as evaluateExternalWaitCapability, n as PROOF_PROTOCOL_VERSION, nn as goalCompletionDenial, nr as validateActionManifest, nt as ACTIVE_HOST_LAUNCHER_VERSION, o as proofDigest, on as isCurrentAcceptedBoundary, or as classifyTaskIntent, ot as DEFAULT_HOST_LOCK, p as hostLockRowsFromComposedDump, pn as proposeRebindV042, pr as sha256, pt as bindLiveGoalCapability, q as extractToolSubject, qn as STATEFUL_ACTIONS, qt as decideTurnBoundary, r as bindProofToProjection, rn as hasCurrentCertificate, rr as validateActionTarget, rt as ALPHA2_DSHMARKET_139_HOST_PACKAGES, s as proofEvidenceConstraints, sn as qualifyBoundary, sr as classifyUserInteraction, st as EXPECTED_HOST_PACKAGES, t as PROOF_KINDS, tn as progressFingerprint, tr as semanticActionFromText, tt as ACTIVE_HOST_COHORT_IDS, u as HostProfileError, un as confirmRebind, ur as normalizeClause, ut as HOST_COHORTS, v as readActiveHostGraph, vn as isFrozenV042RebindResponse, vt as hostVersionFromPackages, w as SessionApiError, wn as captureClause, wt as parseHostVersion, x as verifyComposedHostLockDump, xn as evidenceAvailabilityReason, xt as SUPPORTED_HOST_RANGE, y as resolveActiveProfileHostLock, yn as parseConfirmationMessage, yt as selectHostCohort, z as previewFirstStepInjection, zn as semanticActionOfScope, zt as bindingSatisfies } from "./domain-BqmJLHcu.js";
|
|
2
2
|
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
3
3
|
import { createHash } from "node:crypto";
|
|
4
4
|
import { basename, delimiter, dirname, isAbsolute, join, resolve } from "node:path";
|
|
5
|
-
import { boundContextSummary, createUserMessage } from "@deepseek-ai/dsh-llm";
|
|
5
|
+
import { boundContextSummary, createToolResultMessage, createUserMessage } from "@deepseek-ai/dsh-llm";
|
|
6
6
|
import { execFile } from "node:child_process";
|
|
7
7
|
import { constants, existsSync, readFileSync } from "node:fs";
|
|
8
8
|
import { access, readFile, realpath } from "node:fs/promises";
|
|
@@ -10,6 +10,7 @@ import { tmpdir } from "node:os";
|
|
|
10
10
|
import { fileURLToPath } from "node:url";
|
|
11
11
|
import { promisify } from "node:util";
|
|
12
12
|
import { gunzip } from "node:zlib";
|
|
13
|
+
import { SESSION_FORMAT_VERSION } from "@deepseek-ai/dsh-session";
|
|
13
14
|
|
|
14
15
|
//#region src/tools/rebind.ts
|
|
15
16
|
function createRebindTool(getProjection, prepare) {
|
|
@@ -414,6 +415,33 @@ function createCheckpointTool(getProjection, onRejected, prepare = async () => t
|
|
|
414
415
|
state_evidence_ids: {
|
|
415
416
|
type: "array",
|
|
416
417
|
items: { type: "string" }
|
|
418
|
+
},
|
|
419
|
+
action_bindings: {
|
|
420
|
+
type: "array",
|
|
421
|
+
items: {
|
|
422
|
+
type: "object",
|
|
423
|
+
additionalProperties: false,
|
|
424
|
+
properties: {
|
|
425
|
+
action: {
|
|
426
|
+
type: "string",
|
|
427
|
+
required: true
|
|
428
|
+
},
|
|
429
|
+
evidence_ids: {
|
|
430
|
+
type: "array",
|
|
431
|
+
required: true,
|
|
432
|
+
items: { type: "string" }
|
|
433
|
+
},
|
|
434
|
+
resolved_target: {
|
|
435
|
+
type: "object",
|
|
436
|
+
required: true,
|
|
437
|
+
additionalProperties: true
|
|
438
|
+
},
|
|
439
|
+
order: {
|
|
440
|
+
type: "integer",
|
|
441
|
+
required: true
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
417
445
|
}
|
|
418
446
|
}
|
|
419
447
|
}
|
|
@@ -619,7 +647,13 @@ function createCheckpointTool(getProjection, onRejected, prepare = async () => t
|
|
|
619
647
|
} } : {},
|
|
620
648
|
...binding.resolution_evidence_id ? { resolutionEvidenceId: binding.resolution_evidence_id } : {},
|
|
621
649
|
...binding.effect_evidence_id ? { effectEvidenceId: binding.effect_evidence_id } : {},
|
|
622
|
-
...binding.state_evidence_ids ? { stateEvidenceIds: binding.state_evidence_ids } : {}
|
|
650
|
+
...binding.state_evidence_ids ? { stateEvidenceIds: binding.state_evidence_ids } : {},
|
|
651
|
+
...binding.action_bindings ? { actionBindings: binding.action_bindings.map((closure) => ({
|
|
652
|
+
action: closure.action,
|
|
653
|
+
evidenceIds: closure.evidence_ids,
|
|
654
|
+
resolvedTarget: closure.resolved_target,
|
|
655
|
+
order: closure.order
|
|
656
|
+
})) } : {}
|
|
623
657
|
})), `C${projection.checkpoints.length + 1}`, false);
|
|
624
658
|
if (!result.checkpoint) onRejected();
|
|
625
659
|
const available_evidence = [...projection.evidence.values()].filter((evidence) => evidence.epoch === projection.epoch && (args.evidence_scope === "history" || [...projection.items.values()].some((item) => item.status === "pending" && relevantEvidence(projection, item, evidence)))).sort((a, b) => b.toolResultSeq - a.toolResultSeq || (a.id < b.id ? -1 : 1)).map((evidence) => ({
|
|
@@ -689,7 +723,7 @@ function createCheckpointTool(getProjection, onRejected, prepare = async () => t
|
|
|
689
723
|
function createBoundaryTool(getProjection, prepare, onRejected) {
|
|
690
724
|
return defineTool({
|
|
691
725
|
name: "context_guard_boundary",
|
|
692
|
-
description: "Persist a qualified user_wait, external_wait, or
|
|
726
|
+
description: "Persist a qualified user_wait, external_wait, deferred, or guard_bounded_stop boundary. Free-form notes never qualify a boundary.",
|
|
693
727
|
parameters: {
|
|
694
728
|
disposition: {
|
|
695
729
|
type: "string",
|
|
@@ -697,7 +731,8 @@ function createBoundaryTool(getProjection, prepare, onRejected) {
|
|
|
697
731
|
enum: [
|
|
698
732
|
"user_wait",
|
|
699
733
|
"external_wait",
|
|
700
|
-
"deferred"
|
|
734
|
+
"deferred",
|
|
735
|
+
"guard_bounded_stop"
|
|
701
736
|
]
|
|
702
737
|
},
|
|
703
738
|
qualification_kind: {
|
|
@@ -707,7 +742,8 @@ function createBoundaryTool(getProjection, prepare, onRejected) {
|
|
|
707
742
|
"user_decision_item",
|
|
708
743
|
"root_explicit_wait",
|
|
709
744
|
"external_operation_pending",
|
|
710
|
-
"root_explicit_defer"
|
|
745
|
+
"root_explicit_defer",
|
|
746
|
+
"guard_no_progress"
|
|
711
747
|
]
|
|
712
748
|
},
|
|
713
749
|
qualification_ids: {
|
|
@@ -812,6 +848,103 @@ function createBoundaryTool(getProjection, prepare, onRejected) {
|
|
|
812
848
|
});
|
|
813
849
|
}
|
|
814
850
|
|
|
851
|
+
//#endregion
|
|
852
|
+
//#region src/tools/prepare.ts
|
|
853
|
+
/**
|
|
854
|
+
* Thin READ-ONLY preparation surface (v0.5): before any stateful action it
|
|
855
|
+
* reports the supported command shape, the required resolution/effect/state
|
|
856
|
+
* evidence order, existing reusable references, and the exact missing fields.
|
|
857
|
+
* It never executes, installs, commits, pushes, restarts, or probes authority
|
|
858
|
+
* through side effects, and it never upgrades a default into user authority.
|
|
859
|
+
*/
|
|
860
|
+
function createPrepareTool(options) {
|
|
861
|
+
return defineTool({
|
|
862
|
+
name: "context_guard_prepare",
|
|
863
|
+
description: "Read-only pre-action preparation: report the supported command shape, required resolution/effect/state evidence order, existing references, and exact missing target fields for one contract item. Performs no action and grants no authority.",
|
|
864
|
+
parameters: {
|
|
865
|
+
item_id: {
|
|
866
|
+
type: "string",
|
|
867
|
+
required: true
|
|
868
|
+
},
|
|
869
|
+
item_revision: { type: "number" },
|
|
870
|
+
semantic_action: { type: "string" },
|
|
871
|
+
requested_target: {
|
|
872
|
+
type: "object",
|
|
873
|
+
additionalProperties: true
|
|
874
|
+
},
|
|
875
|
+
planned_operation: { type: "string" }
|
|
876
|
+
},
|
|
877
|
+
output: {
|
|
878
|
+
schema: {
|
|
879
|
+
type: "object",
|
|
880
|
+
additionalProperties: true
|
|
881
|
+
},
|
|
882
|
+
render: (_args, value) => [{
|
|
883
|
+
type: "text",
|
|
884
|
+
text: JSON.stringify(value)
|
|
885
|
+
}]
|
|
886
|
+
},
|
|
887
|
+
async execute(rawArgs) {
|
|
888
|
+
const args = rawArgs;
|
|
889
|
+
const p = options.getProjection();
|
|
890
|
+
if (!p || !p.enabled || p.integrity !== "valid") return {
|
|
891
|
+
status: "unknown",
|
|
892
|
+
reason_code: "guard_unavailable"
|
|
893
|
+
};
|
|
894
|
+
const item = p.items.get(args.item_id ?? "");
|
|
895
|
+
if (!item) return {
|
|
896
|
+
status: "rejected",
|
|
897
|
+
reason_code: "item_not_found"
|
|
898
|
+
};
|
|
899
|
+
if (args.item_revision !== void 0 && item.revision !== args.item_revision) return {
|
|
900
|
+
status: "rejected",
|
|
901
|
+
reason_code: "item_revision_mismatch",
|
|
902
|
+
item_revision: item.revision
|
|
903
|
+
};
|
|
904
|
+
const diagnosis = deriveItemDiagnosis(p, item);
|
|
905
|
+
const plannedAction = args.semantic_action ?? item.semanticAction;
|
|
906
|
+
const manifestEntry = plannedAction ? ACTION_MANIFEST.actions[plannedAction] : void 0;
|
|
907
|
+
if (plannedAction && !manifestEntry) return {
|
|
908
|
+
status: "rejected",
|
|
909
|
+
reason_code: "unsupported_action"
|
|
910
|
+
};
|
|
911
|
+
const reusable = [...p.evidence.values()].filter((evidence) => relevantEvidence(p, item, evidence) && evidenceAvailabilityReason(evidence) === void 0).sort((a, b) => b.toolResultSeq - a.toolResultSeq).slice(0, 8).map((evidence) => ({
|
|
912
|
+
evidence_id: evidence.id,
|
|
913
|
+
role: evidence.evidenceRole,
|
|
914
|
+
semantic_action: evidence.semanticAction,
|
|
915
|
+
resolved_target: evidence.resolvedTarget,
|
|
916
|
+
tool_result_seq: evidence.toolResultSeq
|
|
917
|
+
}));
|
|
918
|
+
const requiredOrder = manifestEntry?.stateful ? [
|
|
919
|
+
"resolution (prestate facts from a trusted read)",
|
|
920
|
+
"effect (the exact planned change)",
|
|
921
|
+
"state (independent post-state readback)"
|
|
922
|
+
] : ["state (matching durable evidence for the requested verification)"];
|
|
923
|
+
const missingTargetFields = manifestEntry?.stateful && plannedAction ? manifestEntry.resolvedTargetKeys.filter((key) => !(item.requestedTarget?.[key] !== void 0 || args.requested_target?.[key] !== void 0)) : [];
|
|
924
|
+
const capability = plannedAction && options.hostCapability ? options.hostCapability(plannedAction) : void 0;
|
|
925
|
+
const commandShape = options.commandTemplate && plannedAction ? options.commandTemplate(plannedAction) : void 0;
|
|
926
|
+
return {
|
|
927
|
+
status: "prepared",
|
|
928
|
+
item: {
|
|
929
|
+
id: item.id,
|
|
930
|
+
revision: item.revision
|
|
931
|
+
},
|
|
932
|
+
diagnosis,
|
|
933
|
+
...plannedAction !== void 0 ? { planned_action: plannedAction } : {},
|
|
934
|
+
...commandShape !== void 0 ? { supported_command_shape: commandShape } : {},
|
|
935
|
+
required_evidence_order: requiredOrder,
|
|
936
|
+
reusable_references: reusable,
|
|
937
|
+
missing_target_fields: missingTargetFields,
|
|
938
|
+
...capability ? { host_capability: {
|
|
939
|
+
status: capability.status,
|
|
940
|
+
reason_code: capability.reasonCode
|
|
941
|
+
} } : {},
|
|
942
|
+
note: "Preparation performs no action. A default or guessed target is not user authority; explicit root instruction is required for missing target fields."
|
|
943
|
+
};
|
|
944
|
+
}
|
|
945
|
+
});
|
|
946
|
+
}
|
|
947
|
+
|
|
815
948
|
//#endregion
|
|
816
949
|
//#region src/tools/evidence.ts
|
|
817
950
|
const execFileAsync = promisify(execFile);
|
|
@@ -2411,7 +2544,7 @@ function createExternalOperationTool(read, capability) {
|
|
|
2411
2544
|
function pendingCount(projection) {
|
|
2412
2545
|
return [...projection.items.values()].filter((item) => item.status === "pending").length;
|
|
2413
2546
|
}
|
|
2414
|
-
function createContextGuardCommand(projectionFor, setEnabled, clearContract) {
|
|
2547
|
+
function createContextGuardCommand(projectionFor, setEnabled, clearContract, lifecycleFor) {
|
|
2415
2548
|
return {
|
|
2416
2549
|
name: "context-guard",
|
|
2417
2550
|
description: "Enable, disable, clear, inspect, or diagnose Context Guard for this session.",
|
|
@@ -2449,12 +2582,26 @@ function createContextGuardCommand(projectionFor, setEnabled, clearContract) {
|
|
|
2449
2582
|
text: "Usage: /context-guard on|off|clear|status|diagnose"
|
|
2450
2583
|
};
|
|
2451
2584
|
const passed = [...projection.items.values()].filter((item) => item.status === "passed").length;
|
|
2585
|
+
let certifiable_missing_evidence = 0;
|
|
2586
|
+
let unsupported = 0;
|
|
2587
|
+
for (const item of projection.items.values()) {
|
|
2588
|
+
if (item.status !== "pending") continue;
|
|
2589
|
+
const diagnosis = deriveItemDiagnosis(projection, item);
|
|
2590
|
+
if (diagnosis.repairability === "agent_repairable") certifiable_missing_evidence += 1;
|
|
2591
|
+
else if (diagnosis.certification === "unsupported") unsupported += 1;
|
|
2592
|
+
}
|
|
2452
2593
|
const response = {
|
|
2453
2594
|
enabled: projection.enabled,
|
|
2595
|
+
lifecycle: lifecycleFor?.(agent) ?? (projection.enabled ? "active" : "disabled"),
|
|
2454
2596
|
epoch: projection.epoch,
|
|
2455
2597
|
contract_revision: projection.contractRevision,
|
|
2456
2598
|
pending: pendingCount(projection),
|
|
2457
2599
|
passed,
|
|
2600
|
+
diagnosis: {
|
|
2601
|
+
certified: passed,
|
|
2602
|
+
certifiable_missing_evidence,
|
|
2603
|
+
unsupported
|
|
2604
|
+
},
|
|
2458
2605
|
evidence: projection.evidence.size,
|
|
2459
2606
|
integrity: projection.integrity,
|
|
2460
2607
|
last_source_seq: projection.lastObservedSourceSeq
|
|
@@ -2468,7 +2615,7 @@ function createContextGuardCommand(projectionFor, setEnabled, clearContract) {
|
|
|
2468
2615
|
}
|
|
2469
2616
|
|
|
2470
2617
|
//#endregion
|
|
2471
|
-
//#region node_modules/.pnpm/@deepseek-ai+cosmokit@1.8.
|
|
2618
|
+
//#region node_modules/.pnpm/@deepseek-ai+cosmokit@1.8.3/node_modules/@deepseek-ai/cosmokit/lib/index.js
|
|
2472
2619
|
/** Return true when a value is `null` or `undefined`. */
|
|
2473
2620
|
function isNullable(value) {
|
|
2474
2621
|
return value === null || value === void 0;
|
|
@@ -2669,7 +2816,7 @@ var Time;
|
|
|
2669
2816
|
})(Time || (Time = {}));
|
|
2670
2817
|
|
|
2671
2818
|
//#endregion
|
|
2672
|
-
//#region node_modules/.pnpm/@deepseek-ai+schemastery@3.18.
|
|
2819
|
+
//#region node_modules/.pnpm/@deepseek-ai+schemastery@3.18.2/node_modules/@deepseek-ai/schemastery/lib/index.mjs
|
|
2673
2820
|
const kSchema = Symbol.for("schemastery");
|
|
2674
2821
|
const kValidationError = Symbol.for("ValidationError");
|
|
2675
2822
|
globalThis.__schemastery_index__ ??= 0;
|
|
@@ -3352,6 +3499,14 @@ function authorizeMutationFromProjection(projection, request) {
|
|
|
3352
3499
|
status: "denied",
|
|
3353
3500
|
reasonCode: "mutation_contract_item_not_pending"
|
|
3354
3501
|
};
|
|
3502
|
+
if (item.authorityDisposition === "conditional_wait" || item.waitAuthorization) return {
|
|
3503
|
+
status: "denied",
|
|
3504
|
+
reasonCode: item.authorityDisposition === "conditional_wait" ? "mutation_awaiting_root_condition" : "mutation_awaiting_root_wait"
|
|
3505
|
+
};
|
|
3506
|
+
if (item.authorityDisposition === "human_actor") return {
|
|
3507
|
+
status: "denied",
|
|
3508
|
+
reasonCode: "mutation_human_executor"
|
|
3509
|
+
};
|
|
3355
3510
|
if (item.kind !== "requirement" || item.verification.enforced !== true) return {
|
|
3356
3511
|
status: "denied",
|
|
3357
3512
|
reasonCode: "mutation_contract_item_not_authorizing"
|
|
@@ -3393,13 +3548,159 @@ function authorizeMutationFromProjection(projection, request) {
|
|
|
3393
3548
|
};
|
|
3394
3549
|
}
|
|
3395
3550
|
const PROTOCOL_CORRECTION_NOTICE = "Context Guard protocol correction: root-authorized work remains pending; continue with tools or obtain a typed boundary.";
|
|
3551
|
+
/**
|
|
3552
|
+
* Establish a boundary Guard itself owns, through the same durable record the
|
|
3553
|
+
* boundary tool writes.
|
|
3554
|
+
*
|
|
3555
|
+
* Replay reads boundaries from the `context_guard_boundary` call/result pair, so
|
|
3556
|
+
* a Guard-created boundary is written in exactly that wire shape rather than in
|
|
3557
|
+
* a private side channel — otherwise it would not survive a reload, and a
|
|
3558
|
+
* boundary that only exists in memory is not a persisted wait or stop.
|
|
3559
|
+
*
|
|
3560
|
+
* Returns the boundary only after the durable flush succeeded. A failed flush
|
|
3561
|
+
* reports the failure instead of a boundary, because an unflushed record must
|
|
3562
|
+
* never be read back as an established boundary.
|
|
3563
|
+
*/
|
|
3564
|
+
async function establishBoundary(agent, runtime, flush, request) {
|
|
3565
|
+
const projection = runtime.projection;
|
|
3566
|
+
const candidate = qualifyBoundary(projection, request);
|
|
3567
|
+
if (candidate.persistedResult !== "accepted") return { reasonCode: candidate.reasonCode };
|
|
3568
|
+
const session = agent.session;
|
|
3569
|
+
const callId = `guard-boundary-${candidate.id}`;
|
|
3570
|
+
session.append("tool/call", {
|
|
3571
|
+
turn: 0,
|
|
3572
|
+
step: session.seq,
|
|
3573
|
+
callId,
|
|
3574
|
+
name: "context_guard_boundary",
|
|
3575
|
+
arguments: JSON.stringify({
|
|
3576
|
+
disposition: request.disposition,
|
|
3577
|
+
qualification_kind: request.qualificationKind,
|
|
3578
|
+
qualification_ids: request.qualificationIds
|
|
3579
|
+
})
|
|
3580
|
+
});
|
|
3581
|
+
session.append("tool/result", {
|
|
3582
|
+
turn: 0,
|
|
3583
|
+
step: session.seq,
|
|
3584
|
+
message: createToolResultMessage({
|
|
3585
|
+
callId,
|
|
3586
|
+
content: [{
|
|
3587
|
+
type: "text",
|
|
3588
|
+
text: JSON.stringify({
|
|
3589
|
+
status: candidate.persistedResult,
|
|
3590
|
+
reason_code: candidate.reasonCode,
|
|
3591
|
+
boundary: { candidate_sha256: candidate.candidateSha256 }
|
|
3592
|
+
})
|
|
3593
|
+
}],
|
|
3594
|
+
isError: false
|
|
3595
|
+
})
|
|
3596
|
+
}, { surfaceOp: "append" });
|
|
3597
|
+
let durable = false;
|
|
3598
|
+
try {
|
|
3599
|
+
durable = await flush();
|
|
3600
|
+
} catch {
|
|
3601
|
+
durable = false;
|
|
3602
|
+
}
|
|
3603
|
+
runtime.setDurability(durable);
|
|
3604
|
+
runtime.sync();
|
|
3605
|
+
if (!durable) return { reasonCode: "boundary_flush_failed" };
|
|
3606
|
+
return {
|
|
3607
|
+
boundary: candidate,
|
|
3608
|
+
reasonCode: candidate.reasonCode
|
|
3609
|
+
};
|
|
3610
|
+
}
|
|
3611
|
+
/**
|
|
3612
|
+
* Effectuate a boundary Guard established in this turn, with the Goal revision
|
|
3613
|
+
* re-checked at the moment of the side effect.
|
|
3614
|
+
*
|
|
3615
|
+
* The progress fingerprint deliberately ignores the Goal revision, because an
|
|
3616
|
+
* edited Goal text is not progress. That is a statement about *detecting*
|
|
3617
|
+
* progress, not permission to act on a stale reference: before disarming, the
|
|
3618
|
+
* boundary's own Goal identity and revision are compared with the live readback,
|
|
3619
|
+
* so a Goal that changed under the boundary is refused rather than disarmed.
|
|
3620
|
+
*/
|
|
3621
|
+
async function effectuateOwnBoundary(runtime, boundary, access$1) {
|
|
3622
|
+
const goalAccess = access$1.goalAccess ?? {
|
|
3623
|
+
get: async () => void 0,
|
|
3624
|
+
disarm: async () => void 0
|
|
3625
|
+
};
|
|
3626
|
+
const recorded = boundary.goalRef;
|
|
3627
|
+
const effect = await effectuateBoundary(boundary, {
|
|
3628
|
+
...goalAccess,
|
|
3629
|
+
requalify: async () => {
|
|
3630
|
+
const live = await goalAccess.get();
|
|
3631
|
+
if (!live || !recorded) return false;
|
|
3632
|
+
return live.id === recorded.id && live.revision === recorded.revision && live.activation === "armed";
|
|
3633
|
+
}
|
|
3634
|
+
});
|
|
3635
|
+
if (effect.resumeRequired) {
|
|
3636
|
+
runtime.projection.integrity = "unknown";
|
|
3637
|
+
runtime.projection.integrityViolations.push(effect.reasonCode);
|
|
3638
|
+
}
|
|
3639
|
+
return effect.reasonCode;
|
|
3640
|
+
}
|
|
3396
3641
|
/** Production Stop boundary: durable replay first, then immutable/live checks. */
|
|
3397
3642
|
async function handleGuardTurnStopping(agent, runtime, access$1) {
|
|
3398
|
-
|
|
3643
|
+
let durable = false;
|
|
3644
|
+
try {
|
|
3645
|
+
durable = await access$1.flush();
|
|
3646
|
+
} catch {
|
|
3647
|
+
durable = false;
|
|
3648
|
+
}
|
|
3399
3649
|
runtime.setDurability(durable);
|
|
3400
3650
|
runtime.sync();
|
|
3401
3651
|
if (!durable) return "boundary_flush_failed";
|
|
3652
|
+
const rootInstruction = latestRootInstruction(agent.session?.snapshotEvents?.() ?? []);
|
|
3653
|
+
if (rootInstruction !== void 0 && isRootPauseRequest(rootInstruction.text) && !runtime.projection.handledControlSeqs.has(rootInstruction.seq) && access$1.pauseAccess) {
|
|
3654
|
+
agent.session.append("user/message", createUserMessage({
|
|
3655
|
+
content: [{
|
|
3656
|
+
type: "text",
|
|
3657
|
+
text: `${CONTROL_RECORD_PREFIX}${JSON.stringify({
|
|
3658
|
+
kind: "root_pause",
|
|
3659
|
+
rootSeq: rootInstruction.seq
|
|
3660
|
+
})}`
|
|
3661
|
+
}],
|
|
3662
|
+
source: {
|
|
3663
|
+
kind: "plugin",
|
|
3664
|
+
plugin: "context-guard",
|
|
3665
|
+
form: "notice",
|
|
3666
|
+
summary: boundContextSummary("carrying the root pause request to the host")
|
|
3667
|
+
}
|
|
3668
|
+
}), { surfaceOp: "append" });
|
|
3669
|
+
const current = await access$1.pauseAccess.get();
|
|
3670
|
+
const paused = current?.phase === "paused" && current.activation === "disarmed" ? current : await access$1.pauseAccess.pause();
|
|
3671
|
+
const readback$1 = await access$1.pauseAccess.get();
|
|
3672
|
+
if (!paused || paused.activation !== "disarmed" || readback$1?.activation !== "disarmed") {
|
|
3673
|
+
runtime.projection.integrity = "unknown";
|
|
3674
|
+
runtime.projection.integrityViolations.push("root_pause_readback_failed");
|
|
3675
|
+
return "root_pause_readback_failed";
|
|
3676
|
+
}
|
|
3677
|
+
return "root_pause_routed";
|
|
3678
|
+
}
|
|
3402
3679
|
const decision = decideTurnBoundary(runtime.projection);
|
|
3680
|
+
if (decision.noProgressClaim) {
|
|
3681
|
+
const record$1 = `${NO_PROGRESS_RECORD_PREFIX}${JSON.stringify(decision.noProgressClaim)}`;
|
|
3682
|
+
agent.session.append("user/message", createUserMessage({
|
|
3683
|
+
content: [{
|
|
3684
|
+
type: "text",
|
|
3685
|
+
text: record$1
|
|
3686
|
+
}],
|
|
3687
|
+
source: {
|
|
3688
|
+
kind: "plugin",
|
|
3689
|
+
plugin: "context-guard",
|
|
3690
|
+
form: "notice",
|
|
3691
|
+
summary: boundContextSummary("recording a turn boundary without relevant progress")
|
|
3692
|
+
}
|
|
3693
|
+
}), { surfaceOp: "append" });
|
|
3694
|
+
let recorded = false;
|
|
3695
|
+
try {
|
|
3696
|
+
recorded = await access$1.flush();
|
|
3697
|
+
} catch {
|
|
3698
|
+
recorded = false;
|
|
3699
|
+
}
|
|
3700
|
+
runtime.setDurability(recorded);
|
|
3701
|
+
runtime.sync();
|
|
3702
|
+
if (!recorded) return "boundary_flush_failed";
|
|
3703
|
+
}
|
|
3403
3704
|
if (decision.action === "continue") {
|
|
3404
3705
|
agent.steer(createUserMessage({
|
|
3405
3706
|
content: [{
|
|
@@ -3415,6 +3716,39 @@ async function handleGuardTurnStopping(agent, runtime, access$1) {
|
|
|
3415
3716
|
}));
|
|
3416
3717
|
return decision.reason ?? "protocol_correction_steer";
|
|
3417
3718
|
}
|
|
3719
|
+
if (decision.reason === "no_progress_bounded_disarm") {
|
|
3720
|
+
if (!access$1.goalAccess || !access$1.hostSupported) {
|
|
3721
|
+
runtime.projection.integrity = "unknown";
|
|
3722
|
+
runtime.projection.integrityViolations.push("boundary_host_lock_unsupported");
|
|
3723
|
+
return "boundary_host_lock_unsupported";
|
|
3724
|
+
}
|
|
3725
|
+
const established = await establishBoundary(agent, runtime, access$1.flush, {
|
|
3726
|
+
disposition: "guard_bounded_stop",
|
|
3727
|
+
qualificationKind: "guard_no_progress",
|
|
3728
|
+
qualificationIds: [progressFingerprint(runtime.projection)]
|
|
3729
|
+
});
|
|
3730
|
+
if (!established.boundary) return established.reasonCode;
|
|
3731
|
+
return await effectuateOwnBoundary(runtime, established.boundary, access$1);
|
|
3732
|
+
}
|
|
3733
|
+
if (decision.reason === "goal_round_driver_owns_continuation" && access$1.goalAccess) {
|
|
3734
|
+
const waiting = [...runtime.projection.items.values()].filter((item) => item.status === "pending" && item.waitAuthorization).map((item) => item.waitAuthorization.id).sort();
|
|
3735
|
+
const current = runtime.projection.boundaries.at(-1);
|
|
3736
|
+
const alreadyCurrent = current && isCurrentAcceptedBoundary(runtime.projection, current) && current.disposition === "user_wait" && current.qualificationIds.slice().sort().join(",") === waiting.join(",");
|
|
3737
|
+
if (waiting.length > 0 && !alreadyCurrent) {
|
|
3738
|
+
if (!access$1.hostSupported) {
|
|
3739
|
+
runtime.projection.integrity = "unknown";
|
|
3740
|
+
runtime.projection.integrityViolations.push("boundary_host_lock_unsupported");
|
|
3741
|
+
return "boundary_host_lock_unsupported";
|
|
3742
|
+
}
|
|
3743
|
+
const established = await establishBoundary(agent, runtime, access$1.flush, {
|
|
3744
|
+
disposition: "user_wait",
|
|
3745
|
+
qualificationKind: "root_explicit_wait",
|
|
3746
|
+
qualificationIds: waiting
|
|
3747
|
+
});
|
|
3748
|
+
if (established.boundary) return await effectuateOwnBoundary(runtime, established.boundary, access$1);
|
|
3749
|
+
return established.reasonCode;
|
|
3750
|
+
}
|
|
3751
|
+
}
|
|
3418
3752
|
if (decision.reason !== "accepted_boundary_pending_effectuation") return decision.reason ?? "safe_yield_pending_preserved";
|
|
3419
3753
|
const boundary = runtime.projection.boundaries.at(-1);
|
|
3420
3754
|
if (!boundary || !isCurrentAcceptedBoundary(runtime.projection, boundary)) return "boundary_candidate_stale";
|
|
@@ -3443,15 +3777,29 @@ async function handleGuardTurnStopping(agent, runtime, access$1) {
|
|
|
3443
3777
|
function createHostCapabilityEvaluator(hostLock) {
|
|
3444
3778
|
return (action) => evaluateHostCapability(hostLock, { action });
|
|
3445
3779
|
}
|
|
3780
|
+
/**
|
|
3781
|
+
* Durable session identity for the certificate binding, read from the
|
|
3782
|
+
* DSH Session V3 header plus the Session-owned inherited prefix length.
|
|
3783
|
+
*
|
|
3784
|
+
* Session V3 stamps `version: 3`, requires the `isSeeded` fork-lineage marker,
|
|
3785
|
+
* and moved the inherited-prefix length off the header onto the `Session`
|
|
3786
|
+
* (`inheritedEventCount`). Anything else is not a V3 identity: returning
|
|
3787
|
+
* `undefined` makes the projection report `session_ref_unavailable` instead of
|
|
3788
|
+
* certifying against a guessed identity.
|
|
3789
|
+
*/
|
|
3446
3790
|
function sessionHeaderForDigest(session) {
|
|
3447
3791
|
const raw = session.header;
|
|
3448
|
-
if (!raw ||
|
|
3792
|
+
if (!raw || raw.version !== SESSION_FORMAT_VERSION) return void 0;
|
|
3793
|
+
if (typeof raw.id !== "string" || typeof raw.createdAt !== "number") return void 0;
|
|
3794
|
+
if (typeof raw.isSeeded !== "boolean") return void 0;
|
|
3795
|
+
const inherited = session.inheritedEventCount;
|
|
3796
|
+
if (typeof inherited !== "number" || !Number.isSafeInteger(inherited) || inherited < 0) return void 0;
|
|
3449
3797
|
return {
|
|
3450
3798
|
version: raw.version,
|
|
3451
3799
|
id: raw.id,
|
|
3452
3800
|
createdAt: raw.createdAt,
|
|
3453
3801
|
...typeof raw.parentSession === "string" ? { parentSession: raw.parentSession } : {},
|
|
3454
|
-
|
|
3802
|
+
seedLength: inherited,
|
|
3455
3803
|
...typeof raw.agentPreset === "string" ? { agentPreset: raw.agentPreset } : {},
|
|
3456
3804
|
...typeof raw.origin === "string" ? { origin: raw.origin } : {},
|
|
3457
3805
|
delegationDepth: typeof raw.delegationDepth === "number" ? raw.delegationDepth : 0
|
|
@@ -3465,17 +3813,34 @@ function createRuntime(agent, config, hostLock = DEFAULT_HOST_LOCK, readGoalStat
|
|
|
3465
3813
|
let observedEpoch = -1;
|
|
3466
3814
|
let observedCompactionSeq = -1;
|
|
3467
3815
|
let observedContractRevision = -1;
|
|
3816
|
+
let protocolV4Present = false;
|
|
3817
|
+
let realRootInputSeen = false;
|
|
3818
|
+
let lifecycle = "armed";
|
|
3468
3819
|
const continuationAttempts = projection.continuationAttempts;
|
|
3469
3820
|
const persistenceCorrectionAttempts = projection.persistenceCorrectionAttempts;
|
|
3470
3821
|
const rebuild = () => {
|
|
3471
3822
|
if (refreshHostLock) hostLock = refreshHostLock();
|
|
3472
3823
|
const header = session.header;
|
|
3473
3824
|
const priorRecoveryDigest = projection.lastRecoveryDigest;
|
|
3474
|
-
const
|
|
3825
|
+
const sessionHeader = sessionHeaderForDigest(session);
|
|
3826
|
+
let events;
|
|
3827
|
+
try {
|
|
3828
|
+
events = snapshotSessionEvents(session);
|
|
3829
|
+
} catch (error) {
|
|
3830
|
+
const code = error instanceof SessionApiError ? error.code : "session_snapshot_failed";
|
|
3831
|
+
projection.integrity = "unknown";
|
|
3832
|
+
if (!projection.integrityViolations.includes(code)) projection.integrityViolations.push(code);
|
|
3833
|
+
return;
|
|
3834
|
+
}
|
|
3835
|
+
const derived = deriveProjection(events, { activation: config.activation }, {
|
|
3475
3836
|
cwd: typeof header?.cwd === "string" ? header.cwd : "",
|
|
3476
|
-
sessionHeader
|
|
3837
|
+
sessionHeader
|
|
3477
3838
|
}, durabilityConfirmed, hostLock);
|
|
3478
3839
|
Object.assign(projection, derived.projection);
|
|
3840
|
+
if (!sessionHeader) {
|
|
3841
|
+
projection.integrity = "unknown";
|
|
3842
|
+
if (!projection.integrityViolations.includes("session_ref_unavailable")) projection.integrityViolations.push("session_ref_unavailable");
|
|
3843
|
+
}
|
|
3479
3844
|
if (readGoalState) try {
|
|
3480
3845
|
const state = normalizeGoalState(readGoalState());
|
|
3481
3846
|
if (state && projection.currentGoalRef?.id === state.id && projection.currentGoalRef.revision === state.revision) {
|
|
@@ -3489,6 +3854,12 @@ function createRuntime(agent, config, hostLock = DEFAULT_HOST_LOCK, readGoalStat
|
|
|
3489
3854
|
projection.continuationAttempts = continuationAttempts;
|
|
3490
3855
|
projection.persistenceCorrectionAttempts = persistenceCorrectionAttempts;
|
|
3491
3856
|
projection.lastRecoveryDigest = priorRecoveryDigest;
|
|
3857
|
+
protocolV4Present = derived.protocolV4Present;
|
|
3858
|
+
realRootInputSeen = derived.realRootInputSeen;
|
|
3859
|
+
lifecycle = lifecyclePhase({
|
|
3860
|
+
enabled: projection.enabled,
|
|
3861
|
+
realInputSeen: realRootInputSeen
|
|
3862
|
+
});
|
|
3492
3863
|
if (observedEpoch >= 0 && derived.projection.epoch > observedEpoch) {
|
|
3493
3864
|
pendingRecovery = true;
|
|
3494
3865
|
projection.lastRecoveryDigest = void 0;
|
|
@@ -3523,6 +3894,12 @@ function createRuntime(agent, config, hostLock = DEFAULT_HOST_LOCK, readGoalStat
|
|
|
3523
3894
|
return {
|
|
3524
3895
|
projection,
|
|
3525
3896
|
session,
|
|
3897
|
+
get lifecycle() {
|
|
3898
|
+
return lifecycle;
|
|
3899
|
+
},
|
|
3900
|
+
get protocolV4Present() {
|
|
3901
|
+
return protocolV4Present;
|
|
3902
|
+
},
|
|
3526
3903
|
sync,
|
|
3527
3904
|
setEnabled,
|
|
3528
3905
|
setDurability,
|
|
@@ -3530,6 +3907,11 @@ function createRuntime(agent, config, hostLock = DEFAULT_HOST_LOCK, readGoalStat
|
|
|
3530
3907
|
consumeRecovery
|
|
3531
3908
|
};
|
|
3532
3909
|
}
|
|
3910
|
+
/** Delegated/subagent sessions never receive root-conversation injections. */
|
|
3911
|
+
function isDelegatedSession(session) {
|
|
3912
|
+
const header = session.header;
|
|
3913
|
+
return header?.origin === "subagent" || typeof header?.delegationDepth === "number" && header.delegationDepth > 0 || typeof header?.parentSession === "string";
|
|
3914
|
+
}
|
|
3533
3915
|
/** Never reinterpret a legacy injected snapshot as freshly accepted core/v1. */
|
|
3534
3916
|
function revalidateCoreLock(config, expected) {
|
|
3535
3917
|
if (config.hostLockPolicy !== "dsh-core/v1" || !config.hostLockRuntimeRoot || !config.hostLockProfileRoot) return {
|
|
@@ -3585,10 +3967,8 @@ function apply(ctx, rawConfig = {}) {
|
|
|
3585
3967
|
}
|
|
3586
3968
|
return runtime;
|
|
3587
3969
|
};
|
|
3588
|
-
ctx.commands.register(createContextGuardCommand((agent) => ensure(agent).projection, (agent, enabled) => ensure(agent).setEnabled(enabled), (agent) => ensure(agent).sync()));
|
|
3970
|
+
ctx.commands.register(createContextGuardCommand((agent) => ensure(agent).projection, (agent, enabled) => ensure(agent).setEnabled(enabled), (agent) => ensure(agent).sync(), (agent) => ensure(agent).lifecycle));
|
|
3589
3971
|
ctx.on("agent/session-start", ({ agent, source }) => {
|
|
3590
|
-
ensureProtocolBoundary(agent);
|
|
3591
|
-
ensureProtocolBoundary(agent, CAPTURE_V042_NOTICE);
|
|
3592
3972
|
const runtime = ensure(agent);
|
|
3593
3973
|
runtime.sync();
|
|
3594
3974
|
if (source === "resume" || source === "compact") {
|
|
@@ -3655,6 +4035,17 @@ function apply(ctx, rawConfig = {}) {
|
|
|
3655
4035
|
};
|
|
3656
4036
|
agent.ctx.tools.register(createEvidenceTool(evidenceOptions));
|
|
3657
4037
|
agent.ctx.tools.register(createActionTool(evidenceOptions));
|
|
4038
|
+
agent.ctx.tools.register(createPrepareTool({
|
|
4039
|
+
getProjection: () => runtime.projection,
|
|
4040
|
+
hostCapability: (action) => {
|
|
4041
|
+
const evaluation = createHostCapabilityEvaluator(hostLocks.get(agent) ?? installedHostLock)(action);
|
|
4042
|
+
return {
|
|
4043
|
+
status: evaluation.status,
|
|
4044
|
+
reasonCode: evaluation.reasonCode
|
|
4045
|
+
};
|
|
4046
|
+
},
|
|
4047
|
+
commandTemplate: (action) => GIT_COMMAND_TEMPLATES[action]
|
|
4048
|
+
}));
|
|
3658
4049
|
agent.ctx.tools.register(createExternalOperationTool((id, toolAgent) => readExternalOperation(ctx, toolAgent, id), () => evaluateExternalWaitCapability(hostLocks.get(agent) ?? installedHostLock)));
|
|
3659
4050
|
agent.ctx.tools.guard((exec) => goalCompletionDenial(runtime.projection, exec.name, exec.arguments));
|
|
3660
4051
|
});
|
|
@@ -3664,12 +4055,33 @@ function apply(ctx, rawConfig = {}) {
|
|
|
3664
4055
|
runtime.setDurability(durability);
|
|
3665
4056
|
runtime.sync();
|
|
3666
4057
|
const decision = await next();
|
|
3667
|
-
if (decision.kind
|
|
3668
|
-
|
|
4058
|
+
if (decision.kind !== "enter") return decision;
|
|
4059
|
+
const injected = [];
|
|
4060
|
+
const delegated = isDelegatedSession(agent.session);
|
|
4061
|
+
let boundaryPending = !runtime.protocolV4Present;
|
|
4062
|
+
const firstStep = previewFirstStepInjection({
|
|
4063
|
+
activation: config.activation,
|
|
4064
|
+
enabled: runtime.projection.enabled,
|
|
4065
|
+
boundaryPresent: runtime.protocolV4Present,
|
|
4066
|
+
delegated
|
|
4067
|
+
}, claimedBatchHasRealRootInput(decision.messages));
|
|
4068
|
+
if (firstStep) {
|
|
4069
|
+
injected.push(pluginNoticeMessage(firstStep.boundary, "Context Guard recorded a replay version boundary"));
|
|
4070
|
+
if (runtime.lifecycle === "armed") injected.push(pluginNoticeMessage(firstStep.guidance, "Context Guard first-step protection guidance"));
|
|
4071
|
+
boundaryPending = false;
|
|
4072
|
+
}
|
|
4073
|
+
if (runtime.projection.enabled && runtime.consumeRecovery()) {
|
|
4074
|
+
const hasOpenWork = [...runtime.projection.items.values()].some((item) => item.status === "pending");
|
|
4075
|
+
const hasRejections = (runtime.projection.lastCheckpointRejections?.length ?? 0) > 0;
|
|
4076
|
+
const recovery = hasOpenWork || hasRejections ? renderRecoveryPacket(runtime.projection, { charBudget: 4e3 }) : void 0;
|
|
3669
4077
|
const digest$2 = recovery ? recoveryDigest(recovery, runtime.projection) : void 0;
|
|
3670
4078
|
if (recovery && digest$2 !== runtime.projection.lastRecoveryDigest) {
|
|
3671
4079
|
runtime.projection.lastRecoveryDigest = digest$2;
|
|
3672
|
-
|
|
4080
|
+
if (boundaryPending && !delegated) {
|
|
4081
|
+
injected.push(pluginNoticeMessage(PROTOCOL_V4_NOTICE, "Context Guard recorded a replay version boundary"));
|
|
4082
|
+
boundaryPending = false;
|
|
4083
|
+
}
|
|
4084
|
+
injected.push(createUserMessage({
|
|
3673
4085
|
content: [{
|
|
3674
4086
|
type: "text",
|
|
3675
4087
|
text: `Open task requirements (recovered after compaction or resume):\n${recovery}`
|
|
@@ -3680,9 +4092,10 @@ function apply(ctx, rawConfig = {}) {
|
|
|
3680
4092
|
form: "notice",
|
|
3681
4093
|
summary: boundContextSummary("recovering open task requirements")
|
|
3682
4094
|
}
|
|
3683
|
-
})
|
|
4095
|
+
}));
|
|
3684
4096
|
}
|
|
3685
4097
|
}
|
|
4098
|
+
if (injected.length > 0) decision.messages = [...injected, ...decision.messages];
|
|
3686
4099
|
return decision;
|
|
3687
4100
|
});
|
|
3688
4101
|
ctx.on("agent/turn-stopping", async ({ agent }) => {
|
|
@@ -3724,26 +4137,20 @@ function optionalMarketOrigin(ctx, agent) {
|
|
|
3724
4137
|
return `http://${service.host === "::1" ? "[::1]" : "127.0.0.1"}:${service.port}`;
|
|
3725
4138
|
} catch {}
|
|
3726
4139
|
}
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
const data = event.data;
|
|
3731
|
-
const source = data.source && typeof data.source === "object" ? data.source : void 0;
|
|
3732
|
-
const content = Array.isArray(data.content) ? data.content : [];
|
|
3733
|
-
return (content.length === 1 && content[0] && typeof content[0] === "object" ? content[0].text : void 0) === notice && source?.kind === "plugin" && source.plugin === "context-guard" && source.form === "notice";
|
|
3734
|
-
})) return;
|
|
3735
|
-
agent.session.append.bind(agent.session)("user/message", createUserMessage({
|
|
4140
|
+
/** Build one host-approved plugin notice user/message for step-batch delivery. */
|
|
4141
|
+
function pluginNoticeMessage(text, summaryLabel) {
|
|
4142
|
+
return createUserMessage({
|
|
3736
4143
|
content: [{
|
|
3737
4144
|
type: "text",
|
|
3738
|
-
text
|
|
4145
|
+
text
|
|
3739
4146
|
}],
|
|
3740
4147
|
source: {
|
|
3741
4148
|
kind: "plugin",
|
|
3742
4149
|
plugin: "context-guard",
|
|
3743
4150
|
form: "notice",
|
|
3744
|
-
summary: boundContextSummary(
|
|
4151
|
+
summary: boundContextSummary(summaryLabel)
|
|
3745
4152
|
}
|
|
3746
|
-
})
|
|
4153
|
+
});
|
|
3747
4154
|
}
|
|
3748
4155
|
function hasPinnedUpdateGoalTool(agent) {
|
|
3749
4156
|
try {
|
|
@@ -3815,4 +4222,4 @@ function normalizeGoalState(value) {
|
|
|
3815
4222
|
}
|
|
3816
4223
|
|
|
3817
4224
|
//#endregion
|
|
3818
|
-
export { ACTION_MANIFEST, ACTION_MANIFEST_VERSION, ALPHA2_DSHMARKET_139_HOST_PACKAGES, ALPHA2_HOST_PACKAGES, ALPHA3_HOST_PACKAGES, BASE_HOST_PACKAGES, CAPTURE_V042_NOTICE, CERTIFICATE_VERSION, COMMAND_SURFACE_MANIFEST, Config, DEFAULT_HOST_LOCK, DEFAULT_RECOVERY_CHAR_BUDGET, EXPECTED_HOST_PACKAGES, GIT_COMMAND_MANIFEST_IDS, GOAL_HOST_PACKAGES, HOST_CAPABILITY_PACKAGE_GROUPS, HOST_COHORTS, HostProfileError, LEGACY_HOST_COHORTS, MIN_RECOVERY_CHAR_BUDGET, PROOF_KINDS, PROOF_PROTOCOL_VERSION, PROTOCOL_V3_NOTICE, RC1_HOST_PACKAGES, SEMANTIC_ACTIONS, STATEFUL_ACTIONS, STOP_PROTOCOL_VERSION, SUPPORTED_EVIDENCE_ADAPTERS, actionCompatible, apply, authorityCaptureCounts, availableBoundaryQualifications, bindExecutableIdentity, bindLiveGoalCapability, bindProofToProjection, bindingSatisfies, canonicalArgvFromCommand, canonicalProjection, canonicalizePath, captureClause, captureItem, certifyCheckpoint, classifyClause, classifyCompletionClaim, classifyUserInteraction, closingHint, commitIndexSnapshotDigest, commitTreeSnapshotDigest, createGitPrestateEnvelope, createProjection, createProofManifest, currentContractDigest, decideTurnBoundary, decideTurnStopping, deriveProjection, digestStrings, effectuateBoundary, evaluateExternalWaitCapability, evaluateHostCapability, evaluateHostLock, evaluateToolSurfaceCapability, evidenceCoverage, evidenceFromPersistedToolResult, evidenceMatchesItem, executeRevalidatedGitEffect, extractArtifactPaths, extractMethod, extractOperation, extractTextContent, extractToolSubject, gitCommandMatchesTarget, goalCompletionDenial, hasCurrentCertificate, hostLockContextFromComposedDump, hostLockRowsFromComposedDump, inject, injectActiveProfileHostLock, inspectTargetHostGraph, isCurrentAcceptedBoundary, isDeterministicCheck, isInformationalMessage, isRunExecutable, isStatefulAction, isVerifyingCapability, isWholeTaskCompletionClaim, latestAssistantText, name, normalizeClause, observeAssistantOutcome, openItems, packageRowsFromActiveGraph, packageRowsFromPnpmLock, parseGitCommandManifest, parsePwshCommand, parseShellCommand, proofDigest, proofEvidenceConstraints, qualifyBoundary, readActiveHostGraph, recoveryDigest, renderRecoveryPacket, requestedTargetAuthorizesMutation, requestedTargetMatchesResolved, resolveActiveProfileHostLock, resolveInstalledHostLock, revalidateGitPrestate, sanitizeClauseText, sanitizeUrl, segmentAuthorityBlocks, segmentClauses, selectHostCohort, semanticActionFromCommand, semanticActionFromText, sessionQuery, sha256, snapshotSessionEvents, supersedeItem, validateActionManifest, validateActionTarget, validateManifest, validateProofManifest, verifiedLinearCommitReadback, verifyComposedHostLockDump, withDurability };
|
|
4225
|
+
export { ACTION_MANIFEST, ACTION_MANIFEST_VERSION, ACTIVE_HOST_COHORT_ID, ACTIVE_HOST_COHORT_IDS, ACTIVE_HOST_LAUNCHER_VERSION, ALPHA2_DSHMARKET_139_HOST_PACKAGES, ALPHA2_HOST_PACKAGES, ALPHA3_HOST_PACKAGES, BASE_HOST_PACKAGES, CAPTURE_V042_NOTICE, CERTIFICATE_VERSION, COMMAND_SURFACE_MANIFEST, CONFIRM_LINE_PATTERN, CONTROL_RECORD_PREFIX, Config, DEFAULT_HOST_LOCK, DEFAULT_RECOVERY_CHAR_BUDGET, EXPECTED_HOST_PACKAGES, FIRST_STEP_GUIDANCE, GIT_COMMAND_MANIFEST_IDS, GIT_COMMAND_TEMPLATES, GOAL_HOST_PACKAGES, HOST_CAPABILITY_PACKAGE_GROUPS, HOST_COHORTS, HostProfileError, LEGACY_HOST_COHORTS, MIN_RECOVERY_CHAR_BUDGET, MIN_SUPPORTED_HOST_VERSION, NO_PROGRESS_RECORD_PREFIX, NO_PROGRESS_TURNS_BEFORE_STOP, PROOF_KINDS, PROOF_PROTOCOL_VERSION, PROTOCOL_V3_NOTICE, PROTOCOL_V4_NOTICE, RC015_HOST_PACKAGES, RC015_RC2_HOST_PACKAGES, RC1_HOST_PACKAGES, SEMANTIC_ACTIONS, SESSION_API_UNSUPPORTED, SESSION_EVENT_ENVELOPE_INVALID, STATEFUL_ACTIONS, STOP_PROTOCOL_VERSION, SUPPORTED_EVIDENCE_ADAPTERS, SUPPORTED_HOST_RANGE, SessionApiError, actionCompatible, apply, authorityCaptureCounts, availableBoundaryQualifications, bindExecutableIdentity, bindLiveGoalCapability, bindProofToProjection, bindingSatisfies, canonicalArgvFromCommand, canonicalProjection, canonicalizePath, captureClause, captureItem, certifyCheckpoint, claimedBatchHasRealRootInput, classifyClause, classifyCompletionClaim, classifyTaskIntent, classifyUserInteraction, closingHint, combineHostPolicy, commitIndexSnapshotDigest, commitTreeSnapshotDigest, compareHostVersions, confirmRebind, createGitPrestateEnvelope, createProjection, createProofManifest, currentContractDigest, decideTurnBoundary, decideTurnStopping, decisionBoundaryKey, deriveItemDiagnosis, deriveProjection, digestStrings, effectuateBoundary, evaluateExternalWaitCapability, evaluateHostCapability, evaluateHostLock, evaluateMinimumHostVersion, evaluateToolSurfaceCapability, evidenceAvailabilityReason, evidenceCoverage, evidenceFromPersistedToolResult, evidenceMatchesItem, executeRevalidatedGitEffect, extractArtifactPaths, extractMethod, extractOperation, extractTextContent, extractToolSubject, gitCommandMatchesTarget, goalCompletionDenial, hasCurrentCertificate, hostLockContextFromComposedDump, hostLockRowsFromComposedDump, hostVersionFromPackages, inject, injectActiveProfileHostLock, inspectTargetHostGraph, interpretClause, interpretMessage, isCurrentAcceptedBoundary, isDeterministicCheck, isExecutableItem, isFrozenV042RebindResponse, isInformationalMessage, isOpenObligation, isRootPauseRequest, isRunExecutable, isStatefulAction, isVerifyingCapability, isWholeTaskCompletionClaim, itemDiagnosis, kindOfScope, latestAssistantText, latestRootInstruction, lifecyclePhase, maskCodeSpans, name, namedActions, normalizeClause, observeAssistantOutcome, openItems, packageRowsFromActiveGraph, packageRowsFromPnpmLock, parseConfirmationMessage, parseGitCommandManifest, parseHostVersion, parsePwshCommand, parseShellCommand, previewFirstStepInjection, progressFingerprint, proofDigest, proofEvidenceConstraints, proposeRebind, proposeRebindOutcome, proposeRebindV042, qualifyBoundary, readActiveHostGraph, rebindAttemptKey, rebindResponse, recoveryDigest, relevantEvidence, renderRecoveryPacket, replayRebindResult, requestedTargetAuthorizesMutation, requestedTargetMatchesResolved, resolveActiveProfileHostLock, resolveInstalledHostLock, revalidateGitPrestate, sanitizeClauseText, sanitizeUrl, satisfiesSupportedHostRange, segmentAuthorityBlocks, segmentClauses, selectHostCohort, semanticActionFromCommand, semanticActionFromText, semanticActionOfScope, sessionQuery, sha256, snapshotSessionEvents, statefulActionsOfScope, supersedeItem, validateActionManifest, validateActionTarget, validateManifest, validateProofManifest, verifiedLinearCommitReadback, verifyComposedHostLockDump, withDurability };
|