dsh-completion-guard 0.5.3 → 0.6.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 +332 -0
- package/CHANGELOG.zh-CN.md +116 -0
- package/README.md +107 -9
- package/README.zh-CN.md +60 -9
- package/dist/domain/index.d.ts +2 -2
- package/dist/domain/index.js +2 -2
- package/dist/{domain-RuX9l07o.js → domain-DKr8sLZZ.js} +3306 -393
- package/dist/{index-BTaiOcE-.d.ts → index-C_N6DaSF.d.ts} +570 -7
- package/dist/index.d.ts +127 -3
- package/dist/index.js +1139 -87
- package/docs/ARCHITECTURE.md +88 -0
- package/docs/LOCAL_ACCEPTANCE.md +199 -0
- package/docs/NEXT_VERSION_REPAIR_NOTES.md +45 -2
- package/docs/PORTING_NOTES.md +36 -2
- package/docs/SEMANTIC_COMPATIBILITY.md +123 -0
- package/docs/WINDOWS_0_6_0_REPAIR_PLAN.md +92 -0
- package/docs/upstream-deltas.json +90 -9
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as
|
|
1
|
+
import { $ as extractToolSubject, $n as isFrozenV042RebindResponse, $r as sha256, $t as proofDigest, A as lifecyclePhase, An as decisionBoundaryKey, Ar as STATEFUL_ACTIONS, At as compareHostVersions, B as RELEASE_RESERVATION_PREFIX, Bn as effectuateBoundary, Br as semanticActionFromCommand, Bt as certifyCheckpoint, C as gitCommandMatchesTarget, Cn as isVerifyingCapability, Cr as npmEscapedPackageName, Ct as evaluateToolSurfaceCapability, D as FIRST_STEP_GUIDANCE, Dn as classifyCompletionClaim, Dr as CERTIFICATE_VERSION, Dt as MIN_SUPPORTED_HOST_VERSION, E as verifiedLinearCommitReadback, En as NO_PROGRESS_TURNS_BEFORE_STOP, Er as BOUNDED_ARTIFACT_TYPES, Et as LATEST_SUPPORTED_HOST_VERSION, F as PROTOCOL_V4_NOTICE, Fn as observeAssistantOutcome, Fr as boundedArtifactChoiceMatches, Ft as RC015_HOST_PACKAGES, G as readbackSettlesContract, Gn as confirmRebind, Gr as validateManifest, Gt as PROOF_PROTOCOL_VERSION, H as contractById, Hn as qualifyBoundary, Hr as validateActionManifest, Ht as PROOF_KINDS, I as PROTOCOL_V5_NOTICE, In as progressFingerprint, Ir as isStatefulAction, It as RC1_HOST_PACKAGES, J as releasePreEffectDecision, Jn as proposeRebindV042, Jr as canonicalizePath, Jt as bindProofV2ToProjection, K as releaseContractFor, Kn as proposeRebind, Kr as classifyTaskIntent, Kt as PROOF_PROTOCOL_VERSION_V2, L as deriveProjection, Ln as goalCompletionDenial, Lr as requestedIdentityKey, Lt as ALPHA3_HOST_PACKAGES, M as CAPTURE_V042_NOTICE, Mn as isWholeTaskCompletionClaim, Mr as STOP_PROTOCOL_VERSION_V2, Mt as parseHostVersion, N as DEFAULT_DELEGATION_TOOL_NAMES, Nn as latestAssistantText, Nr as SUPPORTED_EVIDENCE_ADAPTERS, Nt as satisfiesSupportedHostRange, O as claimedBatchHasRealRootInput, On as decideTurnBoundary, Or as CERTIFICATE_VERSION_V2, Ot as SUPPORTED_HOST_RANGE, P as PROTOCOL_V3_NOTICE, Pn as latestRootInstruction, Pr as actionCompatible, Pt as RC015_RC2_HOST_PACKAGES, Q as extractTextContent, Qn as CONFIRM_LINE_PATTERN, Qr as sanitizeUrl, Qt as proofCapabilityReport, R as RELEASE_OPERATIONS, Rn as hasCurrentCertificate, Rr as requestedTargetAuthorizesMutation, Rt as authorityCaptureCounts, S as executeRevalidatedGitEffect, Sn as evidenceMatchesItem, Sr as canonicalRegistryBase, St as evaluateHostLock, T as revalidateGitPrestate, Tn as NO_PROGRESS_RECORD_PREFIX, Tr as ACTION_MANIFEST_VERSION, Tt as selectHostCohort, U as inFlightReservation, Un as currentContractDigest, Ur as validateActionTarget, Ut as PROOF_KINDS_V2, V as RELEASE_SETTLEMENT_PREFIX, Vn as isCurrentAcceptedBoundary, Vr as semanticActionFromText, Vt as PROOF_CAPABILITY_MATRIX, W as normalizeReleaseContract, Wn as createProjection, Wr as COMMAND_SURFACE_MANIFEST, Wt as PROOF_MANIFEST_DOMAIN_V2, X as supersedeItem, Xn as rebindResponse, Xr as normalizeClause, Xt as createProofManifest, Y as reservationFor, Yn as rebindAttemptKey, Yr as digestStrings, Yt as canonicalProjection, Z as evidenceFromPersistedToolResult, Zn as replayRebindResult, Zr as sanitizeClauseText, Zt as createProofManifestV2, _ as GIT_COMMAND_MANIFEST_IDS, _n as openItems, _r as kindOfScope, _t as LEGACY_HOST_COHORTS, a as injectActiveProfileHostLock, an as requiredSubjectsOf, ar as captureClause, at as parseShellCommand, b as commitTreeSnapshotDigest, bn as bindingSatisfies, br as semanticActionOfScope, bt as evaluateExternalWaitCapability, c as packageRowsFromPnpmLock, cn as sessionQueryV2, cr as extractArtifactPaths, ct as ACTIVE_HOST_LAUNCHER_VERSION, d as resolveInstalledHostLock, dn as certifiableOpenItems, dr as isInformationalMessage, dt as BASE_HOST_PACKAGES, en as proofDigestV2, er as parseConfirmationMessage, et as isDeterministicCheck, f as verifyComposedHostLockDump, fn as certificateClosure, fr as segmentClauses, ft as DEFAULT_HOST_LOCK, g as snapshotSessionEvents, gn as closingHint, gr as isOpenObligation, gt as HOST_COHORTS, h as SessionApiError, hn as MIN_RECOVERY_CHAR_BUDGET, hr as isExecutableItem, ht as HOST_CAPABILITY_PACKAGE_GROUPS, i as hostLockRowsFromComposedDump, in as proofV2Rejection, ir as relevantEvidence, it as parsePwshCommand, j as previewFirstStepInjection, jn as isRootPauseRequest, jr as STOP_PROTOCOL_VERSION, jt as evaluateMinimumHostVersion, k as firstStepGuidance, kn as decideTurnStopping, kr as SEMANTIC_ACTIONS, kt as SUPPORTED_HOST_VERSIONS, l as readActiveHostGraph, ln as validateProofManifest, lr as extractMethod, lt as ALPHA2_DSHMARKET_139_HOST_PACKAGES, m as SESSION_EVENT_ENVELOPE_INVALID, mn as DEFAULT_RECOVERY_CHAR_BUDGET, mr as interpretMessage, mt as GOAL_HOST_PACKAGES, n as combineHostPolicy, nn as proofHostSurfacesOf, nr as evidenceAvailabilityReason, nt as canonicalArgvFromCommand, o as inspectTargetHostGraph, on as scopeCoverageDigest, or as captureItem, ot as ACTIVE_HOST_COHORT_ID, p as SESSION_API_UNSUPPORTED, pn as unitDescendantIds, pr as interpretClause, pt as EXPECTED_HOST_PACKAGES, q as releaseCoverage, qn as proposeRebindOutcome, qr as classifyUserInteraction, qt as bindProofToProjection, r as hostLockContextFromComposedDump, rn as proofOperationMatches, rr as itemDiagnosis, rt as isRunExecutable, s as packageRowsFromActiveGraph, sn as sessionQuery, sr as classifyClause, st as ACTIVE_HOST_COHORT_IDS, t as HostProfileError, tn as proofEvidenceConstraints, tr as deriveItemDiagnosis, tt as withDurability, u as resolveActiveProfileHostLock, un as validateProofManifestV2, ur as extractOperation, ut as ALPHA2_HOST_PACKAGES, v as GIT_COMMAND_TEMPLATES, vn as recoveryDigest, vr as maskCodeSpans, vt as bindExecutableIdentity, w as parseGitCommandManifest, wn as CONTROL_RECORD_PREFIX, wr as ACTION_MANIFEST, wt as hostVersionFromPackages, x as createGitPrestateEnvelope, xn as evidenceCoverage, xr as statefulActionsOfScope, xt as evaluateHostCapability, y as commitIndexSnapshotDigest, yn as renderRecoveryPacket, yr as namedActions, yt as bindLiveGoalCapability, z as RELEASE_OPERATION_SURFACES, zn as availableBoundaryQualifications, zr as requestedTargetMatchesResolved, zt as segmentAuthorityBlocks } from "./domain-DKr8sLZZ.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";
|
|
@@ -166,6 +166,7 @@ function checkpointPage(p, query, full) {
|
|
|
166
166
|
available_qualifications: []
|
|
167
167
|
};
|
|
168
168
|
if (full.certificate) output.certificate = full.certificate;
|
|
169
|
+
if (full.proof_state) output.proof_state = full.proof_state;
|
|
169
170
|
const pagination = {
|
|
170
171
|
snapshot: identity,
|
|
171
172
|
scope: evidence_scope,
|
|
@@ -357,6 +358,10 @@ function createCheckpointTool(getProjection, onRejected, prepare = async () => t
|
|
|
357
358
|
detail_id: { type: "string" },
|
|
358
359
|
detail_offset: { type: "integer" },
|
|
359
360
|
detail_snapshot: { type: "string" },
|
|
361
|
+
proof: {
|
|
362
|
+
type: "object",
|
|
363
|
+
additionalProperties: true
|
|
364
|
+
},
|
|
360
365
|
bindings: {
|
|
361
366
|
type: "array",
|
|
362
367
|
required: true,
|
|
@@ -460,6 +465,25 @@ function createCheckpointTool(getProjection, onRejected, prepare = async () => t
|
|
|
460
465
|
type: "object",
|
|
461
466
|
additionalProperties: true
|
|
462
467
|
},
|
|
468
|
+
proof_state: {
|
|
469
|
+
type: "object",
|
|
470
|
+
additionalProperties: false,
|
|
471
|
+
properties: {
|
|
472
|
+
status: {
|
|
473
|
+
type: "string",
|
|
474
|
+
enum: [
|
|
475
|
+
"absent",
|
|
476
|
+
"bound",
|
|
477
|
+
"rejected",
|
|
478
|
+
"invalid"
|
|
479
|
+
]
|
|
480
|
+
},
|
|
481
|
+
reason_codes: {
|
|
482
|
+
type: "array",
|
|
483
|
+
items: { type: "string" }
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
},
|
|
463
487
|
reason_code: { type: "string" },
|
|
464
488
|
next_step: { type: "string" },
|
|
465
489
|
detail_id: { type: "string" },
|
|
@@ -599,6 +623,8 @@ function createCheckpointTool(getProjection, onRejected, prepare = async () => t
|
|
|
599
623
|
evidence_sha256: { type: "string" },
|
|
600
624
|
binding_digest: { type: "string" },
|
|
601
625
|
certification_digest: { type: "string" },
|
|
626
|
+
unit_id: { type: "string" },
|
|
627
|
+
unit_closure_digest: { type: "string" },
|
|
602
628
|
goal_ref: { oneOf: [{
|
|
603
629
|
type: "object",
|
|
604
630
|
additionalProperties: false,
|
|
@@ -631,7 +657,7 @@ function createCheckpointTool(getProjection, onRejected, prepare = async () => t
|
|
|
631
657
|
rejected_bindings: []
|
|
632
658
|
};
|
|
633
659
|
}
|
|
634
|
-
const
|
|
660
|
+
const bindings = args.bindings.map((binding) => ({
|
|
635
661
|
itemId: binding.item_id,
|
|
636
662
|
evidenceIds: binding.evidence_ids,
|
|
637
663
|
...binding.semantic_action ? { semanticAction: binding.semantic_action } : {},
|
|
@@ -654,7 +680,39 @@ function createCheckpointTool(getProjection, onRejected, prepare = async () => t
|
|
|
654
680
|
resolvedTarget: closure.resolved_target,
|
|
655
681
|
order: closure.order
|
|
656
682
|
})) } : {}
|
|
657
|
-
}))
|
|
683
|
+
}));
|
|
684
|
+
let proofState = {
|
|
685
|
+
status: "absent",
|
|
686
|
+
reason_codes: []
|
|
687
|
+
};
|
|
688
|
+
if (args.proof !== void 0) {
|
|
689
|
+
const structural = validateProofManifestV2(args.proof);
|
|
690
|
+
if (structural.length) proofState = {
|
|
691
|
+
status: "invalid",
|
|
692
|
+
reason_codes: structural
|
|
693
|
+
};
|
|
694
|
+
else {
|
|
695
|
+
const binding = bindProofV2ToProjection(projection, args.proof);
|
|
696
|
+
proofState = binding.length ? {
|
|
697
|
+
status: "rejected",
|
|
698
|
+
reason_codes: binding
|
|
699
|
+
} : {
|
|
700
|
+
status: "bound",
|
|
701
|
+
reason_codes: []
|
|
702
|
+
};
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
const result = proofState.status === "rejected" || proofState.status === "invalid" ? {
|
|
706
|
+
status: "incomplete",
|
|
707
|
+
contractRevision: projection.contractRevision,
|
|
708
|
+
openItems: [],
|
|
709
|
+
rejectedBindings: []
|
|
710
|
+
} : certifyCheckpoint(projection, bindings, `C${projection.checkpoints.length + 1}`, false);
|
|
711
|
+
if (proofState.status === "rejected" || proofState.status === "invalid") for (const code of proofState.reason_codes) result.rejectedBindings.push({
|
|
712
|
+
itemId: "*",
|
|
713
|
+
reason: "the presented proof does not bind the current contract",
|
|
714
|
+
reasonCode: code
|
|
715
|
+
});
|
|
658
716
|
if (!result.checkpoint) onRejected();
|
|
659
717
|
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) => ({
|
|
660
718
|
id: evidence.id,
|
|
@@ -680,6 +738,7 @@ function createCheckpointTool(getProjection, onRejected, prepare = async () => t
|
|
|
680
738
|
}));
|
|
681
739
|
return checkpointPage(projection, args, {
|
|
682
740
|
status: result.status,
|
|
741
|
+
proof_state: proofState,
|
|
683
742
|
contract_revision: result.contractRevision,
|
|
684
743
|
blocking_total: result.openItems.length,
|
|
685
744
|
open_items: (args.item_ids?.length ? args.item_ids : result.openItems).map((id) => projection.items.get(id)).filter((item) => Boolean(item)).sort((a, b) => b.revision - a.revision || a.id.localeCompare(b.id)).map((item) => openItemForTool(projection, item)),
|
|
@@ -711,6 +770,10 @@ function createCheckpointTool(getProjection, onRejected, prepare = async () => t
|
|
|
711
770
|
evidence_sha256: result.checkpoint.evidenceSha256,
|
|
712
771
|
binding_digest: result.checkpoint.bindingDigest,
|
|
713
772
|
certification_digest: result.checkpoint.certificationDigest,
|
|
773
|
+
...result.checkpoint.unitId !== void 0 ? {
|
|
774
|
+
unit_id: result.checkpoint.unitId,
|
|
775
|
+
unit_closure_digest: result.checkpoint.unitClosureDigest
|
|
776
|
+
} : {},
|
|
714
777
|
goal_ref: result.checkpoint.goalRef ?? null
|
|
715
778
|
} } : {}
|
|
716
779
|
});
|
|
@@ -849,59 +912,234 @@ function createBoundaryTool(getProjection, prepare, onRejected) {
|
|
|
849
912
|
}
|
|
850
913
|
|
|
851
914
|
//#endregion
|
|
852
|
-
//#region src/tools/
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
915
|
+
//#region src/tools/action-preparation.ts
|
|
916
|
+
const GUARD_TOOL_STEPS = [
|
|
917
|
+
"Before execution: context_guard_evidence with evidence_role=resolution, selector and command_manifest. Keep the successful tool call ID and target_digest.",
|
|
918
|
+
"Execute once with context_guard_action, semantic_action, resolution_call_id, target_digest, contract_item_id and contract_item_revision.",
|
|
919
|
+
"Collect effect and state separately with context_guard_evidence, using the same resolution_call_id and the successful action call ID as effect_call_id.",
|
|
920
|
+
"Checkpoint the matching resolution/effect/state evidence IDs. Call IDs identify tool events; evidence IDs identify checkpoint facts.",
|
|
921
|
+
"If the action already ran without resolution, report the historical evidence gap and read back state. Do not repeat a mutation to create missing prestate evidence."
|
|
922
|
+
];
|
|
923
|
+
const NATIVE_WRITE_STEPS = [
|
|
924
|
+
"Before execution: context_guard_evidence with evidence_role=resolution, selector and command_manifest. Keep the successful tool call ID and target_digest.",
|
|
925
|
+
"Execute the planned effect once with the native write/edit tool named by command_manifest.planned_tool and exactly the planned_arguments.",
|
|
926
|
+
"Collect effect and state separately with context_guard_evidence, using the same resolution_call_id and the successful write/edit call ID as effect_call_id.",
|
|
927
|
+
"Checkpoint the matching resolution/effect/state evidence IDs. Call IDs identify tool events; evidence IDs identify checkpoint facts.",
|
|
928
|
+
"If the action already ran without resolution, report the historical evidence gap and read back state. Do not repeat a mutation to create missing prestate evidence."
|
|
929
|
+
];
|
|
930
|
+
/**
|
|
931
|
+
* The unified descriptor for one stateful action. Git actions keep their
|
|
932
|
+
* historical selector/manifest/step shapes; the other six gain the same
|
|
933
|
+
* complete recipe instead of Git-only coverage.
|
|
934
|
+
*/
|
|
935
|
+
function actionPreparation(action) {
|
|
936
|
+
switch (action) {
|
|
937
|
+
case "install":
|
|
938
|
+
case "apply": return {
|
|
939
|
+
action,
|
|
940
|
+
selector_fields: ["package_id", "profile"],
|
|
941
|
+
optional_selector_fields: ["version"],
|
|
942
|
+
command_manifest_fields: ["manifest_id", "tgz_path"],
|
|
943
|
+
command_manifest_ids: [action === "install" ? "dsh.plugin_add_tgz.install.v1" : "dsh.plugin_add_tgz.apply.v1"],
|
|
944
|
+
planned_tools: ["context_guard_action"],
|
|
945
|
+
planned_argument_fields: [],
|
|
946
|
+
producer_fields: ["version", "integrity_digest"],
|
|
947
|
+
readback_fields: [
|
|
948
|
+
"package_id",
|
|
949
|
+
"version",
|
|
950
|
+
"integrity_digest",
|
|
951
|
+
"profile"
|
|
952
|
+
],
|
|
953
|
+
execution_surface: "context_guard_action",
|
|
954
|
+
steps: GUARD_TOOL_STEPS
|
|
955
|
+
};
|
|
956
|
+
case "create": return {
|
|
957
|
+
action,
|
|
958
|
+
selector_fields: ["artifact_id"],
|
|
959
|
+
optional_selector_fields: [],
|
|
960
|
+
command_manifest_fields: ["planned_tool", "planned_arguments"],
|
|
961
|
+
command_manifest_ids: ["artifact.create.v1"],
|
|
962
|
+
planned_tools: ["write", "write_file"],
|
|
963
|
+
planned_argument_fields: ["file_path", "content"],
|
|
964
|
+
producer_fields: [
|
|
965
|
+
"scope",
|
|
966
|
+
"pre_digest",
|
|
967
|
+
"change_set_digest"
|
|
968
|
+
],
|
|
969
|
+
readback_fields: ["post_digest"],
|
|
970
|
+
execution_surface: "native_write_edit",
|
|
971
|
+
steps: NATIVE_WRITE_STEPS
|
|
972
|
+
};
|
|
973
|
+
case "modify": return {
|
|
974
|
+
action,
|
|
975
|
+
selector_fields: ["artifact_id"],
|
|
976
|
+
optional_selector_fields: [],
|
|
977
|
+
command_manifest_fields: ["planned_tool", "planned_arguments"],
|
|
978
|
+
command_manifest_ids: ["artifact.modify.v1"],
|
|
979
|
+
planned_tools: ["edit", "edit_file"],
|
|
980
|
+
planned_argument_fields: [
|
|
981
|
+
"file_path",
|
|
982
|
+
"old_string",
|
|
983
|
+
"new_string"
|
|
984
|
+
],
|
|
985
|
+
producer_fields: [
|
|
986
|
+
"scope",
|
|
987
|
+
"pre_digest",
|
|
988
|
+
"change_set_digest"
|
|
989
|
+
],
|
|
990
|
+
readback_fields: ["post_digest"],
|
|
991
|
+
execution_surface: "native_write_edit",
|
|
992
|
+
steps: NATIVE_WRITE_STEPS
|
|
993
|
+
};
|
|
994
|
+
case "restart": return {
|
|
995
|
+
action,
|
|
996
|
+
selector_fields: ["service_id"],
|
|
997
|
+
optional_selector_fields: [],
|
|
998
|
+
command_manifest_fields: ["manifest_id"],
|
|
999
|
+
command_manifest_ids: ["dshmarket.restart.v1"],
|
|
1000
|
+
planned_tools: ["context_guard_action"],
|
|
1001
|
+
planned_argument_fields: [],
|
|
1002
|
+
producer_fields: ["pre_generation"],
|
|
1003
|
+
readback_fields: ["new_generation", "health"],
|
|
1004
|
+
execution_surface: "context_guard_action",
|
|
1005
|
+
steps: GUARD_TOOL_STEPS
|
|
1006
|
+
};
|
|
1007
|
+
case "publish": return {
|
|
1008
|
+
action,
|
|
1009
|
+
selector_fields: [
|
|
1010
|
+
"artifact_id",
|
|
1011
|
+
"version",
|
|
1012
|
+
"registry"
|
|
1013
|
+
],
|
|
1014
|
+
optional_selector_fields: [],
|
|
1015
|
+
command_manifest_fields: ["manifest_id", "tgz_path"],
|
|
1016
|
+
command_manifest_ids: ["npm.publish_tgz.v1"],
|
|
1017
|
+
planned_tools: ["context_guard_action"],
|
|
1018
|
+
planned_argument_fields: [],
|
|
1019
|
+
producer_fields: ["integrity_digest"],
|
|
1020
|
+
readback_fields: [
|
|
1021
|
+
"artifact_id",
|
|
1022
|
+
"version",
|
|
1023
|
+
"registry",
|
|
1024
|
+
"integrity_digest"
|
|
1025
|
+
],
|
|
1026
|
+
execution_surface: "context_guard_action",
|
|
1027
|
+
steps: GUARD_TOOL_STEPS
|
|
1028
|
+
};
|
|
1029
|
+
case "commit": return {
|
|
1030
|
+
action,
|
|
1031
|
+
selector_fields: ["repository", "branch"],
|
|
1032
|
+
optional_selector_fields: [],
|
|
1033
|
+
command_manifest_fields: ["planned_tool", "planned_arguments"],
|
|
1034
|
+
command_manifest_ids: ["git.commit_index_tree.v2"],
|
|
1035
|
+
planned_tools: ["bash", "pwsh"],
|
|
1036
|
+
planned_argument_fields: ["command", "workdir"],
|
|
1037
|
+
producer_fields: ["pre_head_oid", "change_set_digest"],
|
|
1038
|
+
readback_fields: ["post_head_oid", "pre_head_oid"],
|
|
1039
|
+
execution_surface: "context_guard_action",
|
|
1040
|
+
steps: GUARD_TOOL_STEPS
|
|
1041
|
+
};
|
|
1042
|
+
case "push": return {
|
|
1043
|
+
action,
|
|
1044
|
+
selector_fields: [
|
|
1045
|
+
"repository",
|
|
1046
|
+
"remote",
|
|
1047
|
+
"refspec"
|
|
1048
|
+
],
|
|
1049
|
+
optional_selector_fields: [],
|
|
1050
|
+
command_manifest_fields: ["planned_tool", "planned_arguments"],
|
|
1051
|
+
command_manifest_ids: ["git.push_explicit_refs.v2"],
|
|
1052
|
+
planned_tools: ["bash", "pwsh"],
|
|
1053
|
+
planned_argument_fields: ["command", "workdir"],
|
|
1054
|
+
producer_fields: ["local_oid"],
|
|
1055
|
+
readback_fields: ["remote_oid"],
|
|
1056
|
+
execution_surface: "context_guard_action",
|
|
1057
|
+
steps: GUARD_TOOL_STEPS
|
|
1058
|
+
};
|
|
1059
|
+
case "pull": return {
|
|
1060
|
+
action,
|
|
1061
|
+
selector_fields: [
|
|
1062
|
+
"repository",
|
|
1063
|
+
"remote",
|
|
1064
|
+
"refspec"
|
|
1065
|
+
],
|
|
1066
|
+
optional_selector_fields: [],
|
|
1067
|
+
command_manifest_fields: ["planned_tool", "planned_arguments"],
|
|
1068
|
+
command_manifest_ids: ["git.pull_ff_only_explicit.v2"],
|
|
1069
|
+
planned_tools: ["bash", "pwsh"],
|
|
1070
|
+
planned_argument_fields: ["command", "workdir"],
|
|
1071
|
+
producer_fields: [
|
|
1072
|
+
"upstream_oid",
|
|
1073
|
+
"pre_head_oid",
|
|
1074
|
+
"pull_mode"
|
|
1075
|
+
],
|
|
1076
|
+
readback_fields: ["post_head_oid", "tracking_ref_oid"],
|
|
1077
|
+
execution_surface: "context_guard_action",
|
|
1078
|
+
steps: GUARD_TOOL_STEPS
|
|
1079
|
+
};
|
|
1080
|
+
case "fetch": return {
|
|
1081
|
+
action,
|
|
1082
|
+
selector_fields: [
|
|
1083
|
+
"repository",
|
|
1084
|
+
"remote",
|
|
1085
|
+
"refspec"
|
|
1086
|
+
],
|
|
1087
|
+
optional_selector_fields: [],
|
|
1088
|
+
command_manifest_fields: ["planned_tool", "planned_arguments"],
|
|
1089
|
+
command_manifest_ids: ["git.fetch_tracking_explicit.v2"],
|
|
1090
|
+
planned_tools: ["bash", "pwsh"],
|
|
1091
|
+
planned_argument_fields: ["command", "workdir"],
|
|
1092
|
+
producer_fields: ["upstream_oid", "pre_head_oid"],
|
|
1093
|
+
readback_fields: ["tracking_ref_oid", "post_head_oid"],
|
|
1094
|
+
execution_surface: "context_guard_action",
|
|
1095
|
+
steps: GUARD_TOOL_STEPS
|
|
1096
|
+
};
|
|
1097
|
+
}
|
|
878
1098
|
}
|
|
879
1099
|
|
|
880
1100
|
//#endregion
|
|
881
1101
|
//#region src/tools/prepare.ts
|
|
1102
|
+
/** Discovery pages stay bounded like checkpoint pages. */
|
|
1103
|
+
const DISCOVERY_ITEM_LIMIT = 8;
|
|
1104
|
+
const encodeCursor = (cursor) => Buffer.from(JSON.stringify(cursor), "utf8").toString("base64url");
|
|
882
1105
|
/**
|
|
883
|
-
*
|
|
1106
|
+
* The items discovery lists for the CURRENT work: under a v5 boundary that is
|
|
1107
|
+
* the current unit's closure plus its required descendants (the same scope a
|
|
1108
|
+
* v2 certificate answers for, prohibitions included because a standing
|
|
1109
|
+
* constraint is never finished work) plus every pre-v5 obligation, which keeps
|
|
1110
|
+
* their birth rules and must never be silently dropped. A legacy session lists
|
|
1111
|
+
* the whole session. Switched-away sibling units keep their own history and
|
|
1112
|
+
* are reached by item ID, not re-listed here (0.6.1, W060-03).
|
|
1113
|
+
*/
|
|
1114
|
+
function discoveryItemIds(p) {
|
|
1115
|
+
const pending = [...p.items.values()].filter((item) => item.status === "pending").sort((a, b) => a.revision - b.revision || a.id.localeCompare(b.id));
|
|
1116
|
+
if (p.boundaryProtocol !== 5) return pending.map((item) => item.id);
|
|
1117
|
+
const closureUnits = new Set([...p.currentUnitId !== void 0 ? [p.currentUnitId, ...unitDescendantIds(p, p.currentUnitId)] : []]);
|
|
1118
|
+
return pending.filter((item) => item.unitId === void 0 || item.unitId !== void 0 && closureUnits.has(item.unitId)).map((item) => item.id);
|
|
1119
|
+
}
|
|
1120
|
+
/**
|
|
1121
|
+
* Thin READ-ONLY preparation surface (v0.5/0.6): before any stateful action it
|
|
884
1122
|
* reports the supported command shape, the required resolution/effect/state
|
|
885
1123
|
* evidence order, existing reusable references, and the exact missing fields.
|
|
886
1124
|
* It never executes, installs, commits, pushes, restarts, or probes authority
|
|
887
1125
|
* through side effects, and it never upgrades a default into user authority.
|
|
1126
|
+
* Without an `item_id` it returns the bounded current-item discovery list, so
|
|
1127
|
+
* the first step of a session can find the right ID instead of guessing one.
|
|
888
1128
|
*/
|
|
889
1129
|
function createPrepareTool(options) {
|
|
890
1130
|
return defineTool({
|
|
891
1131
|
name: "context_guard_prepare",
|
|
892
|
-
description: "Read-only pre-action preparation: report the supported command shape, required
|
|
1132
|
+
description: "Read-only pre-action preparation: report the supported command shape, required evidence order, existing references, and exact missing target fields for one contract item. Omit item_id to list current open items with their IDs; a stateful change needs resolution/effect/state, a read-only verification needs one matching fact. Pagination follows page_cursor (bound to the contract revision) and semantic_action filters the listing. Performs no action and grants no authority.",
|
|
893
1133
|
parameters: {
|
|
894
|
-
item_id: {
|
|
895
|
-
type: "string",
|
|
896
|
-
required: true
|
|
897
|
-
},
|
|
1134
|
+
item_id: { type: "string" },
|
|
898
1135
|
item_revision: { type: "number" },
|
|
899
1136
|
semantic_action: { type: "string" },
|
|
900
1137
|
requested_target: {
|
|
901
1138
|
type: "object",
|
|
902
1139
|
additionalProperties: true
|
|
903
1140
|
},
|
|
904
|
-
planned_operation: { type: "string" }
|
|
1141
|
+
planned_operation: { type: "string" },
|
|
1142
|
+
page_cursor: { type: "string" }
|
|
905
1143
|
},
|
|
906
1144
|
output: {
|
|
907
1145
|
schema: {
|
|
@@ -915,11 +1153,83 @@ function createPrepareTool(options) {
|
|
|
915
1153
|
},
|
|
916
1154
|
async execute(rawArgs) {
|
|
917
1155
|
const args = rawArgs;
|
|
1156
|
+
if (options.refreshProjection) {
|
|
1157
|
+
let durable = false;
|
|
1158
|
+
try {
|
|
1159
|
+
durable = await options.refreshProjection() === true;
|
|
1160
|
+
} catch {
|
|
1161
|
+
durable = false;
|
|
1162
|
+
}
|
|
1163
|
+
if (!durable) return {
|
|
1164
|
+
status: "unknown",
|
|
1165
|
+
reason_code: "projection_durability_unavailable"
|
|
1166
|
+
};
|
|
1167
|
+
}
|
|
918
1168
|
const p = options.getProjection();
|
|
919
1169
|
if (!p || !p.enabled || p.integrity !== "valid") return {
|
|
920
1170
|
status: "unknown",
|
|
921
1171
|
reason_code: "guard_unavailable"
|
|
922
1172
|
};
|
|
1173
|
+
if (args.item_id === void 0) {
|
|
1174
|
+
const filter = args.semantic_action ?? null;
|
|
1175
|
+
const invalidCursor = (reason_code, note) => ({
|
|
1176
|
+
status: "rejected",
|
|
1177
|
+
reason_code,
|
|
1178
|
+
mode: "discovery",
|
|
1179
|
+
contract_revision: p.contractRevision,
|
|
1180
|
+
...note !== void 0 ? { note } : { note: "Re-run discovery without page_cursor to list from the first page." }
|
|
1181
|
+
});
|
|
1182
|
+
let startAfter;
|
|
1183
|
+
if (args.page_cursor !== void 0) {
|
|
1184
|
+
let parsed;
|
|
1185
|
+
try {
|
|
1186
|
+
if (args.page_cursor.length <= 1024) {
|
|
1187
|
+
const value = JSON.parse(Buffer.from(args.page_cursor, "base64url").toString("utf8"));
|
|
1188
|
+
if (value?.v === 1 && Number.isSafeInteger(value.r) && (value.f === null || typeof value.f === "string") && Array.isArray(value.k) && Number.isSafeInteger(value.k[0]) && typeof value.k[1] === "string") parsed = value;
|
|
1189
|
+
}
|
|
1190
|
+
} catch {
|
|
1191
|
+
parsed = void 0;
|
|
1192
|
+
}
|
|
1193
|
+
if (!parsed) return invalidCursor("discovery_cursor_malformed");
|
|
1194
|
+
if (parsed.r !== p.contractRevision) return invalidCursor("discovery_cursor_stale", `The contract changed (cursor revision ${parsed.r}, current ${p.contractRevision}). Re-run discovery without page_cursor; items are never skipped by a stale page.`);
|
|
1195
|
+
if ((parsed.f ?? null) !== (filter ?? null)) return invalidCursor("discovery_cursor_filter_mismatch");
|
|
1196
|
+
startAfter = parsed.k;
|
|
1197
|
+
}
|
|
1198
|
+
const eligible = discoveryItemIds(p).map((id) => p.items.get(id)).filter((item$1) => filter === null || (item$1.semanticAction ?? "generic_run") === filter);
|
|
1199
|
+
const startIndex = startAfter === void 0 ? 0 : eligible.findIndex((item$1) => item$1.revision === startAfter[0] && item$1.id === startAfter[1]) + 1;
|
|
1200
|
+
if (startAfter !== void 0 && startIndex <= 0) return invalidCursor("discovery_cursor_stale", "The cursor names an item no longer in the current listing. Re-run discovery without page_cursor.");
|
|
1201
|
+
const page = eligible.slice(startIndex, startIndex + DISCOVERY_ITEM_LIMIT);
|
|
1202
|
+
const hasMore = startIndex + page.length < eligible.length;
|
|
1203
|
+
return {
|
|
1204
|
+
status: "prepared",
|
|
1205
|
+
mode: "discovery",
|
|
1206
|
+
durability: p.durabilityWatermark,
|
|
1207
|
+
contract_revision: p.contractRevision,
|
|
1208
|
+
total_open: eligible.length,
|
|
1209
|
+
listed: page.length,
|
|
1210
|
+
has_more: hasMore,
|
|
1211
|
+
items: page.map((item$1) => {
|
|
1212
|
+
const diagnosis$1 = deriveItemDiagnosis(p, item$1);
|
|
1213
|
+
return {
|
|
1214
|
+
id: item$1.id,
|
|
1215
|
+
revision: item$1.revision,
|
|
1216
|
+
kind: item$1.kind,
|
|
1217
|
+
...item$1.taskKind !== void 0 ? { task_kind: item$1.taskKind } : {},
|
|
1218
|
+
semantic_action: item$1.semanticAction ?? "generic_run",
|
|
1219
|
+
reason_code: diagnosis$1.reason_code,
|
|
1220
|
+
text: item$1.normalizedText
|
|
1221
|
+
};
|
|
1222
|
+
}),
|
|
1223
|
+
...hasMore ? { next_cursor: encodeCursor({
|
|
1224
|
+
v: 1,
|
|
1225
|
+
r: p.contractRevision,
|
|
1226
|
+
f: filter,
|
|
1227
|
+
k: [page[page.length - 1].revision, page[page.length - 1].id]
|
|
1228
|
+
}) } : {},
|
|
1229
|
+
...filter !== null ? { filtered_by: { semantic_action: filter } } : {},
|
|
1230
|
+
note: "Re-run with one item_id to prepare that item, or pass page_cursor for the next page. Preparation performs no action."
|
|
1231
|
+
};
|
|
1232
|
+
}
|
|
923
1233
|
const item = p.items.get(args.item_id ?? "");
|
|
924
1234
|
if (!item) return {
|
|
925
1235
|
status: "rejected",
|
|
@@ -944,13 +1254,13 @@ function createPrepareTool(options) {
|
|
|
944
1254
|
resolved_target: evidence.resolvedTarget,
|
|
945
1255
|
tool_result_seq: evidence.toolResultSeq
|
|
946
1256
|
}));
|
|
947
|
-
const requiredOrder =
|
|
1257
|
+
const requiredOrder = plannedAction && isStatefulAction(plannedAction) ? [
|
|
948
1258
|
"resolution (prestate facts from a trusted read)",
|
|
949
1259
|
"effect (the exact planned change)",
|
|
950
1260
|
"state (independent post-state readback)"
|
|
951
|
-
] : ["
|
|
952
|
-
const recipe = plannedAction ?
|
|
953
|
-
const missingTargetFields =
|
|
1261
|
+
] : ["effect (one matching durable verification fact)"];
|
|
1262
|
+
const recipe = plannedAction && isStatefulAction(plannedAction) ? actionPreparation(plannedAction) : void 0;
|
|
1263
|
+
const missingTargetFields = recipe ? recipe.selector_fields.filter((key) => !(item.requestedTarget?.[key] !== void 0 || args.requested_target?.[key] !== void 0)) : [];
|
|
954
1264
|
const capability = plannedAction && options.hostCapability ? options.hostCapability(plannedAction) : void 0;
|
|
955
1265
|
const commandShape = options.commandTemplate && plannedAction ? options.commandTemplate(plannedAction) : void 0;
|
|
956
1266
|
return {
|
|
@@ -969,13 +1279,163 @@ function createPrepareTool(options) {
|
|
|
969
1279
|
status: capability.status,
|
|
970
1280
|
...capability.reasonCode !== void 0 ? { reason_code: capability.reasonCode } : {}
|
|
971
1281
|
} } : {},
|
|
972
|
-
...recipe ? { evidence_input_contract:
|
|
1282
|
+
...recipe ? { evidence_input_contract: {
|
|
1283
|
+
selector_fields: recipe.selector_fields,
|
|
1284
|
+
optional_selector_fields: recipe.optional_selector_fields,
|
|
1285
|
+
command_manifest_fields: recipe.command_manifest_fields,
|
|
1286
|
+
command_manifest_ids: recipe.command_manifest_ids,
|
|
1287
|
+
planned_tools: recipe.planned_tools,
|
|
1288
|
+
planned_argument_fields: recipe.planned_argument_fields,
|
|
1289
|
+
producer_fields: recipe.producer_fields,
|
|
1290
|
+
readback_fields: recipe.readback_fields,
|
|
1291
|
+
execution_surface: recipe.execution_surface,
|
|
1292
|
+
steps: recipe.steps
|
|
1293
|
+
} } : {},
|
|
973
1294
|
note: "Preparation performs no action. A default or guessed target is not user authority; explicit root instruction is required for missing target fields."
|
|
974
1295
|
};
|
|
975
1296
|
}
|
|
976
1297
|
});
|
|
977
1298
|
}
|
|
978
1299
|
|
|
1300
|
+
//#endregion
|
|
1301
|
+
//#region src/tools/interpret.ts
|
|
1302
|
+
function parsePartition(args, extent) {
|
|
1303
|
+
const read = (key) => {
|
|
1304
|
+
const raw = args[key];
|
|
1305
|
+
if (raw === void 0) return void 0;
|
|
1306
|
+
if (!Array.isArray(raw)) return void 0;
|
|
1307
|
+
const spans = [];
|
|
1308
|
+
for (const entry of raw) {
|
|
1309
|
+
const record$1 = entry;
|
|
1310
|
+
const start = record$1?.start;
|
|
1311
|
+
const end = record$1?.end;
|
|
1312
|
+
if (typeof start !== "number" || !Number.isSafeInteger(start) || typeof end !== "number" || !Number.isSafeInteger(end) || start >= end) return void 0;
|
|
1313
|
+
spans.push({
|
|
1314
|
+
start,
|
|
1315
|
+
end
|
|
1316
|
+
});
|
|
1317
|
+
}
|
|
1318
|
+
return spans;
|
|
1319
|
+
};
|
|
1320
|
+
const information = read("information_spans");
|
|
1321
|
+
const unknown = read("unknown_spans");
|
|
1322
|
+
if (information === void 0 || unknown === void 0) return { error: "interpretation_partition_required" };
|
|
1323
|
+
if (information.length === 0) return { error: "interpretation_partition_required" };
|
|
1324
|
+
const all = [...information, ...unknown];
|
|
1325
|
+
for (const span of all) if (span.start < extent.start || span.end > extent.end) return { error: "interpretation_span_outside_input" };
|
|
1326
|
+
const ordered = [...all].sort((left, right) => left.start - right.start || left.end - right.end);
|
|
1327
|
+
for (let index = 1; index < ordered.length; index += 1) if (ordered[index].start < ordered[index - 1].end) return { error: "interpretation_spans_overlap" };
|
|
1328
|
+
return {
|
|
1329
|
+
information,
|
|
1330
|
+
unknown
|
|
1331
|
+
};
|
|
1332
|
+
}
|
|
1333
|
+
/** The byte extent that covers every source span of one item. */
|
|
1334
|
+
function itemExtent(spans) {
|
|
1335
|
+
return {
|
|
1336
|
+
start: Math.min(...spans.map((span) => span.start)),
|
|
1337
|
+
end: Math.max(...spans.map((span) => span.end))
|
|
1338
|
+
};
|
|
1339
|
+
}
|
|
1340
|
+
function createInterpretTool(options) {
|
|
1341
|
+
return defineTool({
|
|
1342
|
+
name: "context_guard_interpret",
|
|
1343
|
+
description: "Record the interpretation of one unresolved obligation: pass the item ID from context_guard_prepare plus the partition of its input spans you read as information (information_spans) and the sub-spans you could not resolve (unknown_spans); for an attached asset, the partition is unnecessary. Contract bookkeeping only — performs no action, grants no authority. Information sub-spans close when this turn's host-confirmed final answer is delivered; unknown sub-spans remain pending obligations. Correctness is never certified.",
|
|
1344
|
+
parameters: {
|
|
1345
|
+
item_id: {
|
|
1346
|
+
type: "string",
|
|
1347
|
+
required: true
|
|
1348
|
+
},
|
|
1349
|
+
information_spans: {
|
|
1350
|
+
type: "array",
|
|
1351
|
+
items: {
|
|
1352
|
+
type: "object",
|
|
1353
|
+
additionalProperties: true
|
|
1354
|
+
}
|
|
1355
|
+
},
|
|
1356
|
+
unknown_spans: {
|
|
1357
|
+
type: "array",
|
|
1358
|
+
items: {
|
|
1359
|
+
type: "object",
|
|
1360
|
+
additionalProperties: true
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
},
|
|
1364
|
+
output: {
|
|
1365
|
+
schema: {
|
|
1366
|
+
type: "object",
|
|
1367
|
+
additionalProperties: true
|
|
1368
|
+
},
|
|
1369
|
+
render: (_args, value) => [{
|
|
1370
|
+
type: "text",
|
|
1371
|
+
text: JSON.stringify(value)
|
|
1372
|
+
}]
|
|
1373
|
+
},
|
|
1374
|
+
async execute(rawArgs) {
|
|
1375
|
+
const args = rawArgs;
|
|
1376
|
+
const reject = (reason_code) => ({
|
|
1377
|
+
status: "rejected",
|
|
1378
|
+
reason_code
|
|
1379
|
+
});
|
|
1380
|
+
if (options.refreshProjection) {
|
|
1381
|
+
let durable = false;
|
|
1382
|
+
try {
|
|
1383
|
+
durable = await options.refreshProjection() === true;
|
|
1384
|
+
} catch {
|
|
1385
|
+
durable = false;
|
|
1386
|
+
}
|
|
1387
|
+
if (!durable) return {
|
|
1388
|
+
status: "unknown",
|
|
1389
|
+
reason_code: "projection_durability_unavailable"
|
|
1390
|
+
};
|
|
1391
|
+
}
|
|
1392
|
+
const p = options.getProjection();
|
|
1393
|
+
if (!p || !p.enabled || p.integrity !== "valid") return reject("guard_unavailable");
|
|
1394
|
+
const itemId = typeof args.item_id === "string" ? args.item_id.trim() : "";
|
|
1395
|
+
if (!itemId) return reject("item_not_found");
|
|
1396
|
+
const item = p.items.get(itemId);
|
|
1397
|
+
if (!item) return reject("item_not_found");
|
|
1398
|
+
if (item.status !== "pending") return reject("item_not_pending");
|
|
1399
|
+
if (!item.asset && item.authorityDisposition !== "unresolved") return reject("not_interpretable");
|
|
1400
|
+
if (item.asset) return {
|
|
1401
|
+
status: "recorded",
|
|
1402
|
+
item_id: item.id,
|
|
1403
|
+
item_revision: item.revision,
|
|
1404
|
+
kind: "asset",
|
|
1405
|
+
asset: {
|
|
1406
|
+
message_seq: item.asset.messageSeq,
|
|
1407
|
+
part_index: item.asset.partIndex,
|
|
1408
|
+
media_sha256: item.asset.mediaSha256
|
|
1409
|
+
},
|
|
1410
|
+
note: "Interpretation recorded for this asset obligation. It closes when the host-confirmed final answer of this interpreting turn is delivered; this record never certifies the interpretation's correctness and never authorizes or proves any execution."
|
|
1411
|
+
};
|
|
1412
|
+
if (!item.spans || item.spans.length === 0) return reject("item_spans_unavailable");
|
|
1413
|
+
const partition = parsePartition(args, itemExtent(item.spans));
|
|
1414
|
+
if ("error" in partition) return reject(partition.error);
|
|
1415
|
+
return {
|
|
1416
|
+
status: "recorded",
|
|
1417
|
+
item_id: item.id,
|
|
1418
|
+
item_revision: item.revision,
|
|
1419
|
+
kind: "clause",
|
|
1420
|
+
spans: item.spans.map((span) => ({
|
|
1421
|
+
part_index: span.partIndex,
|
|
1422
|
+
start: span.start,
|
|
1423
|
+
end: span.end
|
|
1424
|
+
})),
|
|
1425
|
+
information_spans: partition.information.map((span) => ({
|
|
1426
|
+
start: span.start,
|
|
1427
|
+
end: span.end
|
|
1428
|
+
})),
|
|
1429
|
+
unknown_spans: partition.unknown.map((span) => ({
|
|
1430
|
+
start: span.start,
|
|
1431
|
+
end: span.end
|
|
1432
|
+
})),
|
|
1433
|
+
note: "Interpretation partition recorded for this unresolved clause: information sub-spans close when the host-confirmed final answer of this interpreting turn is delivered; every unknown sub-span remains a pending obligation and must still be resolved or performed. This record never certifies correctness and never authorizes any execution."
|
|
1434
|
+
};
|
|
1435
|
+
}
|
|
1436
|
+
});
|
|
1437
|
+
}
|
|
1438
|
+
|
|
979
1439
|
//#endregion
|
|
980
1440
|
//#region src/tools/evidence.ts
|
|
981
1441
|
const execFileAsync = promisify(execFile);
|
|
@@ -1315,12 +1775,63 @@ async function tgzIdentity(path) {
|
|
|
1315
1775
|
offset = bodyStart + Math.ceil(size$1 / 512) * 512;
|
|
1316
1776
|
}
|
|
1317
1777
|
if (typeof manifest?.name !== "string" || typeof manifest.version !== "string") return void 0;
|
|
1778
|
+
const gitHead = typeof manifest.gitHead === "string" && /^[0-9a-f]{40}$/.test(manifest.gitHead) ? manifest.gitHead : void 0;
|
|
1779
|
+
const repositoryField = manifest.repository;
|
|
1780
|
+
const repository = typeof repositoryField === "string" ? repositoryField : record(repositoryField) && typeof record(repositoryField)?.url === "string" ? String(record(repositoryField).url) : void 0;
|
|
1318
1781
|
return {
|
|
1319
1782
|
name: manifest.name,
|
|
1320
1783
|
version: manifest.version,
|
|
1321
|
-
integrity: `sha512-${createHash("sha512").update(bytes).digest("base64")}
|
|
1784
|
+
integrity: `sha512-${createHash("sha512").update(bytes).digest("base64")}`,
|
|
1785
|
+
sha256: createHash("sha256").update(bytes).digest("hex"),
|
|
1786
|
+
...gitHead ? { gitHead } : {},
|
|
1787
|
+
...repository ? { repository } : {}
|
|
1788
|
+
};
|
|
1789
|
+
}
|
|
1790
|
+
/**
|
|
1791
|
+
* Read the candidate identity of a publish from TRUSTED PRODUCERS only: the
|
|
1792
|
+
* exact tgz bytes (SHA-256 and npm SRI), the manifest the packer embedded
|
|
1793
|
+
* (package name, version, gitHead, repository) and, when the contract names a
|
|
1794
|
+
* ref, the local repository's own answer for that ref. Nothing here comes from
|
|
1795
|
+
* a model argument, so a caller cannot assert an identity the artifact does
|
|
1796
|
+
* not have.
|
|
1797
|
+
*/
|
|
1798
|
+
async function observePublishCandidate(resolution, roots, signal, cwd) {
|
|
1799
|
+
const tgzPath = requireString(resolution.commandManifest, "tgz_path");
|
|
1800
|
+
if (!tgzPath) return void 0;
|
|
1801
|
+
const identity = await tgzIdentity(tgzPath);
|
|
1802
|
+
if (!identity) return void 0;
|
|
1803
|
+
const registry = typeof resolution.target.registry === "string" ? resolution.target.registry : void 0;
|
|
1804
|
+
return {
|
|
1805
|
+
packageId: identity.name,
|
|
1806
|
+
version: identity.version,
|
|
1807
|
+
artifactSha256: identity.sha256,
|
|
1808
|
+
artifactSri: identity.integrity,
|
|
1809
|
+
...identity.gitHead ? { fullSha40: identity.gitHead } : {},
|
|
1810
|
+
...identity.repository ? { repository: identity.repository } : {},
|
|
1811
|
+
...registry ? { registry } : {}
|
|
1322
1812
|
};
|
|
1323
1813
|
}
|
|
1814
|
+
/**
|
|
1815
|
+
* Resolve one ref to its commit with the audited git executable. Exported so
|
|
1816
|
+
* the runtime can resolve the ref an ADOPTED CONTRACT names, which is the only
|
|
1817
|
+
* closed, reachable path for that identity: the action tool's manifest schema
|
|
1818
|
+
* has no field for it, and a model-supplied ref would not be authority.
|
|
1819
|
+
*/
|
|
1820
|
+
async function resolveAuditedRef(cwd, ref, roots, signal) {
|
|
1821
|
+
if (!cwd || !/^refs\/[A-Za-z0-9._/-]+$/.test(ref)) return void 0;
|
|
1822
|
+
try {
|
|
1823
|
+
const identity = await (roots.readExecutableIdentity ?? executableIdentity)("git", signal);
|
|
1824
|
+
if (!identity || identity.executable !== "git") return void 0;
|
|
1825
|
+
const resolved = (await git(cwd, [
|
|
1826
|
+
"rev-parse",
|
|
1827
|
+
"--verify",
|
|
1828
|
+
`${ref}^{commit}`
|
|
1829
|
+
], signal, identity.realpath)).trim().toLowerCase();
|
|
1830
|
+
return /^[0-9a-f]{40}$/.test(resolved) ? resolved : void 0;
|
|
1831
|
+
} catch {
|
|
1832
|
+
return;
|
|
1833
|
+
}
|
|
1834
|
+
}
|
|
1324
1835
|
const MARKET_SCHEMA = "dsh-market/update-api/v1";
|
|
1325
1836
|
const MARKET_GENERATION_PREFIX = "dsh-market-instance/v1:";
|
|
1326
1837
|
async function marketCapabilities(roots, signal) {
|
|
@@ -1518,7 +2029,7 @@ async function executeGuardAction(action, resolution, roots, signal, executableI
|
|
|
1518
2029
|
if (action === "install" || action === "apply") {
|
|
1519
2030
|
const tgzPath = requireString(resolution.commandManifest, "tgz_path");
|
|
1520
2031
|
const identity = tgzPath ? await tgzIdentity(tgzPath) : void 0;
|
|
1521
|
-
if (!executableIdentity$1 || !tgzPath || !identity || identity.name !== target.package_id || identity.version !== target.version || identity.integrity !== target.integrity_digest || roots.profile?.name !== target.profile) return "unavailable";
|
|
2032
|
+
if (!executableIdentity$1 || !tgzPath || !identity || identity.name !== target.package_id || identity.version !== target.version || identity.integrity !== target.integrity_digest || roots.profile?.name !== target.profile) return { status: "unavailable" };
|
|
1522
2033
|
await runCommand(roots, executableIdentity$1, [
|
|
1523
2034
|
"plugin",
|
|
1524
2035
|
"--profile",
|
|
@@ -1526,13 +2037,13 @@ async function executeGuardAction(action, resolution, roots, signal, executableI
|
|
|
1526
2037
|
"add",
|
|
1527
2038
|
`file:${tgzPath}`
|
|
1528
2039
|
], void 0, signal);
|
|
1529
|
-
return "completed";
|
|
2040
|
+
return { status: "completed" };
|
|
1530
2041
|
}
|
|
1531
2042
|
if (action === "publish") {
|
|
1532
2043
|
const tgzPath = requireString(resolution.commandManifest, "tgz_path");
|
|
1533
2044
|
const identity = tgzPath ? await tgzIdentity(tgzPath) : void 0;
|
|
1534
2045
|
const registry = typeof target.registry === "string" ? canonicalRegistryBase(target.registry, { allowLoopbackHttp: roots.allowLoopbackHttpRegistry }) : void 0;
|
|
1535
|
-
if (!executableIdentity$1 || !tgzPath || !identity || identity.name !== target.artifact_id || identity.version !== target.version || identity.integrity !== target.integrity_digest || !registry || registry !== target.registry) return "unavailable";
|
|
2046
|
+
if (!executableIdentity$1 || !tgzPath || !identity || identity.name !== target.artifact_id || identity.version !== target.version || identity.integrity !== target.integrity_digest || !registry || registry !== target.registry) return { status: "unavailable" };
|
|
1536
2047
|
await runCommand(roots, executableIdentity$1, [
|
|
1537
2048
|
"publish",
|
|
1538
2049
|
tgzPath,
|
|
@@ -1540,19 +2051,19 @@ async function executeGuardAction(action, resolution, roots, signal, executableI
|
|
|
1540
2051
|
registry,
|
|
1541
2052
|
"--ignore-scripts"
|
|
1542
2053
|
], void 0, signal);
|
|
1543
|
-
return "completed";
|
|
2054
|
+
return { status: "completed" };
|
|
1544
2055
|
}
|
|
1545
2056
|
if (action === "restart") {
|
|
1546
2057
|
const capabilities = await marketCapabilities(roots, signal);
|
|
1547
|
-
if (!capabilities || !roots.marketOrigin || !resolutionCallId || !agent) return "unavailable";
|
|
1548
|
-
if (!sameMarketProvider(target.pre_generation, capabilities.generation)) return "unavailable";
|
|
1549
|
-
if (capabilities.generation !== target.pre_generation) return restartIntent(snapshotSessionEvents(agent.session), resolutionCallId, target) ? "completed" : "unavailable";
|
|
1550
|
-
if (restartIntent(snapshotSessionEvents(agent.session), resolutionCallId, target)) return "handoff_pending";
|
|
2058
|
+
if (!capabilities || !roots.marketOrigin || !resolutionCallId || !agent) return { status: "unavailable" };
|
|
2059
|
+
if (!sameMarketProvider(target.pre_generation, capabilities.generation)) return { status: "unavailable" };
|
|
2060
|
+
if (capabilities.generation !== target.pre_generation) return restartIntent(snapshotSessionEvents(agent.session), resolutionCallId, target) ? { status: "completed" } : { status: "unavailable" };
|
|
2061
|
+
if (restartIntent(snapshotSessionEvents(agent.session), resolutionCallId, target)) return { status: "handoff_pending" };
|
|
1551
2062
|
if (!roots.persistRestartIntent || !await roots.persistRestartIntent(agent, {
|
|
1552
2063
|
resolutionCallId,
|
|
1553
2064
|
serviceId: String(target.service_id),
|
|
1554
2065
|
preGeneration: String(target.pre_generation)
|
|
1555
|
-
})) return "unavailable";
|
|
2066
|
+
})) return { status: "unavailable" };
|
|
1556
2067
|
const response = await (roots.fetcher ?? fetch)(`${roots.marketOrigin}/dsh-market/api/v1/restart`, {
|
|
1557
2068
|
method: "POST",
|
|
1558
2069
|
signal,
|
|
@@ -1564,21 +2075,25 @@ async function executeGuardAction(action, resolution, roots, signal, executableI
|
|
|
1564
2075
|
},
|
|
1565
2076
|
body: "{}"
|
|
1566
2077
|
});
|
|
1567
|
-
if (!response.ok) return "unavailable";
|
|
1568
|
-
return record(await response.json())?.schema === MARKET_SCHEMA ? "handoff_pending" : "unavailable";
|
|
2078
|
+
if (!response.ok) return { status: "unavailable" };
|
|
2079
|
+
return record(await response.json())?.schema === MARKET_SCHEMA ? { status: "handoff_pending" } : { status: "unavailable" };
|
|
1569
2080
|
}
|
|
1570
2081
|
if (action === "commit" || action === "push" || action === "pull" || action === "fetch") {
|
|
1571
2082
|
const binding = resolution.gitBinding;
|
|
1572
2083
|
const repository = requireString(resolution.target, "repository");
|
|
1573
|
-
if (!executableIdentity$1 || !binding || !repository) return "unavailable";
|
|
2084
|
+
if (!executableIdentity$1 || !binding || !repository) return { status: "unavailable" };
|
|
1574
2085
|
const targetIdentity = {
|
|
1575
2086
|
repository,
|
|
1576
2087
|
...typeof resolution.target.remote === "string" ? { remote: resolution.target.remote } : {},
|
|
1577
2088
|
...typeof resolution.target.refspec === "string" ? { refspec: resolution.target.refspec } : {}
|
|
1578
2089
|
};
|
|
1579
2090
|
const current = await gitPrestate(binding.manifest, repository, signal, executableIdentity$1.realpath);
|
|
1580
|
-
if (!current) return "unavailable";
|
|
1581
|
-
|
|
2091
|
+
if (!current) return { status: "unavailable" };
|
|
2092
|
+
const executed = await executeRevalidatedGitEffect(binding.envelope, binding.manifest, targetIdentity, current, async (_file, argv, workingDirectory) => runCommand(roots, executableIdentity$1, argv, workingDirectory, signal));
|
|
2093
|
+
if (executed.status !== "executed") return {
|
|
2094
|
+
status: "unavailable",
|
|
2095
|
+
reasonCode: executed.reasonCode
|
|
2096
|
+
};
|
|
1582
2097
|
if (action === "commit") {
|
|
1583
2098
|
const commit = verifiedLinearCommitReadback(await gitBytes(repository, [
|
|
1584
2099
|
"rev-list",
|
|
@@ -1593,10 +2108,10 @@ async function executeGuardAction(action, resolution, roots, signal, executableI
|
|
|
1593
2108
|
"-z",
|
|
1594
2109
|
commit.postHeadOid
|
|
1595
2110
|
], signal, executableIdentity$1.realpath)) : void 0;
|
|
1596
|
-
if (!commit || postTree !== resolution.target.change_set_digest) return "unavailable";
|
|
2111
|
+
if (!commit || postTree !== resolution.target.change_set_digest) return { status: "unavailable" };
|
|
1597
2112
|
} else if (action === "push") {
|
|
1598
2113
|
const remoteOid = binding.manifest.remote && binding.manifest.destinationRef ? await exactRemoteOid(repository, binding.manifest.remote, binding.manifest.destinationRef, signal, executableIdentity$1.realpath) : void 0;
|
|
1599
|
-
if (!remoteOid || remoteOid !== resolution.target.local_oid) return "unavailable";
|
|
2114
|
+
if (!remoteOid || remoteOid !== resolution.target.local_oid) return { status: "unavailable" };
|
|
1600
2115
|
} else {
|
|
1601
2116
|
const upstream = String(resolution.target.upstream_oid ?? "");
|
|
1602
2117
|
const trackingRef = binding.manifest.action === "fetch" ? binding.manifest.trackingRef : binding.manifest.remote && binding.manifest.sourceRef ? `refs/remotes/${binding.manifest.remote}/${binding.manifest.sourceRef.slice(11)}` : void 0;
|
|
@@ -1605,13 +2120,13 @@ async function executeGuardAction(action, resolution, roots, signal, executableI
|
|
|
1605
2120
|
"--verify",
|
|
1606
2121
|
trackingRef
|
|
1607
2122
|
], signal, executableIdentity$1.realpath)) : void 0;
|
|
1608
|
-
if (!tracking || tracking !== upstream) return "unavailable";
|
|
1609
|
-
if (action === "pull" && oid(await git(repository, ["rev-parse", "HEAD"], signal, executableIdentity$1.realpath)) !== upstream) return "unavailable";
|
|
1610
|
-
if (action === "fetch" && oid(await git(repository, ["rev-parse", "HEAD"], signal, executableIdentity$1.realpath)) !== resolution.target.pre_head_oid) return "unavailable";
|
|
2123
|
+
if (!tracking || tracking !== upstream) return { status: "unavailable" };
|
|
2124
|
+
if (action === "pull" && oid(await git(repository, ["rev-parse", "HEAD"], signal, executableIdentity$1.realpath)) !== upstream) return { status: "unavailable" };
|
|
2125
|
+
if (action === "fetch" && oid(await git(repository, ["rev-parse", "HEAD"], signal, executableIdentity$1.realpath)) !== resolution.target.pre_head_oid) return { status: "unavailable" };
|
|
1611
2126
|
}
|
|
1612
|
-
return "completed";
|
|
2127
|
+
return { status: "completed" };
|
|
1613
2128
|
}
|
|
1614
|
-
return "unavailable";
|
|
2129
|
+
return { status: "unavailable" };
|
|
1615
2130
|
}
|
|
1616
2131
|
async function gitBytes(repository, args, signal, file = "git") {
|
|
1617
2132
|
const { stdout } = await execFileAsync(file, args, {
|
|
@@ -2050,7 +2565,9 @@ function normalizedRoots(options) {
|
|
|
2050
2565
|
...options.authorizeMutation ? { authorizeMutation: options.authorizeMutation } : {},
|
|
2051
2566
|
...options.prepareMutation ? { prepareMutation: options.prepareMutation } : {},
|
|
2052
2567
|
...options.readExecutableIdentity ? { readExecutableIdentity: options.readExecutableIdentity } : {},
|
|
2053
|
-
...options.allowLoopbackHttpRegistry ? { allowLoopbackHttpRegistry: true } : {}
|
|
2568
|
+
...options.allowLoopbackHttpRegistry ? { allowLoopbackHttpRegistry: true } : {},
|
|
2569
|
+
...options.releaseGate ? { releaseGate: options.releaseGate } : {},
|
|
2570
|
+
...options.releaseSettle ? { releaseSettle: options.releaseSettle } : {}
|
|
2054
2571
|
};
|
|
2055
2572
|
}
|
|
2056
2573
|
function createActionTool(options = {}) {
|
|
@@ -2219,14 +2736,70 @@ function createActionTool(options = {}) {
|
|
|
2219
2736
|
...identity
|
|
2220
2737
|
};
|
|
2221
2738
|
}
|
|
2739
|
+
const releaseOperation = action === "publish" ? "npm_publish" : void 0;
|
|
2740
|
+
let releaseGranted = false;
|
|
2741
|
+
let releaseContractId;
|
|
2742
|
+
if (releaseOperation && roots.releaseGate) {
|
|
2743
|
+
const observed = await observePublishCandidate(resolution, roots, exec.signal, cwdOf(agent));
|
|
2744
|
+
if (!observed) return {
|
|
2745
|
+
status: "unavailable",
|
|
2746
|
+
reason_code: "release_candidate_unobservable",
|
|
2747
|
+
...identity
|
|
2748
|
+
};
|
|
2749
|
+
let decision;
|
|
2750
|
+
try {
|
|
2751
|
+
decision = await roots.releaseGate({
|
|
2752
|
+
agent,
|
|
2753
|
+
operation: releaseOperation,
|
|
2754
|
+
callId: args.resolution_call_id,
|
|
2755
|
+
resolvedTarget: resolution.target,
|
|
2756
|
+
observed
|
|
2757
|
+
});
|
|
2758
|
+
} catch {
|
|
2759
|
+
decision = void 0;
|
|
2760
|
+
}
|
|
2761
|
+
if (decision === void 0) return {
|
|
2762
|
+
status: "unavailable",
|
|
2763
|
+
reason_code: "release_gate_unavailable",
|
|
2764
|
+
...identity
|
|
2765
|
+
};
|
|
2766
|
+
if (decision.status !== "granted") return {
|
|
2767
|
+
status: "unavailable",
|
|
2768
|
+
reason_code: decision.reasonCode,
|
|
2769
|
+
...identity
|
|
2770
|
+
};
|
|
2771
|
+
releaseGranted = true;
|
|
2772
|
+
releaseContractId = decision.contractId;
|
|
2773
|
+
}
|
|
2222
2774
|
try {
|
|
2223
|
-
const
|
|
2775
|
+
const outcome = await executeGuardAction(action, resolution, roots, exec.signal, currentExecutable, args.resolution_call_id, agent);
|
|
2776
|
+
if (releaseOperation && releaseGranted && roots.releaseSettle) {
|
|
2777
|
+
const readback$1 = outcome.status === "completed" ? await publishReadback(resolution.target, roots, exec.signal) : void 0;
|
|
2778
|
+
await roots.releaseSettle({
|
|
2779
|
+
agent,
|
|
2780
|
+
operation: releaseOperation,
|
|
2781
|
+
callId: args.resolution_call_id,
|
|
2782
|
+
...releaseContractId !== void 0 ? { contractId: releaseContractId } : {},
|
|
2783
|
+
effect: outcome.status === "completed" ? "completed" : outcome.status === "unavailable" ? "not_effected" : "unknown",
|
|
2784
|
+
readback: readback$1 === void 0 ? "unavailable" : {
|
|
2785
|
+
kind: "npm_integrity",
|
|
2786
|
+
identity: readback$1
|
|
2787
|
+
}
|
|
2788
|
+
});
|
|
2789
|
+
}
|
|
2224
2790
|
return {
|
|
2225
|
-
status,
|
|
2226
|
-
reason_code: status === "completed" ? "action_completed" : status === "handoff_pending" ? "restart_handoff_pending" : "action_execution_failed",
|
|
2791
|
+
status: outcome.status,
|
|
2792
|
+
reason_code: outcome.status === "completed" ? "action_completed" : outcome.status === "handoff_pending" ? "restart_handoff_pending" : outcome.reasonCode === "effect_already_applied" ? "action_already_applied" : "action_execution_failed",
|
|
2227
2793
|
...identity
|
|
2228
2794
|
};
|
|
2229
2795
|
} catch {
|
|
2796
|
+
if (releaseOperation && releaseGranted && roots.releaseSettle) await roots.releaseSettle({
|
|
2797
|
+
agent,
|
|
2798
|
+
operation: releaseOperation,
|
|
2799
|
+
callId: args.resolution_call_id,
|
|
2800
|
+
effect: "unknown",
|
|
2801
|
+
readback: "unavailable"
|
|
2802
|
+
});
|
|
2230
2803
|
return {
|
|
2231
2804
|
status: "unavailable",
|
|
2232
2805
|
reason_code: "action_execution_failed",
|
|
@@ -2236,6 +2809,23 @@ function createActionTool(options = {}) {
|
|
|
2236
2809
|
}
|
|
2237
2810
|
});
|
|
2238
2811
|
}
|
|
2812
|
+
/**
|
|
2813
|
+
* The trusted npm readback identity for a completed publish: the registry's
|
|
2814
|
+
* own `dist.integrity` for the exact package version. `undefined` means no
|
|
2815
|
+
* producer is reachable, which keeps the release attempt `unconfirmed` instead
|
|
2816
|
+
* of claiming a verified release.
|
|
2817
|
+
*/
|
|
2818
|
+
async function publishReadback(target, roots, signal) {
|
|
2819
|
+
const registry = typeof target.registry === "string" ? target.registry : void 0;
|
|
2820
|
+
const artifact = typeof target.artifact_id === "string" ? target.artifact_id : void 0;
|
|
2821
|
+
const version = typeof target.version === "string" ? target.version : void 0;
|
|
2822
|
+
if (!registry || !artifact || !version) return void 0;
|
|
2823
|
+
try {
|
|
2824
|
+
return await registryIntegrity(registry, artifact, version, roots, signal);
|
|
2825
|
+
} catch {
|
|
2826
|
+
return;
|
|
2827
|
+
}
|
|
2828
|
+
}
|
|
2239
2829
|
function createEvidenceTool(options = {}) {
|
|
2240
2830
|
const roots = normalizedRoots(options);
|
|
2241
2831
|
return defineTool({
|
|
@@ -2452,17 +3042,26 @@ function createEvidenceTool(options = {}) {
|
|
|
2452
3042
|
if (!agent) return unavailable(action, role, "producer_agent_unavailable");
|
|
2453
3043
|
try {
|
|
2454
3044
|
if (role === "resolution") {
|
|
2455
|
-
const recipe =
|
|
2456
|
-
|
|
3045
|
+
const recipe = actionPreparation(action);
|
|
3046
|
+
{
|
|
2457
3047
|
const manifest = record(args.command_manifest);
|
|
2458
3048
|
const plannedArgs = record(manifest?.planned_arguments);
|
|
2459
3049
|
const selector = record(args.selector);
|
|
3050
|
+
const needsManifestId = [
|
|
3051
|
+
"install",
|
|
3052
|
+
"apply",
|
|
3053
|
+
"publish",
|
|
3054
|
+
"restart"
|
|
3055
|
+
].includes(action);
|
|
3056
|
+
const needsPlannedEffect = !needsManifestId;
|
|
2460
3057
|
const missing = [
|
|
2461
3058
|
...recipe.selector_fields.filter((key) => !requireString(selector ?? {}, key)).map((key) => `selector.${key}`),
|
|
2462
|
-
|
|
2463
|
-
...recipe.
|
|
3059
|
+
...needsManifestId && !requireString(manifest ?? {}, "manifest_id") ? ["command_manifest.manifest_id"] : [],
|
|
3060
|
+
...needsManifestId && recipe.command_manifest_fields.includes("tgz_path") && !requireString(manifest ?? {}, "tgz_path") ? ["command_manifest.tgz_path"] : [],
|
|
3061
|
+
...needsPlannedEffect && !requireString(manifest ?? {}, "planned_tool") ? ["command_manifest.planned_tool"] : [],
|
|
3062
|
+
...needsPlannedEffect ? recipe.planned_argument_fields.filter((key) => !requireString(plannedArgs ?? {}, key)).map((key) => `command_manifest.planned_arguments.${key}`) : []
|
|
2464
3063
|
];
|
|
2465
|
-
if (missing.length) return unavailable(action, role, "resolution_input_missing", missing, "Supply the listed resolution inputs before execution. Use context_guard_prepare for the exact
|
|
3064
|
+
if (missing.length) return unavailable(action, role, "resolution_input_missing", missing, "Supply the listed resolution inputs before execution. Use context_guard_prepare for the exact input contract of this action. A manifest_id alone does not describe a planned tool call.");
|
|
2466
3065
|
}
|
|
2467
3066
|
const executable$1 = executableFor(action);
|
|
2468
3067
|
const executableBinding = executable$1 ? await (roots.readExecutableIdentity ?? executableIdentity)(executable$1, exec.signal) : void 0;
|
|
@@ -2514,6 +3113,135 @@ function createEvidenceTool(options = {}) {
|
|
|
2514
3113
|
});
|
|
2515
3114
|
}
|
|
2516
3115
|
|
|
3116
|
+
//#endregion
|
|
3117
|
+
//#region src/tools/release.ts
|
|
3118
|
+
const RELEASE_TOOL = "context_guard_release";
|
|
3119
|
+
function createReleaseTool(options) {
|
|
3120
|
+
return defineTool({
|
|
3121
|
+
name: RELEASE_TOOL,
|
|
3122
|
+
description: "Read the explicit release state, or reconcile a release attempt whose effect was unknown by reading back the external identity. This tool never re-sends a release.",
|
|
3123
|
+
parameters: {
|
|
3124
|
+
operation: {
|
|
3125
|
+
type: "string",
|
|
3126
|
+
required: true,
|
|
3127
|
+
enum: ["status", "reconcile"]
|
|
3128
|
+
},
|
|
3129
|
+
contract_id: { type: "string" },
|
|
3130
|
+
resolution_call_id: { type: "string" }
|
|
3131
|
+
},
|
|
3132
|
+
output: {
|
|
3133
|
+
schema: {
|
|
3134
|
+
type: "object",
|
|
3135
|
+
additionalProperties: true
|
|
3136
|
+
},
|
|
3137
|
+
render: (_args, value) => [{
|
|
3138
|
+
type: "text",
|
|
3139
|
+
text: JSON.stringify(value)
|
|
3140
|
+
}]
|
|
3141
|
+
},
|
|
3142
|
+
async execute(rawArgs, exec) {
|
|
3143
|
+
const args = rawArgs;
|
|
3144
|
+
const projection = options.getProjection();
|
|
3145
|
+
if (!projection) return {
|
|
3146
|
+
status: "unknown",
|
|
3147
|
+
reason_code: "guard_unavailable"
|
|
3148
|
+
};
|
|
3149
|
+
if (args.operation === "status") return {
|
|
3150
|
+
status: "available",
|
|
3151
|
+
policy: projection.policy,
|
|
3152
|
+
state_damaged: projection.releaseStateDamaged,
|
|
3153
|
+
coverage_surface: Object.keys(RELEASE_OPERATION_SURFACES).map((operation$1) => ({
|
|
3154
|
+
operation: operation$1,
|
|
3155
|
+
...RELEASE_OPERATION_SURFACES[operation$1]
|
|
3156
|
+
})),
|
|
3157
|
+
contracts: projection.releaseContracts.map((contract$1) => ({
|
|
3158
|
+
contract_id: contract$1.contractId,
|
|
3159
|
+
revoked_at_seq: contract$1.revokedAtSeq ?? null,
|
|
3160
|
+
adopted_at_revision: contract$1.adoptedAtRevision,
|
|
3161
|
+
operations: releaseCoverage(contract$1),
|
|
3162
|
+
candidate: contract$1.candidate
|
|
3163
|
+
})),
|
|
3164
|
+
reservations: projection.releaseReservations.map(({ contractId: contractId$1, operation: operation$1, callId: callId$1, startedAtSeq, observedArtifactSri }) => ({
|
|
3165
|
+
contract_id: contractId$1,
|
|
3166
|
+
operation: operation$1,
|
|
3167
|
+
resolution_call_id: callId$1,
|
|
3168
|
+
started_at_seq: startedAtSeq,
|
|
3169
|
+
observed_artifact_sri: observedArtifactSri ?? null,
|
|
3170
|
+
in_flight: inFlightReservation(projection, contractId$1, operation$1)?.callId === callId$1
|
|
3171
|
+
})),
|
|
3172
|
+
settlements: projection.releaseSettlements.map(({ contractId: contractId$1, operation: operation$1, callId: callId$1, outcome: outcome$1, readback: readback$2, settledAtSeq }) => ({
|
|
3173
|
+
contract_id: contractId$1,
|
|
3174
|
+
operation: operation$1,
|
|
3175
|
+
resolution_call_id: callId$1,
|
|
3176
|
+
outcome: outcome$1,
|
|
3177
|
+
readback: readback$2,
|
|
3178
|
+
settled_at_seq: settledAtSeq
|
|
3179
|
+
})),
|
|
3180
|
+
diagnostics: projection.releaseDiagnostics
|
|
3181
|
+
};
|
|
3182
|
+
if (args.operation !== "reconcile") return {
|
|
3183
|
+
status: "rejected",
|
|
3184
|
+
reason_code: "release_subcommand_unknown"
|
|
3185
|
+
};
|
|
3186
|
+
const contractId = args.contract_id ?? "";
|
|
3187
|
+
const callId = args.resolution_call_id ?? "";
|
|
3188
|
+
const contract = contractById(projection, contractId);
|
|
3189
|
+
if (!contract) return {
|
|
3190
|
+
status: "rejected",
|
|
3191
|
+
reason_code: "release_contract_unknown"
|
|
3192
|
+
};
|
|
3193
|
+
const reservation = reservationFor(projection, contractId, callId);
|
|
3194
|
+
if (!reservation) return {
|
|
3195
|
+
status: "rejected",
|
|
3196
|
+
reason_code: "release_reservation_unknown"
|
|
3197
|
+
};
|
|
3198
|
+
const operation = reservation.operation;
|
|
3199
|
+
const settled = projection.releaseSettlements.find((entry) => entry.contractId === contractId && entry.operation === operation && entry.callId === callId && (entry.outcome === "settled" || entry.outcome === "not_effected"));
|
|
3200
|
+
if (settled) return {
|
|
3201
|
+
status: "already_resolved",
|
|
3202
|
+
outcome: settled.outcome,
|
|
3203
|
+
reason_code: "release_already_resolved"
|
|
3204
|
+
};
|
|
3205
|
+
const registry = contract.candidate.registry;
|
|
3206
|
+
const packageId = contract.candidate.packageId;
|
|
3207
|
+
const version = contract.candidate.version;
|
|
3208
|
+
if (!registry || !packageId || !version) return {
|
|
3209
|
+
status: "unavailable",
|
|
3210
|
+
reason_code: "release_readback_identity_incomplete"
|
|
3211
|
+
};
|
|
3212
|
+
const identity = await registryIntegrity(registry, packageId, version, options, exec.signal);
|
|
3213
|
+
if (!identity) return {
|
|
3214
|
+
status: "unavailable",
|
|
3215
|
+
reason_code: "release_readback_unavailable"
|
|
3216
|
+
};
|
|
3217
|
+
const readback$1 = {
|
|
3218
|
+
kind: "npm_integrity",
|
|
3219
|
+
identity
|
|
3220
|
+
};
|
|
3221
|
+
const verdict = readbackSettlesContract(contract, readback$1, reservation.observedArtifactSri);
|
|
3222
|
+
const outcome = verdict === "settled" ? "settled" : "unknown";
|
|
3223
|
+
if (!await options.persistSettlement({
|
|
3224
|
+
agent: exec.agent,
|
|
3225
|
+
contractId,
|
|
3226
|
+
operation,
|
|
3227
|
+
callId,
|
|
3228
|
+
readback: readback$1,
|
|
3229
|
+
outcome
|
|
3230
|
+
})) return {
|
|
3231
|
+
status: "unknown",
|
|
3232
|
+
reason_code: "release_settlement_not_durable"
|
|
3233
|
+
};
|
|
3234
|
+
return {
|
|
3235
|
+
status: verdict === "settled" ? "settled" : verdict === "mismatch" ? "mismatch" : "unconfirmed",
|
|
3236
|
+
outcome,
|
|
3237
|
+
readback: readback$1,
|
|
3238
|
+
reason_code: verdict === "settled" ? "release_reconciled" : verdict === "mismatch" ? "release_readback_identity_mismatch" : "release_readback_identity_unavailable",
|
|
3239
|
+
note: "Reconciliation never re-sends the release operation."
|
|
3240
|
+
};
|
|
3241
|
+
}
|
|
3242
|
+
});
|
|
3243
|
+
}
|
|
3244
|
+
|
|
2517
3245
|
//#endregion
|
|
2518
3246
|
//#region src/tools/external-operation.ts
|
|
2519
3247
|
function createExternalOperationTool(read, capability) {
|
|
@@ -2589,17 +3317,168 @@ function createExternalOperationTool(read, capability) {
|
|
|
2589
3317
|
});
|
|
2590
3318
|
}
|
|
2591
3319
|
|
|
3320
|
+
//#endregion
|
|
3321
|
+
//#region src/domain/migration.ts
|
|
3322
|
+
/** The frozen digest domains: a migration never rewrites any of them. */
|
|
3323
|
+
const PRESERVED_DIGEST_DOMAINS = [
|
|
3324
|
+
"ccg.sessionRefDigest.v3",
|
|
3325
|
+
"ccg.hostLockDigest.v3",
|
|
3326
|
+
"ccg.evidenceFact.v3",
|
|
3327
|
+
"ccg.evidenceSha256.v3",
|
|
3328
|
+
"ccg.predParams.v3",
|
|
3329
|
+
"ccg.binding.v3",
|
|
3330
|
+
"ccg.bindingDigest.v3",
|
|
3331
|
+
"ccg.certificationDigest.v3",
|
|
3332
|
+
"ccg.locator.v1",
|
|
3333
|
+
"ccg.proofManifest.v1"
|
|
3334
|
+
];
|
|
3335
|
+
function migrationReport(projection) {
|
|
3336
|
+
const v5 = projection.boundaryProtocol === 5;
|
|
3337
|
+
const legacyItemIds = certifiableOpenItems(projection).filter((item) => item.unitId === void 0).map((item) => item.id);
|
|
3338
|
+
const closure = v5 ? certificateClosure(projection) : { itemIds: [] };
|
|
3339
|
+
const reasonCodes = [];
|
|
3340
|
+
if (!v5) reasonCodes.push("legacy_session_keeps_v4_contract");
|
|
3341
|
+
if (v5 && legacyItemIds.length > 0) reasonCodes.push("pre_v5_obligations_retained_in_closure");
|
|
3342
|
+
return {
|
|
3343
|
+
ruleMode: v5 ? "v5" : "legacy-v4",
|
|
3344
|
+
certificateVersion: v5 ? CERTIFICATE_VERSION_V2 : CERTIFICATE_VERSION,
|
|
3345
|
+
stopProtocolVersion: v5 ? STOP_PROTOCOL_VERSION_V2 : STOP_PROTOCOL_VERSION,
|
|
3346
|
+
unitClosure: v5,
|
|
3347
|
+
...v5 && projection.currentUnitId !== void 0 ? { currentUnitId: projection.currentUnitId } : {},
|
|
3348
|
+
legacyItemIds,
|
|
3349
|
+
unitClosureItemIds: [...closure.itemIds],
|
|
3350
|
+
preservedDigestDomains: [...PRESERVED_DIGEST_DOMAINS],
|
|
3351
|
+
historyOnlyCertificateVersions: v5 ? [CERTIFICATE_VERSION] : [],
|
|
3352
|
+
rollbackRequiresStateSnapshot: v5,
|
|
3353
|
+
rollbackInstruction: v5 ? "Restore the 0.5.x state snapshot before starting the older binary. Replaying a v5 log with 0.5.x fails closed with certificate_replay_mismatch; never migrate new-schema data down by hand." : "No rollback action is required for this session: it has not written a v5 boundary.",
|
|
3354
|
+
reasonCodes
|
|
3355
|
+
};
|
|
3356
|
+
}
|
|
3357
|
+
|
|
2592
3358
|
//#endregion
|
|
2593
3359
|
//#region src/commands/context-guard.ts
|
|
2594
3360
|
function pendingCount(projection) {
|
|
2595
3361
|
return [...projection.items.values()].filter((item) => item.status === "pending").length;
|
|
2596
3362
|
}
|
|
3363
|
+
/**
|
|
3364
|
+
* The release surface. Adoption is deliberately NOT performed here: the
|
|
3365
|
+
* derivation adopts a contract only from the durable root `command/run` for
|
|
3366
|
+
* `/context-guard release adopt <json>`, so the command handler's job is to
|
|
3367
|
+
* report the resulting state (and to explain what is not protectable), never
|
|
3368
|
+
* to grant authority itself.
|
|
3369
|
+
*/
|
|
3370
|
+
function releaseResponse(projection, rawInput) {
|
|
3371
|
+
const rest = rawInput.trim().slice(7).trim();
|
|
3372
|
+
const [verb] = rest.split(/\s+/, 1);
|
|
3373
|
+
if (verb === "adopt") {
|
|
3374
|
+
const payload = rest.slice(5).trim();
|
|
3375
|
+
let parsed;
|
|
3376
|
+
try {
|
|
3377
|
+
parsed = JSON.parse(payload);
|
|
3378
|
+
} catch {
|
|
3379
|
+
return {
|
|
3380
|
+
kind: "error",
|
|
3381
|
+
text: "Context Guard release adopt: the contract must be one JSON object."
|
|
3382
|
+
};
|
|
3383
|
+
}
|
|
3384
|
+
const normalized = normalizeReleaseContract(parsed, {
|
|
3385
|
+
seq: -1,
|
|
3386
|
+
digest: ""
|
|
3387
|
+
});
|
|
3388
|
+
if (!normalized.contract) return {
|
|
3389
|
+
kind: "error",
|
|
3390
|
+
text: `Context Guard release adopt rejected: ${normalized.errors.join(", ")}`
|
|
3391
|
+
};
|
|
3392
|
+
const contract = normalized.contract;
|
|
3393
|
+
const adopted = projection.releaseContracts.some((entry) => entry.contractId === contract.contractId) ? projection.releaseContracts.find((entry) => entry.contractId === contract.contractId) : contract;
|
|
3394
|
+
return {
|
|
3395
|
+
kind: "success",
|
|
3396
|
+
text: JSON.stringify({
|
|
3397
|
+
status: "adopted",
|
|
3398
|
+
contract_id: adopted.contractId,
|
|
3399
|
+
candidate: adopted.candidate,
|
|
3400
|
+
operations: releaseCoverage(adopted),
|
|
3401
|
+
readiness_refs: adopted.readinessRefs,
|
|
3402
|
+
closure_cert_ref: adopted.closureCertRef ?? null,
|
|
3403
|
+
expires_at_epoch_ms: adopted.expiresAtEpochMs ?? null,
|
|
3404
|
+
note: "The contract becomes authoritative from the durable root command that carried it. It grants no authority in this process."
|
|
3405
|
+
})
|
|
3406
|
+
};
|
|
3407
|
+
}
|
|
3408
|
+
if (verb === "revoke") {
|
|
3409
|
+
const contractId = rest.slice(6).trim();
|
|
3410
|
+
if (!contractId) return {
|
|
3411
|
+
kind: "error",
|
|
3412
|
+
text: "Usage: /context-guard release revoke <contract_id>"
|
|
3413
|
+
};
|
|
3414
|
+
const contract = projection.releaseContracts.find((entry) => entry.contractId === contractId);
|
|
3415
|
+
if (!contract) return {
|
|
3416
|
+
kind: "error",
|
|
3417
|
+
text: `Context Guard release revoke: unknown contract ${contractId}`
|
|
3418
|
+
};
|
|
3419
|
+
return {
|
|
3420
|
+
kind: "success",
|
|
3421
|
+
text: JSON.stringify({
|
|
3422
|
+
status: contract.revokedAtSeq === void 0 ? "revoking" : "revoked",
|
|
3423
|
+
contract_id: contractId,
|
|
3424
|
+
revoked_at_seq: contract.revokedAtSeq ?? null,
|
|
3425
|
+
in_flight: projection.releaseReservations.filter((reservation) => reservation.contractId === contractId && !projection.releaseSettlements.some((settlement) => settlement.callId === reservation.callId && (settlement.outcome === "settled" || settlement.outcome === "not_effected"))).map(({ operation, callId }) => ({
|
|
3426
|
+
operation,
|
|
3427
|
+
call_id: callId
|
|
3428
|
+
})),
|
|
3429
|
+
note: "Revocation is recorded durably and keeps the audit trail. It denies the next effect; an operation already in flight still needs its trusted readback to be reconciled."
|
|
3430
|
+
})
|
|
3431
|
+
};
|
|
3432
|
+
}
|
|
3433
|
+
if (verb !== "" && verb !== "status") return {
|
|
3434
|
+
kind: "error",
|
|
3435
|
+
text: "Usage: /context-guard release status | release adopt <json contract> | release revoke <contract_id>. Adoption and revocation are recorded from this command itself; they never grant authority in-process."
|
|
3436
|
+
};
|
|
3437
|
+
const contracts = projection.releaseContracts.map((contract) => ({
|
|
3438
|
+
contract_id: contract.contractId,
|
|
3439
|
+
adopted_at_seq: contract.adoptedBy.seq,
|
|
3440
|
+
revoked_at_seq: contract.revokedAtSeq ?? null,
|
|
3441
|
+
candidate: contract.candidate,
|
|
3442
|
+
readiness_refs: contract.readinessRefs,
|
|
3443
|
+
closure_cert_ref: contract.closureCertRef ?? null,
|
|
3444
|
+
operations: releaseCoverage(contract),
|
|
3445
|
+
expires_at_epoch_ms: contract.expiresAtEpochMs ?? null,
|
|
3446
|
+
consumed_operations: projection.releaseSettlements.filter((settlement) => settlement.contractId === contract.contractId && settlement.outcome === "settled").map((settlement) => settlement.operation),
|
|
3447
|
+
in_flight: projection.releaseReservations.filter((reservation) => reservation.contractId === contract.contractId && !projection.releaseSettlements.some((settlement) => settlement.callId === reservation.callId && (settlement.outcome === "settled" || settlement.outcome === "not_effected"))).map(({ operation, callId, startedAtSeq }) => ({
|
|
3448
|
+
operation,
|
|
3449
|
+
call_id: callId,
|
|
3450
|
+
started_at_seq: startedAtSeq
|
|
3451
|
+
})),
|
|
3452
|
+
settlements: projection.releaseSettlements.filter((settlement) => settlement.contractId === contract.contractId).map(({ operation, callId, outcome, readback: readback$1, settledAtSeq }) => ({
|
|
3453
|
+
operation,
|
|
3454
|
+
call_id: callId,
|
|
3455
|
+
outcome,
|
|
3456
|
+
readback: readback$1,
|
|
3457
|
+
settled_at_seq: settledAtSeq
|
|
3458
|
+
}))
|
|
3459
|
+
}));
|
|
3460
|
+
return {
|
|
3461
|
+
kind: "success",
|
|
3462
|
+
text: JSON.stringify({
|
|
3463
|
+
profile_applicable: projection.policy === "release" || contracts.length > 0,
|
|
3464
|
+
policy: projection.policy,
|
|
3465
|
+
state_damaged: projection.releaseStateDamaged,
|
|
3466
|
+
adopted_contracts: contracts,
|
|
3467
|
+
coverage_surface: RELEASE_OPERATIONS.map((operation) => ({
|
|
3468
|
+
operation,
|
|
3469
|
+
...RELEASE_OPERATION_SURFACES[operation]
|
|
3470
|
+
})),
|
|
3471
|
+
diagnostics: projection.releaseDiagnostics,
|
|
3472
|
+
note: "A release is never implicit: only an explicit root adoption creates a contract, and only operations with a Guard execution surface can be protected."
|
|
3473
|
+
})
|
|
3474
|
+
};
|
|
3475
|
+
}
|
|
2597
3476
|
function createContextGuardCommand(projectionFor, setEnabled, clearContract, lifecycleFor) {
|
|
2598
3477
|
return {
|
|
2599
3478
|
name: "context-guard",
|
|
2600
|
-
description: "Enable, disable, clear, inspect, or
|
|
3479
|
+
description: "Enable, disable, clear, inspect, diagnose, or manage the explicit release contract for this session.",
|
|
2601
3480
|
recordInput: true,
|
|
2602
|
-
input: { hint: "on|off|clear|status|diagnose" },
|
|
3481
|
+
input: { hint: "on|off|clear|status|diagnose|migration|release status|release adopt <json>|release revoke <id>" },
|
|
2603
3482
|
handler: ({ agent, rawInput }) => {
|
|
2604
3483
|
const projection = projectionFor(agent);
|
|
2605
3484
|
const [subcommand] = rawInput.trim().split(/\s+/, 1);
|
|
@@ -2627,22 +3506,31 @@ function createContextGuardCommand(projectionFor, setEnabled, clearContract, lif
|
|
|
2627
3506
|
text: `Context Guard contract cleared: ${before - after} requirement/acceptance item(s) superseded; ${after} pending remain (prohibitions retained).`
|
|
2628
3507
|
};
|
|
2629
3508
|
}
|
|
3509
|
+
if (resolved === "release") return releaseResponse(projection, rawInput);
|
|
3510
|
+
if (resolved === "migration") return {
|
|
3511
|
+
kind: "success",
|
|
3512
|
+
text: JSON.stringify(migrationReport(projection))
|
|
3513
|
+
};
|
|
2630
3514
|
if (resolved !== "status" && resolved !== "diagnose") return {
|
|
2631
3515
|
kind: "error",
|
|
2632
|
-
text: "Usage: /context-guard on|off|clear|status|diagnose"
|
|
3516
|
+
text: "Usage: /context-guard on|off|clear|status|diagnose|migration|release status|release adopt <json>|release revoke <id>"
|
|
2633
3517
|
};
|
|
2634
3518
|
const passed = [...projection.items.values()].filter((item) => item.status === "passed").length;
|
|
2635
3519
|
let certifiable_missing_evidence = 0;
|
|
2636
3520
|
let unsupported = 0;
|
|
3521
|
+
const reason_classes = {};
|
|
2637
3522
|
for (const item of projection.items.values()) {
|
|
2638
3523
|
if (item.status !== "pending") continue;
|
|
2639
3524
|
const diagnosis = deriveItemDiagnosis(projection, item);
|
|
3525
|
+
reason_classes[diagnosis.reason_class] = (reason_classes[diagnosis.reason_class] ?? 0) + 1;
|
|
2640
3526
|
if (diagnosis.repairability === "agent_repairable") certifiable_missing_evidence += 1;
|
|
2641
3527
|
else if (diagnosis.certification === "unsupported") unsupported += 1;
|
|
2642
3528
|
}
|
|
3529
|
+
const migration = migrationReport(projection);
|
|
2643
3530
|
const response = {
|
|
2644
3531
|
enabled: projection.enabled,
|
|
2645
3532
|
lifecycle: lifecycleFor?.(agent) ?? (projection.enabled ? "active" : "disabled"),
|
|
3533
|
+
policy: projection.policy,
|
|
2646
3534
|
epoch: projection.epoch,
|
|
2647
3535
|
contract_revision: projection.contractRevision,
|
|
2648
3536
|
pending: pendingCount(projection),
|
|
@@ -2650,11 +3538,25 @@ function createContextGuardCommand(projectionFor, setEnabled, clearContract, lif
|
|
|
2650
3538
|
diagnosis: {
|
|
2651
3539
|
certified: passed,
|
|
2652
3540
|
certifiable_missing_evidence,
|
|
2653
|
-
unsupported
|
|
3541
|
+
unsupported,
|
|
3542
|
+
reason_classes
|
|
2654
3543
|
},
|
|
2655
3544
|
evidence: projection.evidence.size,
|
|
2656
3545
|
integrity: projection.integrity,
|
|
2657
|
-
last_source_seq: projection.lastObservedSourceSeq
|
|
3546
|
+
last_source_seq: projection.lastObservedSourceSeq,
|
|
3547
|
+
migration: {
|
|
3548
|
+
rule_mode: migration.ruleMode,
|
|
3549
|
+
certificate_version: migration.certificateVersion,
|
|
3550
|
+
unit_closure: migration.unitClosure,
|
|
3551
|
+
legacy_open_items: migration.legacyItemIds.length
|
|
3552
|
+
},
|
|
3553
|
+
release: {
|
|
3554
|
+
policy: projection.policy,
|
|
3555
|
+
state_damaged: projection.releaseStateDamaged,
|
|
3556
|
+
adopted_contracts: projection.releaseContracts.length,
|
|
3557
|
+
in_flight: projection.releaseReservations.filter((reservation) => !projection.releaseSettlements.some((settlement) => settlement.callId === reservation.callId && settlement.outcome === "settled")).length,
|
|
3558
|
+
applicable: projection.policy === "release" || projection.releaseContracts.length > 0
|
|
3559
|
+
}
|
|
2658
3560
|
};
|
|
2659
3561
|
return {
|
|
2660
3562
|
kind: "success",
|
|
@@ -3464,6 +4366,7 @@ defineMethod("transform", [
|
|
|
3464
4366
|
//#region src/config.ts
|
|
3465
4367
|
const Config = Schema.object({
|
|
3466
4368
|
activation: Schema.string().default("opt-in"),
|
|
4369
|
+
policy: Schema.string().default("standard"),
|
|
3467
4370
|
hostLockPlatform: Schema.string(),
|
|
3468
4371
|
hostLockProfile: Schema.string(),
|
|
3469
4372
|
hostLockPolicy: Schema.string(),
|
|
@@ -3478,6 +4381,8 @@ const Config = Schema.object({
|
|
|
3478
4381
|
function resolveConfig(config) {
|
|
3479
4382
|
const activation = config.activation ?? "opt-in";
|
|
3480
4383
|
if (activation !== "opt-in" && activation !== "always") throw new TypeError(`activation must be "opt-in" or "always", received ${JSON.stringify(activation)}`);
|
|
4384
|
+
const policy = config.policy ?? "standard";
|
|
4385
|
+
if (policy !== "standard" && policy !== "strict" && policy !== "release") throw new TypeError(`policy must be "standard", "strict", or "release", received ${JSON.stringify(policy)}`);
|
|
3481
4386
|
let hostLockPackages;
|
|
3482
4387
|
if (config.hostLockPackages !== void 0) {
|
|
3483
4388
|
if (!Array.isArray(config.hostLockPackages)) throw new TypeError("hostLockPackages must be an array");
|
|
@@ -3508,6 +4413,7 @@ function resolveConfig(config) {
|
|
|
3508
4413
|
...typeof config.hostLockRuntimeRoot === "string" ? { hostLockRuntimeRoot: config.hostLockRuntimeRoot } : {},
|
|
3509
4414
|
...typeof config.hostLockProfileRoot === "string" ? { hostLockProfileRoot: config.hostLockProfileRoot } : {},
|
|
3510
4415
|
activation,
|
|
4416
|
+
policy,
|
|
3511
4417
|
...hostLockPackages ? { hostLockPackages } : {},
|
|
3512
4418
|
...config.hostLockPlatform ? { hostLockPlatform: config.hostLockPlatform } : {},
|
|
3513
4419
|
...config.hostLockProfile ? { hostLockProfile: config.hostLockProfile } : {}
|
|
@@ -3584,7 +4490,12 @@ function authorizeMutationFromProjection(projection, request) {
|
|
|
3584
4490
|
status: "denied",
|
|
3585
4491
|
reasonCode: "mutation_target_clarification_required"
|
|
3586
4492
|
};
|
|
3587
|
-
|
|
4493
|
+
const boundedAuthorized = (scope) => requestedTargetAuthorizesMutation(request.action, {
|
|
4494
|
+
...item.requestedTarget,
|
|
4495
|
+
scope
|
|
4496
|
+
}, request.resolvedTarget);
|
|
4497
|
+
const selectionAuthorized = projection.trustedSelections.some((selection) => selection.kind === "directory" && typeof item.requestedTarget?.artifact_type === "string" && item.unitId !== void 0 && boundedAuthorized(selection.selected));
|
|
4498
|
+
if (!requestedTargetAuthorizesMutation(request.action, item.requestedTarget, request.resolvedTarget) && !selectionAuthorized) return {
|
|
3588
4499
|
status: "denied",
|
|
3589
4500
|
reasonCode: "mutation_requested_target_mismatch"
|
|
3590
4501
|
};
|
|
@@ -3860,10 +4771,12 @@ function createRuntime(agent, config, hostLock = DEFAULT_HOST_LOCK, readGoalStat
|
|
|
3860
4771
|
const session = agent.session;
|
|
3861
4772
|
let pendingRecovery = false;
|
|
3862
4773
|
let durabilityConfirmed = false;
|
|
4774
|
+
let durabilityWatermark = "unknown";
|
|
3863
4775
|
let observedEpoch = -1;
|
|
3864
4776
|
let observedCompactionSeq = -1;
|
|
3865
4777
|
let observedContractRevision = -1;
|
|
3866
4778
|
let protocolV4Present = false;
|
|
4779
|
+
let protocolV5Present = false;
|
|
3867
4780
|
let realRootInputSeen = false;
|
|
3868
4781
|
let lifecycle = "armed";
|
|
3869
4782
|
const continuationAttempts = projection.continuationAttempts;
|
|
@@ -3882,7 +4795,10 @@ function createRuntime(agent, config, hostLock = DEFAULT_HOST_LOCK, readGoalStat
|
|
|
3882
4795
|
if (!projection.integrityViolations.includes(code)) projection.integrityViolations.push(code);
|
|
3883
4796
|
return;
|
|
3884
4797
|
}
|
|
3885
|
-
const derived = deriveProjection(events, {
|
|
4798
|
+
const derived = deriveProjection(events, {
|
|
4799
|
+
activation: config.activation,
|
|
4800
|
+
policy: config.policy
|
|
4801
|
+
}, {
|
|
3886
4802
|
cwd: typeof header?.cwd === "string" ? header.cwd : "",
|
|
3887
4803
|
sessionHeader
|
|
3888
4804
|
}, durabilityConfirmed, hostLock);
|
|
@@ -3904,7 +4820,9 @@ function createRuntime(agent, config, hostLock = DEFAULT_HOST_LOCK, readGoalStat
|
|
|
3904
4820
|
projection.continuationAttempts = continuationAttempts;
|
|
3905
4821
|
projection.persistenceCorrectionAttempts = persistenceCorrectionAttempts;
|
|
3906
4822
|
projection.lastRecoveryDigest = priorRecoveryDigest;
|
|
4823
|
+
projection.durabilityWatermark = durabilityWatermark;
|
|
3907
4824
|
protocolV4Present = derived.protocolV4Present;
|
|
4825
|
+
protocolV5Present = derived.boundaryV5;
|
|
3908
4826
|
realRootInputSeen = derived.realRootInputSeen;
|
|
3909
4827
|
lifecycle = lifecyclePhase({
|
|
3910
4828
|
enabled: projection.enabled,
|
|
@@ -3931,6 +4849,8 @@ function createRuntime(agent, config, hostLock = DEFAULT_HOST_LOCK, readGoalStat
|
|
|
3931
4849
|
};
|
|
3932
4850
|
const setDurability = (confirmed) => {
|
|
3933
4851
|
durabilityConfirmed = confirmed;
|
|
4852
|
+
durabilityWatermark = confirmed ? "confirmed" : "failed";
|
|
4853
|
+
projection.durabilityWatermark = durabilityWatermark;
|
|
3934
4854
|
};
|
|
3935
4855
|
const markRecoveryNeeded = () => {
|
|
3936
4856
|
pendingRecovery = true;
|
|
@@ -3950,6 +4870,9 @@ function createRuntime(agent, config, hostLock = DEFAULT_HOST_LOCK, readGoalStat
|
|
|
3950
4870
|
get protocolV4Present() {
|
|
3951
4871
|
return protocolV4Present;
|
|
3952
4872
|
},
|
|
4873
|
+
get protocolV5Present() {
|
|
4874
|
+
return protocolV5Present;
|
|
4875
|
+
},
|
|
3953
4876
|
sync,
|
|
3954
4877
|
setEnabled,
|
|
3955
4878
|
setDurability,
|
|
@@ -3957,6 +4880,15 @@ function createRuntime(agent, config, hostLock = DEFAULT_HOST_LOCK, readGoalStat
|
|
|
3957
4880
|
consumeRecovery
|
|
3958
4881
|
};
|
|
3959
4882
|
}
|
|
4883
|
+
/** The durable session working directory, when the V3 header carries one. */
|
|
4884
|
+
function sessionCwd(session) {
|
|
4885
|
+
const header = session.header;
|
|
4886
|
+
return typeof header?.cwd === "string" && header.cwd.length > 0 ? header.cwd : void 0;
|
|
4887
|
+
}
|
|
4888
|
+
/** A bounded signal for a short trusted readback performed by the gate. */
|
|
4889
|
+
function requestSignal() {
|
|
4890
|
+
return AbortSignal.timeout(5e3);
|
|
4891
|
+
}
|
|
3960
4892
|
/** Delegated/subagent sessions never receive root-conversation injections. */
|
|
3961
4893
|
function isDelegatedSession(session) {
|
|
3962
4894
|
const header = session.header;
|
|
@@ -3992,9 +4924,9 @@ function revalidateCoreLock(config, expected) {
|
|
|
3992
4924
|
};
|
|
3993
4925
|
}
|
|
3994
4926
|
}
|
|
3995
|
-
function apply(ctx, rawConfig = {}) {
|
|
4927
|
+
function apply(ctx, rawConfig = {}, seams = {}) {
|
|
3996
4928
|
const config = resolveConfig(rawConfig);
|
|
3997
|
-
const installedHostLock = evaluateHostLock(config.hostLockPackages ?? [], {
|
|
4929
|
+
const installedHostLock = seams.hostLock ?? evaluateHostLock(config.hostLockPackages ?? [], {
|
|
3998
4930
|
platform: config.hostLockPlatform,
|
|
3999
4931
|
profileKind: config.hostLockProfile
|
|
4000
4932
|
});
|
|
@@ -4006,7 +4938,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
4006
4938
|
if (!runtime) {
|
|
4007
4939
|
const goals = optionalGoalService(ctx, agent);
|
|
4008
4940
|
const refreshHostLock = () => {
|
|
4009
|
-
const current = bindLiveGoalCapability(revalidateCoreLock(config, installedHostLock), Boolean(goals) && hasPinnedUpdateGoalTool(agent));
|
|
4941
|
+
const current = bindLiveGoalCapability(seams.hostLock ?? revalidateCoreLock(config, installedHostLock), Boolean(goals) && hasPinnedUpdateGoalTool(agent));
|
|
4010
4942
|
hostLocks.set(agent, current);
|
|
4011
4943
|
return current;
|
|
4012
4944
|
};
|
|
@@ -4045,8 +4977,41 @@ function apply(ctx, rawConfig = {}) {
|
|
|
4045
4977
|
runtime.sync();
|
|
4046
4978
|
return durable;
|
|
4047
4979
|
}, () => runtime.markRecoveryNeeded()));
|
|
4980
|
+
/**
|
|
4981
|
+
* Persist one C10 release record through the plugin-notice channel and make
|
|
4982
|
+
* it durable before returning. A record that cannot be flushed is reported
|
|
4983
|
+
* as a failure: an unflushed reservation is not an in-flight operation, and
|
|
4984
|
+
* an unflushed settlement would let a consumed ticket look unused.
|
|
4985
|
+
*/
|
|
4986
|
+
const persistReleaseRecord = async (toolAgent, prefix, payload) => {
|
|
4987
|
+
const target = toolAgent.session;
|
|
4988
|
+
target.append.bind(target)("user/message", createUserMessage({
|
|
4989
|
+
content: [{
|
|
4990
|
+
type: "text",
|
|
4991
|
+
text: `${prefix}${JSON.stringify(payload)}`
|
|
4992
|
+
}],
|
|
4993
|
+
source: {
|
|
4994
|
+
kind: "plugin",
|
|
4995
|
+
plugin: "context-guard",
|
|
4996
|
+
form: "notice",
|
|
4997
|
+
summary: boundContextSummary("recording an explicit release record")
|
|
4998
|
+
}
|
|
4999
|
+
}), { surfaceOp: "append" });
|
|
5000
|
+
let durable = false;
|
|
5001
|
+
try {
|
|
5002
|
+
durable = await ctx.sessions.flush(target);
|
|
5003
|
+
} catch {
|
|
5004
|
+
durable = false;
|
|
5005
|
+
}
|
|
5006
|
+
runtime.setDurability(durable);
|
|
5007
|
+
runtime.sync();
|
|
5008
|
+
return durable;
|
|
5009
|
+
};
|
|
4048
5010
|
const evidenceOptions = {
|
|
4049
5011
|
hostCapability: createHostCapabilityEvaluator(hostLocks.get(agent) ?? installedHostLock),
|
|
5012
|
+
...seams.commandRunner ? { commandRunner: seams.commandRunner } : {},
|
|
5013
|
+
...seams.fetcher ? { fetcher: seams.fetcher } : {},
|
|
5014
|
+
...seams.allowLoopbackHttpRegistry ? { allowLoopbackHttpRegistry: true } : {},
|
|
4050
5015
|
prepareMutation: async (toolAgent) => {
|
|
4051
5016
|
if (toolAgent.session !== agent.session) return false;
|
|
4052
5017
|
const durable = await ctx.sessions.flush(agent.session);
|
|
@@ -4059,6 +5024,63 @@ function apply(ctx, rawConfig = {}) {
|
|
|
4059
5024
|
return authorizeMutationFromProjection(runtime.projection, request);
|
|
4060
5025
|
},
|
|
4061
5026
|
marketOrigin: optionalMarketOrigin(ctx, agent),
|
|
5027
|
+
releaseGate: async (request) => {
|
|
5028
|
+
runtime.sync();
|
|
5029
|
+
const projection = runtime.projection;
|
|
5030
|
+
if (!(projection.policy === "release" || projection.releaseContracts.length > 0)) return {
|
|
5031
|
+
status: "granted",
|
|
5032
|
+
reasonCode: "release_profile_not_adopted"
|
|
5033
|
+
};
|
|
5034
|
+
const observed = { ...request.observed };
|
|
5035
|
+
const declaredRef = releaseContractFor(projection, request.operation)?.candidate.ref;
|
|
5036
|
+
if (declaredRef !== void 0 && observed.ref === void 0) {
|
|
5037
|
+
const refSha = await resolveAuditedRef(sessionCwd(runtime.session), declaredRef, evidenceOptions, requestSignal());
|
|
5038
|
+
if (refSha !== void 0) {
|
|
5039
|
+
observed.ref = declaredRef;
|
|
5040
|
+
observed.refSha = refSha;
|
|
5041
|
+
}
|
|
5042
|
+
}
|
|
5043
|
+
const decision = releasePreEffectDecision(projection, {
|
|
5044
|
+
operation: request.operation,
|
|
5045
|
+
observed,
|
|
5046
|
+
resolvedTarget: request.resolvedTarget,
|
|
5047
|
+
nowEpochMs: Date.now()
|
|
5048
|
+
});
|
|
5049
|
+
if (decision.status !== "granted" || decision.contractId === void 0) return {
|
|
5050
|
+
status: "denied",
|
|
5051
|
+
reasonCode: decision.reasonCode
|
|
5052
|
+
};
|
|
5053
|
+
return await persistReleaseRecord(agent, RELEASE_RESERVATION_PREFIX, {
|
|
5054
|
+
contractId: decision.contractId,
|
|
5055
|
+
operation: request.operation,
|
|
5056
|
+
callId: request.callId,
|
|
5057
|
+
startedAtSeq: 0,
|
|
5058
|
+
status: "in_flight",
|
|
5059
|
+
...observed.artifactSri !== void 0 ? { observedArtifactSri: observed.artifactSri } : {}
|
|
5060
|
+
}) ? {
|
|
5061
|
+
status: "granted",
|
|
5062
|
+
reasonCode: decision.reasonCode,
|
|
5063
|
+
contractId: decision.contractId
|
|
5064
|
+
} : {
|
|
5065
|
+
status: "denied",
|
|
5066
|
+
reasonCode: "release_reservation_not_durable"
|
|
5067
|
+
};
|
|
5068
|
+
},
|
|
5069
|
+
releaseSettle: async (request) => {
|
|
5070
|
+
const contractId = request.contractId ?? releaseContractFor(runtime.projection, request.operation)?.contractId ?? "unknown";
|
|
5071
|
+
const contract = runtime.projection.releaseContracts.find((entry) => entry.contractId === contractId);
|
|
5072
|
+
const reservation = reservationFor(runtime.projection, contractId, request.callId);
|
|
5073
|
+
let outcome = request.effect === "not_effected" ? "not_effected" : "unknown";
|
|
5074
|
+
if (request.effect === "completed" && contract) outcome = readbackSettlesContract(contract, request.readback, reservation?.observedArtifactSri) === "settled" ? "settled" : "unknown";
|
|
5075
|
+
await persistReleaseRecord(agent, RELEASE_SETTLEMENT_PREFIX, {
|
|
5076
|
+
contractId,
|
|
5077
|
+
operation: request.operation,
|
|
5078
|
+
callId: request.callId,
|
|
5079
|
+
settledAtSeq: 0,
|
|
5080
|
+
readback: request.readback,
|
|
5081
|
+
outcome
|
|
5082
|
+
});
|
|
5083
|
+
},
|
|
4062
5084
|
persistRestartIntent: async (toolAgent, intent) => {
|
|
4063
5085
|
const session = toolAgent.session;
|
|
4064
5086
|
session.append.bind(session)("user/message", createUserMessage({
|
|
@@ -4094,7 +5116,35 @@ function apply(ctx, rawConfig = {}) {
|
|
|
4094
5116
|
reasonCode: evaluation.reasonCode
|
|
4095
5117
|
};
|
|
4096
5118
|
},
|
|
4097
|
-
commandTemplate: (action) => GIT_COMMAND_TEMPLATES[action]
|
|
5119
|
+
commandTemplate: (action) => GIT_COMMAND_TEMPLATES[action],
|
|
5120
|
+
refreshProjection: async () => {
|
|
5121
|
+
const durable = await ctx.sessions.flush(agent.session);
|
|
5122
|
+
runtime.setDurability(durable);
|
|
5123
|
+
runtime.sync();
|
|
5124
|
+
return durable;
|
|
5125
|
+
}
|
|
5126
|
+
}));
|
|
5127
|
+
agent.ctx.tools.register(createInterpretTool({
|
|
5128
|
+
getProjection: () => runtime.projection,
|
|
5129
|
+
refreshProjection: async () => {
|
|
5130
|
+
const durable = await ctx.sessions.flush(agent.session);
|
|
5131
|
+
runtime.setDurability(durable);
|
|
5132
|
+
runtime.sync();
|
|
5133
|
+
return durable;
|
|
5134
|
+
}
|
|
5135
|
+
}));
|
|
5136
|
+
agent.ctx.tools.register(createReleaseTool({
|
|
5137
|
+
getProjection: () => runtime.projection,
|
|
5138
|
+
fetcher: evidenceOptions.fetcher,
|
|
5139
|
+
...evidenceOptions.allowLoopbackHttpRegistry ? { allowLoopbackHttpRegistry: true } : {},
|
|
5140
|
+
persistSettlement: async (request) => persistReleaseRecord(request.agent, RELEASE_SETTLEMENT_PREFIX, {
|
|
5141
|
+
contractId: request.contractId,
|
|
5142
|
+
operation: request.operation,
|
|
5143
|
+
callId: request.callId,
|
|
5144
|
+
settledAtSeq: 0,
|
|
5145
|
+
readback: request.readback,
|
|
5146
|
+
outcome: request.outcome
|
|
5147
|
+
})
|
|
4098
5148
|
}));
|
|
4099
5149
|
agent.ctx.tools.register(createExternalOperationTool((id, toolAgent) => readExternalOperation(ctx, toolAgent, id), () => evaluateExternalWaitCapability(hostLocks.get(agent) ?? installedHostLock)));
|
|
4100
5150
|
agent.ctx.tools.guard((exec) => goalCompletionDenial(runtime.projection, exec.name, exec.arguments));
|
|
@@ -4108,12 +5158,14 @@ function apply(ctx, rawConfig = {}) {
|
|
|
4108
5158
|
if (decision.kind !== "enter") return decision;
|
|
4109
5159
|
const injected = [];
|
|
4110
5160
|
const delegated = isDelegatedSession(agent.session);
|
|
4111
|
-
let boundaryPending = !runtime.
|
|
5161
|
+
let boundaryPending = !runtime.protocolV5Present;
|
|
4112
5162
|
const firstStep = previewFirstStepInjection({
|
|
4113
5163
|
activation: config.activation,
|
|
4114
5164
|
enabled: runtime.projection.enabled,
|
|
5165
|
+
boundaryV5Present: runtime.protocolV5Present,
|
|
4115
5166
|
boundaryPresent: runtime.protocolV4Present,
|
|
4116
|
-
delegated
|
|
5167
|
+
delegated,
|
|
5168
|
+
policy: runtime.projection.policy
|
|
4117
5169
|
}, claimedBatchHasRealRootInput(decision.messages));
|
|
4118
5170
|
if (firstStep) {
|
|
4119
5171
|
injected.push(pluginNoticeMessage(firstStep.boundary, "Context Guard recorded a replay version boundary"));
|
|
@@ -4128,7 +5180,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
4128
5180
|
if (recovery && digest$2 !== runtime.projection.lastRecoveryDigest) {
|
|
4129
5181
|
runtime.projection.lastRecoveryDigest = digest$2;
|
|
4130
5182
|
if (boundaryPending && !delegated) {
|
|
4131
|
-
injected.push(pluginNoticeMessage(
|
|
5183
|
+
injected.push(pluginNoticeMessage(PROTOCOL_V5_NOTICE, "Context Guard recorded a replay version boundary"));
|
|
4132
5184
|
boundaryPending = false;
|
|
4133
5185
|
}
|
|
4134
5186
|
injected.push(createUserMessage({
|
|
@@ -4272,4 +5324,4 @@ function normalizeGoalState(value) {
|
|
|
4272
5324
|
}
|
|
4273
5325
|
|
|
4274
5326
|
//#endregion
|
|
4275
|
-
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, LATEST_SUPPORTED_HOST_VERSION, 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, SUPPORTED_HOST_VERSIONS, 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 };
|
|
5327
|
+
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, BOUNDED_ARTIFACT_TYPES, CAPTURE_V042_NOTICE, CERTIFICATE_VERSION, CERTIFICATE_VERSION_V2, COMMAND_SURFACE_MANIFEST, CONFIRM_LINE_PATTERN, CONTROL_RECORD_PREFIX, Config, DEFAULT_DELEGATION_TOOL_NAMES, 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, LATEST_SUPPORTED_HOST_VERSION, LEGACY_HOST_COHORTS, MIN_RECOVERY_CHAR_BUDGET, MIN_SUPPORTED_HOST_VERSION, NO_PROGRESS_RECORD_PREFIX, NO_PROGRESS_TURNS_BEFORE_STOP, PROOF_CAPABILITY_MATRIX, PROOF_KINDS, PROOF_KINDS_V2, PROOF_MANIFEST_DOMAIN_V2, PROOF_PROTOCOL_VERSION, PROOF_PROTOCOL_VERSION_V2, PROTOCOL_V3_NOTICE, PROTOCOL_V4_NOTICE, PROTOCOL_V5_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, STOP_PROTOCOL_VERSION_V2, SUPPORTED_EVIDENCE_ADAPTERS, SUPPORTED_HOST_RANGE, SUPPORTED_HOST_VERSIONS, SessionApiError, actionCompatible, apply, authorityCaptureCounts, availableBoundaryQualifications, bindExecutableIdentity, bindLiveGoalCapability, bindProofToProjection, bindProofV2ToProjection, bindingSatisfies, boundedArtifactChoiceMatches, canonicalArgvFromCommand, canonicalProjection, canonicalizePath, captureClause, captureItem, certifyCheckpoint, claimedBatchHasRealRootInput, classifyClause, classifyCompletionClaim, classifyTaskIntent, classifyUserInteraction, closingHint, combineHostPolicy, commitIndexSnapshotDigest, commitTreeSnapshotDigest, compareHostVersions, confirmRebind, createGitPrestateEnvelope, createProjection, createProofManifest, createProofManifestV2, currentContractDigest, decideTurnBoundary, decideTurnStopping, decisionBoundaryKey, deriveItemDiagnosis, deriveProjection, digestStrings, effectuateBoundary, evaluateExternalWaitCapability, evaluateHostCapability, evaluateHostLock, evaluateMinimumHostVersion, evaluateToolSurfaceCapability, evidenceAvailabilityReason, evidenceCoverage, evidenceFromPersistedToolResult, evidenceMatchesItem, executeRevalidatedGitEffect, extractArtifactPaths, extractMethod, extractOperation, extractTextContent, extractToolSubject, firstStepGuidance, 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, proofCapabilityReport, proofDigest, proofDigestV2, proofEvidenceConstraints, proofHostSurfacesOf, proofOperationMatches, proofV2Rejection, proposeRebind, proposeRebindOutcome, proposeRebindV042, qualifyBoundary, readActiveHostGraph, rebindAttemptKey, rebindResponse, recoveryDigest, relevantEvidence, renderRecoveryPacket, replayRebindResult, requestedIdentityKey, requestedTargetAuthorizesMutation, requestedTargetMatchesResolved, requiredSubjectsOf, resolveActiveProfileHostLock, resolveInstalledHostLock, revalidateGitPrestate, sanitizeClauseText, sanitizeUrl, satisfiesSupportedHostRange, scopeCoverageDigest, segmentAuthorityBlocks, segmentClauses, selectHostCohort, semanticActionFromCommand, semanticActionFromText, semanticActionOfScope, sessionQuery, sessionQueryV2, sha256, snapshotSessionEvents, statefulActionsOfScope, supersedeItem, validateActionManifest, validateActionTarget, validateManifest, validateProofManifest, validateProofManifestV2, verifiedLinearCommitReadback, verifyComposedHostLockDump, withDurability };
|