dsh-completion-guard 0.6.3 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,16 +1,16 @@
1
- import { $ as evidenceFromPersistedToolResult, $n as proposeRebind, $r as isRestatement, $t as createProofManifestV2, A as lifecyclePhase, Ai as requestedTargetMatchesResolved, An as NO_PROGRESS_TURNS_BEFORE_STOP, Ar as canonicalRegistryBase, At as SUPPORTED_HOST_RANGE, B as RELEASE_OPERATIONS, Bi as sanitizeClauseText, Bn as progressFingerprint, Br as clauseIsProtected, Bt as authorityCaptureCounts, C as gitCommandMatchesTarget, Ci as STOP_PROTOCOL_VERSION_V2, Cn as renderRecoveryPacket, Cr as classifyClause, Ct as evaluateHostCapability, D as FIRST_STEP_GUIDANCE, Di as isStatefulAction, Dn as isVerifyingCapability, Dr as extractOperation, Dt as selectHostCohort, E as verifiedLinearCommitReadback, Ei as boundedArtifactChoiceMatches, En as evidenceMatchesItem, Er as extractMethod, Et as hostVersionFromPackages, F as PROTOCOL_V4_NOTICE, Fi as COMMAND_SURFACE_MANIFEST, Fn as isRootPauseRequest, Fr as LEGACY_QUALIFICATION, Ft as satisfiesSupportedHostRange, G as inFlightReservation, Gn as unitDescendantIds, Gr as interpretClause, Gt as PROOF_KINDS_V2, H as RELEASE_RESERVATION_PREFIX, Hi as sha256, Hn as hasCurrentCertificate, Hr as governedClauseRestrictsExecution, Ht as certifyCheckpoint, I as PROTOCOL_V5_NOTICE, Ii as validateManifest, In as isWholeTaskCompletionClaim, Ir as actionVerbMatches, It as RC015_RC2_HOST_PACKAGES, J as releaseContractFor, Jn as isCurrentAcceptedBoundary, Jr as isExecutableItem, Jt as PROOF_PROTOCOL_VERSION_V2, K as normalizeReleaseContract, Kn as availableBoundaryQualifications, Kr as interpretMessage, Kt as PROOF_MANIFEST_DOMAIN_V2, L as applyUpgradeEligibility, Li as canonicalizePath, Ln as latestAssistantText, Lr as clarifiedSpanOf, Lt as RC015_HOST_PACKAGES, M as CAPTURE_V042_NOTICE, Mi as semanticActionFromText, Mn as decideTurnBoundary, Mr as classifyTaskIntent, Mt as compareHostVersions, N as DEFAULT_DELEGATION_TOOL_NAMES, Ni as validateActionManifest, Nn as decideTurnStopping, Nr as classifyUserInteraction, Nt as evaluateMinimumHostVersion, O as claimedBatchHasRealRootInput, Oi as requestedIdentityKey, On as CONTROL_RECORD_PREFIX, Or as isInformationalMessage, Ot as LATEST_SUPPORTED_HOST_VERSION, P as PROTOCOL_V3_NOTICE, Pi as validateActionTarget, Pn as decisionBoundaryKey, Pr as GRANTED_QUALIFICATION, Pt as parseHostVersion, Q as supersedeItem, Qn as confirmRebind, Qr as isQuestionScopeNeedingReview, Qt as createProofManifest, R as deriveProjection, Ri as digestStrings, Rn as latestRootInstruction, Rr as clauseAsksOwnQuestion, Rt as RC1_HOST_PACKAGES, S as executeRevalidatedGitEffect, Si as STOP_PROTOCOL_VERSION, Sn as recoveryDigest, Sr as captureItem, St as evaluateExternalWaitCapability, T as revalidateGitPrestate, Ti as actionCompatible, Tn as evidenceCoverage, Tr as extractArtifactPaths, Tt as evaluateToolSurfaceCapability, U as RELEASE_SETTLEMENT_PREFIX, Un as certifiableOpenItems, Ur as hasOrderedCoordination, Ut as PROOF_CAPABILITY_MATRIX, V as RELEASE_OPERATION_SURFACES, Vi as sanitizeUrl, Vn as goalCompletionDenial, Vr as explanationHasActionResidue, Vt as segmentAuthorityBlocks, W as contractById, Wn as certificateClosure, Wr as hasQuestionScope, Wt as PROOF_KINDS, X as releasePreEffectDecision, Xn as currentContractDigest, Xr as isInformationalFragment, Xt as bindProofV2ToProjection, Y as releaseCoverage, Yn as qualifyBoundary, Yr as isExplanationScope, Yt as bindProofToProjection, Z as reservationFor, Zn as createProjection, Zr as isOpenObligation, Zt as canonicalProjection, _ as GIT_COMMAND_MANIFEST_IDS, _i as BOUNDED_ARTIFACT_TYPES, _n as MIN_RECOVERY_CHAR_BUDGET, _r as capabilityFactOf, _t as HOST_CAPABILITY_PACKAGE_GROUPS, a as injectActiveProfileHostLock, ai as namedActions, an as proofOperationMatches, ar as CONFIRM_LINE_PATTERN, at as isRunExecutable, b as commitTreeSnapshotDigest, bi as SEMANTIC_ACTIONS, bn as closingHint, br as removalIsPartiallyKnown, bt as bindExecutableIdentity, c as packageRowsFromPnpmLock, ci as questionHeadsClause, cn as scopeCoverageDigest, cr as capabilityRemedyPhrase, ct as ACTIVE_HOST_COHORT_ID, d as resolveInstalledHostLock, di as semanticActionOfScope, dn as validateProofManifest, dr as itemDiagnosis, dt as ALPHA2_DSHMARKET_139_HOST_PACKAGES, ei as itemHoldsExecutionAuthority, en as proofCapabilityReport, er as proposeRebindOutcome, et as extractTextContent, f as verifyComposedHostLockDump, fi as splitTextFragments, fn as validateProofManifestV2, fr as relevantEvidence, ft as ALPHA2_HOST_PACKAGES, g as snapshotSessionEvents, gi as ACTION_MANIFEST_VERSION, gn as DEFAULT_RECOVERY_CHAR_BUDGET, gr as capabilityConsequence, gt as GOAL_HOST_PACKAGES, h as SessionApiError, hi as ACTION_MANIFEST, hn as CLEANUP_CONDITION_RULE_SHORT, hr as admissibleForRemoval, ht as EXPECTED_HOST_PACKAGES, i as hostLockRowsFromComposedDump, ii as maskQuotedSpans, in as proofHostSurfacesOf, ir as replayRebindResult, it as canonicalArgvFromCommand, j as previewFirstStepInjection, ji as semanticActionFromCommand, jn as classifyCompletionClaim, jr as npmEscapedPackageName, jt as SUPPORTED_HOST_VERSIONS, k as firstStepGuidance, ki as requestedTargetAuthorizesMutation, kn as NO_PROGRESS_RECORD_PREFIX, kr as segmentClauses, kt as MIN_SUPPORTED_HOST_VERSION, l as readActiveHostGraph, li as reportingHeadGoverns, ln as sessionQuery, lr as deriveItemDiagnosis, lt as ACTIVE_HOST_COHORT_IDS, m as SESSION_EVENT_ENVELOPE_INVALID, mi as verbIsNegated, mn as CLEANUP_CONDITION_RULE_COMPACT, mr as actionHasCertificationPath, mt as DEFAULT_HOST_LOCK, n as combineHostPolicy, ni as legacyQuestionReadingIsInformational, nn as proofDigestV2, nr as rebindAttemptKey, nt as isDeterministicCheck, o as inspectTargetHostGraph, oi as opensWithDirective, on as proofV2Rejection, or as isFrozenV042RebindResponse, ot as parsePwshCommand, p as SESSION_API_UNSUPPORTED, pi as statefulActionsOfScope, pn as CLEANUP_CONDITION_RULE, pr as DEPENDENCY_FREE_ONLY_CONDITION, pt as BASE_HOST_PACKAGES, q as readbackSettlesContract, qn as effectuateBoundary, qr as introducesActionClause, qt as PROOF_PROTOCOL_VERSION, r as hostLockContextFromComposedDump, ri as maskCodeSpans, rn as proofEvidenceConstraints, rr as rebindResponse, rt as withDurability, s as packageRowsFromActiveGraph, si as qualificationOfClause, sn as requiredSubjectsOf, sr as parseConfirmationMessage, st as parseShellCommand, t as HostProfileError, ti as kindOfScope, tn as proofDigest, tr as proposeRebindV042, tt as extractToolSubject, u as resolveActiveProfileHostLock, ui as restatedContentOf, un as sessionQueryV2, ur as evidenceAvailabilityReason, ut as ACTIVE_HOST_LAUNCHER_VERSION, v as GIT_COMMAND_TEMPLATES, vi as CERTIFICATE_VERSION, vn as carriesCleanupCondition, vr as partialFailureOf, vt as HOST_COHORTS, w as parseGitCommandManifest, wi as SUPPORTED_EVIDENCE_ADAPTERS, wn as bindingSatisfies, wr as environmentDefaultRepositoryTarget, wt as evaluateHostLock, x as createGitPrestateEnvelope, xi as STATEFUL_ACTIONS, xn as openItems, xr as captureClause, xt as bindLiveGoalCapability, y as commitIndexSnapshotDigest, yi as CERTIFICATE_VERSION_V2, yn as cleanupConditionFor, yr as removalIsComplete, yt as LEGACY_HOST_COHORTS, z as legacyRecordsNeedingReview, zi as normalizeClause, zn as observeAssistantOutcome, zr as clauseIsGoverned, zt as ALPHA3_HOST_PACKAGES } from "./domain-BUA1lLjs.js";
1
+ import { $ as currentV6Feedback, $i as requestedIdentityKey, $n as decideTurnStopping, $r as npmEscapedPackageName, $t as RC015_RC2_HOST_PACKAGES, A as firstStepGuidanceV6, Ai as opensWithDirective, An as CLEANUP_CONDITION_RULE, Ar as capabilityRemedyPhrase, At as BASE_HOST_PACKAGES, B as SessionApiError, Bi as ACTION_MANIFEST, Bn as renderRecoveryPacket, Br as partialFailureOf, Bt as evaluateHostCapability, C as gitCommandMatchesTarget, Ci as itemHoldsExecutionAuthority, Cn as proofV2Rejection, Cr as proposeRebindV042, Ct as parsePwshCommand, D as FIRST_STEP_GUIDANCE, Di as maskQuotedSpans, Dn as sessionQueryV2, Dr as CONFIRM_LINE_PATTERN, Dt as ACTIVE_HOST_LAUNCHER_VERSION, E as verifiedLinearCommitReadback, Ei as maskCodeSpans, En as sessionQuery, Er as replayRebindResult, Et as ACTIVE_HOST_COHORT_IDS, F as HOST_WORKDIR_PREFIX, Fi as restatedContentOf, Fn as carriesCleanupCondition, Fr as DEPENDENCY_FREE_ONLY_CONDITION, Ft as HOST_COHORTS, G as PROTOCOL_V3_NOTICE, Gi as SEMANTIC_ACTIONS, Gn as CONTROL_RECORD_PREFIX, Gr as classifyClause, Gt as LATEST_SUPPORTED_HOST_VERSION, H as projectCoreV2, Hi as BOUNDED_ARTIFACT_TYPES, Hn as evidenceCoverage, Hr as removalIsPartiallyKnown, Ht as evaluateToolSurfaceCapability, I as captureHostWorkdir, Ii as semanticActionOfScope, In as cleanupConditionFor, Ir as actionHasCertificationPath, It as LEGACY_HOST_COHORTS, J as PROTOCOL_V6_NOTICE, Ji as STOP_PROTOCOL_VERSION_V2, Jn as assessmentAction, Jr as extractMethod, Jt as SUPPORTED_HOST_VERSIONS, K as PROTOCOL_V4_NOTICE, Ki as STATEFUL_ACTIONS, Kn as NO_PROGRESS_RECORD_PREFIX, Kr as environmentDefaultRepositoryTarget, Kt as MIN_SUPPORTED_HOST_VERSION, L as sourcedNamedTestRoot, Li as splitTextFragments, Ln as closingHint, Lr as admissibleForRemoval, Lt as bindExecutableIdentity, M as previewFirstStepInjection, Mi as qualificationOfClause, Mn as CLEANUP_CONDITION_RULE_SHORT, Mr as evidenceAvailabilityReason, Mt as EXPECTED_HOST_PACKAGES, N as projectSessionCoreV2, Ni as questionHeadsClause, Nn as DEFAULT_RECOVERY_CHAR_BUDGET, Nr as itemDiagnosis, Nt as GOAL_HOST_PACKAGES, O as claimedBatchHasRealRootInput, Oi as namedActions, On as validateProofManifest, Or as isFrozenV042RebindResponse, Ot as ALPHA2_DSHMARKET_139_HOST_PACKAGES, P as sessionCoreSnapshot, Pi as reportingHeadGoverns, Pn as MIN_RECOVERY_CHAR_BUDGET, Pr as relevantEvidence, Pt as HOST_CAPABILITY_PACKAGE_GROUPS, Q as rootLocatorFlavor, Qi as isStatefulAction, Qn as decideTurnBoundary, Qr as canonicalRegistryBase, Qt as satisfiesSupportedHostRange, R as SESSION_API_UNSUPPORTED, Ri as statefulActionsOfScope, Rn as openItems, Rr as capabilityConsequence, Rt as bindLiveGoalCapability, S as executeRevalidatedGitEffect, Si as isRestatement, Sn as proofOperationMatches, Sr as proposeRebindOutcome, St as isRunExecutable, T as revalidateGitPrestate, Ti as legacyQuestionReadingIsInformational, Tn as scopeCoverageDigest, Tr as rebindResponse, Tt as ACTIVE_HOST_COHORT_ID, U as CAPTURE_V042_NOTICE, Ui as CERTIFICATE_VERSION, Un as evidenceMatchesItem, Ur as captureClause, Ut as hostVersionFromPackages, V as snapshotSessionEvents, Vi as ACTION_MANIFEST_VERSION, Vn as bindingSatisfies, Vr as removalIsComplete, Vt as evaluateHostLock, W as DEFAULT_DELEGATION_TOOL_NAMES, Wi as CERTIFICATE_VERSION_V2, Wn as isVerifyingCapability, Wr as captureItem, Wt as selectHostCohort, X as deriveProjection, Xi as actionCompatible, Xn as classifyCompletionClaim, Xr as isInformationalMessage, Xt as evaluateMinimumHostVersion, Y as applyUpgradeEligibility, Yi as SUPPORTED_EVIDENCE_ADAPTERS, Yn as assessmentOutcomePredicate, Yr as extractOperation, Yt as compareHostVersions, Z as legacyRecordsNeedingReview, Zi as boundedArtifactChoiceMatches, Zn as currentActionBases, Zr as segmentClauses, Zt as parseHostVersion, _ as GIT_COMMAND_MANIFEST_IDS, _i as isExecutableItem, _n as proofCapabilityReport, _r as qualifyBoundary, _t as extractToolSubject, a as auditedForegroundRenderers, aa as validateActionTarget, ai as clarifiedSpanOf, an as certifyCheckpoint, ar as observeAssistantOutcome, at as inFlightReservation, b as commitTreeSnapshotDigest, bi as isOpenObligation, bn as proofEvidenceConstraints, br as confirmRebind, bt as withDurability, c as hostLockRowsFromComposedDump, ca as canonicalizePath, ci as clauseIsProtected, cn as PROOF_KINDS_V2, cr as v6TestPredicate, ct as normalizeSettlement, d as packageRowsFromActiveGraph, da as sanitizeClauseText, di as hasOrderedCoordination, dn as PROOF_PROTOCOL_VERSION_V2, dr as certifiableOpenItems, dt as releaseCoverage, ea as requestedTargetAuthorizesMutation, ei as classifyTaskIntent, en as RC015_HOST_PACKAGES, er as decisionBoundaryKey, et as sourceItemForCoreRequirement, f as packageRowsFromPnpmLock, fa as sanitizeUrl, fi as hasQuestionScope, fn as bindProofToProjection, fr as certificateClosure, ft as releasePreEffectDecision, g as verifyComposedHostLockDump, gi as introducesActionClause, gn as createProofManifestV2, gr as isCurrentAcceptedBoundary, gt as extractTextContent, h as resolveInstalledHostLock, hi as interpretMessage, hn as createProofManifest, hr as effectuateBoundary, ht as evidenceFromPersistedToolResult, i as auditedDefaultWorkdirProvider, ia as validateActionManifest, ii as actionVerbMatches, in as segmentAuthorityBlocks, ir as latestRootInstruction, it as contractById, j as lifecyclePhase, ji as presentExplanationHead, jn as CLEANUP_CONDITION_RULE_COMPACT, jr as deriveItemDiagnosis, jt as DEFAULT_HOST_LOCK, k as firstStepGuidance, ki as opensConditionLead, kn as validateProofManifestV2, kr as parseConfirmationMessage, kt as ALPHA2_HOST_PACKAGES, l as injectActiveProfileHostLock, la as digestStrings, li as explanationHasActionResidue, ln as PROOF_MANIFEST_DOMAIN_V2, lr as goalCompletionDenial, lt as readbackSettlesContract, m as resolveActiveProfileHostLock, mi as interpretClause, mn as canonicalProjection, mr as availableBoundaryQualifications, mt as supersedeItem, n as activeRendererModule, na as semanticActionFromCommand, ni as GRANTED_QUALIFICATION, nn as ALPHA3_HOST_PACKAGES, nr as isWholeTaskCompletionClaim, nt as RELEASE_OPERATIONS, o as combineHostPolicy, oa as COMMAND_SURFACE_MANIFEST, oi as clauseAsksOwnQuestion, on as PROOF_CAPABILITY_MATRIX, or as progressFingerprint, ot as normalizeReleaseContract, p as readActiveHostGraph, pa as sha256, pi as hasWorkPredicate, pn as bindProofV2ToProjection, pr as unitDescendantIds, pt as reservationFor, q as PROTOCOL_V5_NOTICE, qi as STOP_PROTOCOL_VERSION, qn as NO_PROGRESS_TURNS_BEFORE_STOP, qr as extractArtifactPaths, qt as SUPPORTED_HOST_RANGE, r as auditedDefaultWorkdirHost, ra as semanticActionFromText, ri as LEGACY_QUALIFICATION, rn as authorityCaptureCounts, rr as latestAssistantText, rt as RELEASE_OPERATION_SURFACES, s as hostLockContextFromComposedDump, sa as validateManifest, si as clauseIsGoverned, sn as PROOF_KINDS, sr as testOutcomePredicate, st as normalizeReservation, t as HostProfileError, ta as requestedTargetMatchesResolved, ti as classifyUserInteraction, tn as RC1_HOST_PACKAGES, tr as isRootPauseRequest, tt as OUTCOME_STRENGTH, u as inspectTargetHostGraph, ua as normalizeClause, ui as governedClauseRestrictsExecution, un as PROOF_PROTOCOL_VERSION, ur as hasCurrentCertificate, ut as releaseContractFor, v as GIT_COMMAND_TEMPLATES, vi as isExplanationScope, vn as proofDigest, vr as currentContractDigest, vt as isDeterministicCheck, w as parseGitCommandManifest, wi as kindOfScope, wn as requiredSubjectsOf, wr as rebindAttemptKey, wt as parseShellCommand, x as createGitPrestateEnvelope, xi as isQuestionScopeNeedingReview, xn as proofHostSurfacesOf, xr as proposeRebind, xt as canonicalArgvFromCommand, y as commitIndexSnapshotDigest, yi as isInformationalFragment, yn as proofDigestV2, yr as createProjection, yt as persistedToolResultStatus, z as SESSION_EVENT_ENVELOPE_INVALID, zi as verbIsNegated, zn as recoveryDigest, zr as capabilityFactOf, zt as evaluateExternalWaitCapability } from "./domain-B3EuAllT.js";
2
2
  import { defineTool } from "@deepseek-ai/dsh-tools";
3
3
  import { createHash } from "node:crypto";
4
- import { basename, delimiter, dirname, isAbsolute, join, resolve } from "node:path";
4
+ import { basename, delimiter, dirname, isAbsolute, join, posix, resolve, win32 } from "node:path";
5
+ import { homedir, tmpdir } from "node:os";
5
6
  import { boundContextSummary, createToolResultMessage, createUserMessage } from "@deepseek-ai/dsh-llm";
7
+ import { closeSync, constants, existsSync, fchmodSync, fstatSync, fsyncSync, lstatSync, mkdirSync, openSync, readFileSync, realpathSync, unlinkSync, writeSync } from "node:fs";
8
+ import { promisify } from "node:util";
6
9
  import { execFile } from "node:child_process";
7
- import { constants, existsSync, readFileSync } from "node:fs";
8
10
  import { access, readFile, realpath } from "node:fs/promises";
9
- import { tmpdir } from "node:os";
10
11
  import { fileURLToPath } from "node:url";
11
- import { promisify } from "node:util";
12
12
  import { gunzip } from "node:zlib";
13
- import { SESSION_FORMAT_VERSION } from "@deepseek-ai/dsh-session";
13
+ import { SESSION_FORMAT_VERSION, Session, SessionId } from "@deepseek-ai/dsh-session";
14
14
 
15
15
  //#region src/tools/rebind.ts
16
16
  function createRebindTool(getProjection, prepare) {
@@ -86,6 +86,7 @@ function checkpointPage(p, query, full) {
86
86
  revision: p.contractRevision,
87
87
  evidence: [...p.evidence.values()],
88
88
  items: [...p.items.values()],
89
+ ...full.current_feedback === true ? { current_core: p.coreV2 } : {},
89
90
  item_ids,
90
91
  evidence_ids,
91
92
  evidence_scope,
@@ -167,12 +168,23 @@ function checkpointPage(p, query, full) {
167
168
  available_evidence: [],
168
169
  available_qualifications: []
169
170
  };
171
+ if (full.current_feedback === true) {
172
+ output.reason_code = full.reason_code;
173
+ output.feedback_source = "confirmed_core_v2";
174
+ output.current_actions = (full.current_actions ?? []).slice(0, 8);
175
+ output.current_action_total = (full.current_actions ?? []).length;
176
+ output.certificate_status = "not_requested";
177
+ }
170
178
  if (full.certificate) output.certificate = full.certificate;
171
179
  if (full.proof_state) output.proof_state = full.proof_state;
172
180
  const pagination = {
173
181
  snapshot: identity,
174
182
  scope: evidence_scope,
175
- counts: {
183
+ counts: full.current_feedback === true ? {
184
+ pending: full.open_items.length,
185
+ passed: Object.values(p.coreV2?.predicates ?? {}).filter((value) => value === "satisfied").length,
186
+ superseded: 0
187
+ } : {
176
188
  pending: [...p.items.values()].filter((i) => i.status === "pending").length,
177
189
  passed: [...p.items.values()].filter((i) => i.status === "passed").length,
178
190
  superseded: [...p.items.values()].filter((i) => i.status === "superseded").length
@@ -185,6 +197,10 @@ function checkpointPage(p, query, full) {
185
197
  id: String(row.id ?? row.item_id).slice(0, 128),
186
198
  reason_code: row.reason_code,
187
199
  certifiable: row.certifiable,
200
+ source_item_id: row.source_item_id,
201
+ revision: row.revision,
202
+ kind: row.kind,
203
+ semantic_action: row.semantic_action,
188
204
  next_step: typeof row.next_step === "string" ? row.next_step.slice(0, 240) : void 0,
189
205
  adapter_disposition: row.adapter_disposition,
190
206
  ...row.binding_template !== void 0 ? { binding_template: row.binding_template } : {},
@@ -352,7 +368,7 @@ function openItemForTool(projection, item) {
352
368
  function createCheckpointTool(getProjection, onRejected, prepare = async () => true) {
353
369
  return defineTool({
354
370
  name: "context_guard_checkpoint",
355
- description: "Request a completion certificate from existing durable evidence.",
371
+ description: "Read current ordinary closure from confirmed observations; request a certificate only for an explicitly adopted proof, Goal, or release contract.",
356
372
  parameters: {
357
373
  item_ids: {
358
374
  type: "array",
@@ -508,10 +524,27 @@ function createCheckpointTool(getProjection, onRejected, prepare = async () => t
508
524
  type: "string",
509
525
  enum: [
510
526
  "certified",
527
+ "observed",
511
528
  "incomplete",
512
529
  "unknown"
513
530
  ]
514
531
  },
532
+ feedback_source: {
533
+ type: "string",
534
+ enum: ["confirmed_core_v2"]
535
+ },
536
+ current_actions: {
537
+ type: "array",
538
+ items: {
539
+ type: "object",
540
+ additionalProperties: true
541
+ }
542
+ },
543
+ current_action_total: { type: "integer" },
544
+ certificate_status: {
545
+ type: "string",
546
+ enum: ["not_requested"]
547
+ },
515
548
  contract_revision: { type: "integer" },
516
549
  active_constraints: {
517
550
  type: "array",
@@ -638,6 +671,22 @@ function createCheckpointTool(getProjection, onRejected, prepare = async () => t
638
671
  certification_digest: { type: "string" },
639
672
  unit_id: { type: "string" },
640
673
  unit_closure_digest: { type: "string" },
674
+ root_locator_identity: { type: "string" },
675
+ native_observations: {
676
+ type: "object",
677
+ additionalProperties: false,
678
+ properties: {
679
+ schema: {
680
+ type: "string",
681
+ required: true
682
+ },
683
+ digests: {
684
+ type: "array",
685
+ required: true,
686
+ items: { type: "string" }
687
+ }
688
+ }
689
+ },
641
690
  goal_ref: { oneOf: [{
642
691
  type: "object",
643
692
  additionalProperties: false,
@@ -670,6 +719,46 @@ function createCheckpointTool(getProjection, onRejected, prepare = async () => t
670
719
  rejected_bindings: []
671
720
  };
672
721
  }
722
+ const currentFeedback = args.proof === void 0 ? currentV6Feedback(projection) : void 0;
723
+ if (currentFeedback) {
724
+ const openRows = currentFeedback.openIds.map((id) => {
725
+ const sourced = sourceItemForCoreRequirement(projection, id);
726
+ return {
727
+ id,
728
+ reason_code: currentFeedback.predicates[id],
729
+ ...sourced ? {
730
+ source_item_id: sourced.item.id,
731
+ revision: sourced.item.revision,
732
+ kind: sourced.item.kind,
733
+ text: sourced.item.normalizedText
734
+ } : {},
735
+ ...sourced?.origin ? {
736
+ source_start: sourced.origin.sourceStart,
737
+ source_end: sourced.origin.sourceEnd,
738
+ semantic_action: sourced.origin.action,
739
+ target: sourced.origin.target
740
+ } : sourced?.item.semanticAction ? { semantic_action: sourced.item.semanticAction } : {},
741
+ next_step: "Answer this sourced requirement using the current Host observation or final delivery; ordinary Guard bindings are not required."
742
+ };
743
+ });
744
+ const constraints = Object.entries(currentFeedback.predicates).filter(([, state]) => state === "constraint_active" || state === "constraint_unresolved" || state === "constraint_violated").map(([id, state]) => ({
745
+ id,
746
+ reason_code: state
747
+ }));
748
+ return checkpointPage(projection, args, {
749
+ status: currentFeedback.status,
750
+ reason_code: currentFeedback.reasonCode,
751
+ current_feedback: true,
752
+ contract_revision: projection.contractRevision,
753
+ blocking_total: openRows.length,
754
+ open_items: openRows,
755
+ active_constraints: constraints,
756
+ available_evidence: [],
757
+ available_qualifications: [],
758
+ rejected_bindings: [],
759
+ current_actions: currentFeedback.currentActions
760
+ });
761
+ }
673
762
  const bindings = args.bindings.map((binding) => ({
674
763
  itemId: binding.item_id,
675
764
  evidenceIds: binding.evidence_ids,
@@ -796,6 +885,8 @@ function createCheckpointTool(getProjection, onRejected, prepare = async () => t
796
885
  open_digest: result.checkpoint.openDigest,
797
886
  evidence_sha256: result.checkpoint.evidenceSha256,
798
887
  binding_digest: result.checkpoint.bindingDigest,
888
+ ...result.checkpoint.nativeObservations ? { native_observations: result.checkpoint.nativeObservations } : {},
889
+ ...result.checkpoint.rootLocatorIdentity ? { root_locator_identity: result.checkpoint.rootLocatorIdentity } : {},
799
890
  certification_digest: result.checkpoint.certificationDigest,
800
891
  ...result.checkpoint.unitId !== void 0 ? {
801
892
  unit_id: result.checkpoint.unitId,
@@ -1234,8 +1325,10 @@ const encodeCursor = (cursor) => Buffer.from(JSON.stringify(cursor), "utf8").toS
1234
1325
  * are reached by item ID, not re-listed here (0.6.1, W060-03).
1235
1326
  */
1236
1327
  function discoveryItemIds(p) {
1328
+ const current = currentV6Feedback(p);
1329
+ if (current && current.status !== "unknown") return current.openIds;
1237
1330
  const pending = [...p.items.values()].filter((item) => item.status === "pending").sort((a, b) => a.revision - b.revision || a.id.localeCompare(b.id));
1238
- if (p.boundaryProtocol !== 5) return pending.map((item) => item.id);
1331
+ if (p.boundaryProtocol === void 0 || p.boundaryProtocol < 5) return pending.map((item) => item.id);
1239
1332
  const closureUnits = new Set([...p.currentUnitId !== void 0 ? [p.currentUnitId, ...unitDescendantIds(p, p.currentUnitId)] : []]);
1240
1333
  return pending.filter((item) => item.unitId === void 0 || item.unitId !== void 0 && closureUnits.has(item.unitId)).map((item) => item.id);
1241
1334
  }
@@ -1251,7 +1344,7 @@ function discoveryItemIds(p) {
1251
1344
  function createPrepareTool(options) {
1252
1345
  return defineTool({
1253
1346
  name: "context_guard_prepare",
1254
- 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.",
1347
+ description: "Read-only diagnosis of open contract items. Ordinary changes use native host tools and observed facts; this tool never grants execution permission. Omit item_id for a paginated item list.",
1255
1348
  parameters: {
1256
1349
  item_id: { type: "string" },
1257
1350
  item_revision: { type: "number" },
@@ -1292,8 +1385,66 @@ function createPrepareTool(options) {
1292
1385
  status: "unknown",
1293
1386
  reason_code: "guard_unavailable"
1294
1387
  };
1388
+ const currentFeedback = currentV6Feedback(p);
1389
+ if (currentFeedback?.status === "unknown") return {
1390
+ status: "unknown",
1391
+ reason_code: currentFeedback.reasonCode
1392
+ };
1393
+ if (p.boundaryProtocol === 6 && args.item_id !== void 0) {
1394
+ const sourced = currentFeedback ? sourceItemForCoreRequirement(p, args.item_id) : void 0;
1395
+ const current = sourced?.item ?? p.items.get(args.item_id);
1396
+ if (!current) return {
1397
+ status: "rejected",
1398
+ reason_code: "item_not_found"
1399
+ };
1400
+ if (args.item_revision !== void 0 && args.item_revision !== current.revision) return {
1401
+ status: "rejected",
1402
+ reason_code: "item_revision_mismatch"
1403
+ };
1404
+ if (current.kind === "prohibition" && currentFeedback) {
1405
+ const state = currentFeedback.predicates[args.item_id];
1406
+ if (state === "constraint_active" || state === "constraint_unresolved" || state === "constraint_violated") return {
1407
+ status: state === "constraint_active" ? "active" : state === "constraint_unresolved" ? "unknown" : "incomplete",
1408
+ reason_code: state,
1409
+ item: {
1410
+ id: current.id,
1411
+ revision: current.revision,
1412
+ status: state
1413
+ },
1414
+ next_step: state === "constraint_active" ? "This sourced prohibition remains active." : state === "constraint_unresolved" ? "The current Host facts cannot establish whether this prohibition was respected." : "A sourced Host mutation violated this prohibition."
1415
+ };
1416
+ }
1417
+ if (current.semanticAction !== "publish" && currentFeedback) {
1418
+ const exactDerived = sourced?.origin !== void 0;
1419
+ const related = Object.entries(currentFeedback.predicates).filter(([id]) => exactDerived ? id === args.item_id : id === args.item_id || sourceItemForCoreRequirement(p, id)?.item.id === current.id);
1420
+ const state = related.length === 0 ? void 0 : related.every(([, value]) => value === "satisfied") ? "satisfied" : "insufficient";
1421
+ return {
1422
+ status: state === void 0 || state === "satisfied" ? "observed" : "incomplete",
1423
+ reason_code: state === void 0 ? "historical_item_not_current" : state === "satisfied" ? "ordinary_current_predicate_observed" : "current_predicate_insufficient",
1424
+ item: {
1425
+ id: args.item_id,
1426
+ source_item_id: current.id,
1427
+ revision: current.revision,
1428
+ status: state ?? "historical",
1429
+ related_requirement_ids: related.map(([id]) => id)
1430
+ },
1431
+ next_step: state === void 0 ? "This item is historical and is not current ordinary work." : state === "satisfied" ? "This ordinary predicate is already observed. Continue with the remaining sourced requirements; no Guard execution qualification is needed." : "Use the current sourced action and host facts; no Guard execution qualification is needed."
1432
+ };
1433
+ }
1434
+ if (current.semanticAction !== "publish") return {
1435
+ status: "observed",
1436
+ reason_code: "ordinary_execution_host_owned",
1437
+ item: {
1438
+ id: current.id,
1439
+ revision: current.revision,
1440
+ status: current.status
1441
+ },
1442
+ next_step: "Use the host tool for ordinary work. Guard can observe its persisted result and independent readback; no Guard preparation or qualification is required."
1443
+ };
1444
+ }
1295
1445
  if (args.item_id === void 0) {
1296
1446
  const filter = args.semantic_action ?? null;
1447
+ const coreIdentity = currentFeedback ? sha256(JSON.stringify(p.coreV2 ?? null)) : void 0;
1297
1448
  const invalidCursor = (reason_code, note) => ({
1298
1449
  status: "rejected",
1299
1450
  reason_code,
@@ -1307,18 +1458,23 @@ function createPrepareTool(options) {
1307
1458
  try {
1308
1459
  if (args.page_cursor.length <= 1024) {
1309
1460
  const value = JSON.parse(Buffer.from(args.page_cursor, "base64url").toString("utf8"));
1310
- 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;
1461
+ 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" && (value.c === void 0 || typeof value.c === "string")) parsed = value;
1311
1462
  }
1312
1463
  } catch {
1313
1464
  parsed = void 0;
1314
1465
  }
1315
1466
  if (!parsed) return invalidCursor("discovery_cursor_malformed");
1316
1467
  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.`);
1468
+ if (parsed.c !== coreIdentity) return invalidCursor("discovery_cursor_stale", "The current observation changed. Re-run discovery without page_cursor.");
1317
1469
  if ((parsed.f ?? null) !== (filter ?? null)) return invalidCursor("discovery_cursor_filter_mismatch");
1318
1470
  startAfter = parsed.k;
1319
1471
  }
1320
- const eligible = discoveryItemIds(p).map((id) => p.items.get(id)).filter((item$1) => filter === null || (item$1.semanticAction ?? "generic_run") === filter);
1321
- const startIndex = startAfter === void 0 ? 0 : eligible.findIndex((item$1) => item$1.revision === startAfter[0] && item$1.id === startAfter[1]) + 1;
1472
+ const eligible = discoveryItemIds(p).map((id) => ({
1473
+ id,
1474
+ sourced: currentFeedback ? sourceItemForCoreRequirement(p, id) : void 0,
1475
+ item: currentFeedback ? sourceItemForCoreRequirement(p, id)?.item : p.items.get(id)
1476
+ })).filter((entry) => entry.item !== void 0).filter(({ item: item$1, sourced }) => filter === null || (sourced?.origin?.action ?? item$1.semanticAction ?? "generic_run") === filter);
1477
+ const startIndex = startAfter === void 0 ? 0 : eligible.findIndex(({ id, item: item$1 }) => item$1.revision === startAfter[0] && id === startAfter[1]) + 1;
1322
1478
  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.");
1323
1479
  const page = eligible.slice(startIndex, startIndex + DISCOVERY_ITEM_LIMIT);
1324
1480
  const hasMore = startIndex + page.length < eligible.length;
@@ -1330,15 +1486,21 @@ function createPrepareTool(options) {
1330
1486
  total_open: eligible.length,
1331
1487
  listed: page.length,
1332
1488
  has_more: hasMore,
1333
- items: page.map((item$1) => {
1489
+ items: page.map(({ id, item: item$1, sourced }) => {
1334
1490
  const diagnosis$1 = deriveItemDiagnosis(p, item$1);
1335
1491
  return {
1336
- id: item$1.id,
1492
+ id,
1493
+ ...sourced?.origin ? {
1494
+ source_item_id: item$1.id,
1495
+ source_start: sourced.origin.sourceStart,
1496
+ source_end: sourced.origin.sourceEnd,
1497
+ target: sourced.origin.target
1498
+ } : {},
1337
1499
  revision: item$1.revision,
1338
1500
  kind: item$1.kind,
1339
1501
  ...item$1.taskKind !== void 0 ? { task_kind: item$1.taskKind } : {},
1340
- semantic_action: item$1.semanticAction ?? "generic_run",
1341
- reason_code: diagnosis$1.reason_code,
1502
+ semantic_action: sourced?.origin?.action ?? item$1.semanticAction ?? "generic_run",
1503
+ reason_code: currentFeedback ? currentFeedback.predicates[id] ?? "current_predicate_insufficient" : diagnosis$1.reason_code,
1342
1504
  text: item$1.normalizedText
1343
1505
  };
1344
1506
  }),
@@ -1346,10 +1508,11 @@ function createPrepareTool(options) {
1346
1508
  v: 1,
1347
1509
  r: p.contractRevision,
1348
1510
  f: filter,
1349
- k: [page[page.length - 1].revision, page[page.length - 1].id]
1511
+ k: [page[page.length - 1].item.revision, page[page.length - 1].id],
1512
+ ...coreIdentity ? { c: coreIdentity } : {}
1350
1513
  }) } : {},
1351
1514
  ...filter !== null ? { filtered_by: { semantic_action: filter } } : {},
1352
- note: "Re-run with one item_id to prepare that item, or pass page_cursor for the next page. Preparation performs no action."
1515
+ note: "Re-run with one item_id for a read-only diagnosis, or pass page_cursor for the next page."
1353
1516
  };
1354
1517
  }
1355
1518
  const item = p.items.get(args.item_id ?? "");
@@ -1498,9 +1661,9 @@ function parsePartition(args, extent) {
1498
1661
  if (!Array.isArray(raw)) return void 0;
1499
1662
  const spans = [];
1500
1663
  for (const entry of raw) {
1501
- const record$1 = entry;
1502
- const start = record$1?.start;
1503
- const end = record$1?.end;
1664
+ const record$2 = entry;
1665
+ const start = record$2?.start;
1666
+ const end = record$2?.end;
1504
1667
  if (typeof start !== "number" || !Number.isSafeInteger(start) || typeof end !== "number" || !Number.isSafeInteger(end) || start >= end) return void 0;
1505
1668
  spans.push({
1506
1669
  start,
@@ -1630,7 +1793,7 @@ function createInterpretTool(options) {
1630
1793
 
1631
1794
  //#endregion
1632
1795
  //#region src/tools/evidence.ts
1633
- const execFileAsync = promisify(execFile);
1796
+ const execFileAsync$1 = promisify(execFile);
1634
1797
  const PRODUCER_VERSION = "1.0.0";
1635
1798
  const PRODUCER_TOOL = "context_guard_evidence";
1636
1799
  const ACTION_TOOL = "context_guard_action";
@@ -1649,17 +1812,17 @@ const SUPPORTED = [
1649
1812
  const RESTART_INTENT_PREFIX = "Context Guard restart intent v1: ";
1650
1813
  function restartIntent(events, resolutionCallId, target) {
1651
1814
  for (const raw of events) {
1652
- const event = record(raw);
1815
+ const event = record$1(raw);
1653
1816
  if (!event || event.type !== "user/message") continue;
1654
- const data = record(event.data);
1655
- const source = record(data?.source);
1817
+ const data = record$1(event.data);
1818
+ const source = record$1(data?.source);
1656
1819
  if (source?.kind !== "plugin" || source.plugin !== "context-guard" || source.form !== "notice") continue;
1657
1820
  const content = Array.isArray(data?.content) ? data.content : [];
1658
- const block = content.length === 1 ? record(content[0]) : void 0;
1821
+ const block = content.length === 1 ? record$1(content[0]) : void 0;
1659
1822
  const text = typeof block?.text === "string" ? block.text : "";
1660
1823
  if (!text.startsWith(RESTART_INTENT_PREFIX)) continue;
1661
1824
  try {
1662
- const value = record(JSON.parse(text.slice(33)));
1825
+ const value = record$1(JSON.parse(text.slice(33)));
1663
1826
  if (value?.resolution_call_id === resolutionCallId && value.service_id === target.service_id && value.pre_generation === target.pre_generation) return true;
1664
1827
  } catch {}
1665
1828
  }
@@ -1687,7 +1850,7 @@ function installedProfile(moduleUrl = import.meta.url) {
1687
1850
  directory = parent;
1688
1851
  }
1689
1852
  }
1690
- function record(value) {
1853
+ function record$1(value) {
1691
1854
  return value && typeof value === "object" ? value : void 0;
1692
1855
  }
1693
1856
  function stable(value) {
@@ -1711,7 +1874,7 @@ function jsonExpectedTransition(transition) {
1711
1874
  };
1712
1875
  }
1713
1876
  function tuple(value) {
1714
- return record(value);
1877
+ return record$1(value);
1715
1878
  }
1716
1879
  function adapterId(action) {
1717
1880
  if (["create", "modify"].includes(action)) return "context-guard.artifact.v1";
@@ -1760,29 +1923,29 @@ function supported(action, role, resolved, observed = {}, commandManifest = {},
1760
1923
  };
1761
1924
  }
1762
1925
  function messageMeta(event) {
1763
- return record(record(event.data)?.meta);
1926
+ return record$1(record$1(event.data)?.meta);
1764
1927
  }
1765
1928
  function producerMeta(event) {
1766
- return record(messageMeta(event)?.contextGuard);
1929
+ return record$1(messageMeta(event)?.contextGuard);
1767
1930
  }
1768
1931
  function eventCallId(event) {
1769
- const data = record(event.data);
1932
+ const data = record$1(event.data);
1770
1933
  if (event.type === "tool/call") return typeof data?.callId === "string" ? data.callId : void 0;
1771
- const source = record(record(data?.message)?.source);
1934
+ const source = record$1(record$1(data?.message)?.source);
1772
1935
  return typeof source?.callId === "string" ? source.callId : void 0;
1773
1936
  }
1774
1937
  function findResolution(events, callId, action) {
1775
1938
  let selector;
1776
1939
  let commandManifest;
1777
1940
  for (const raw of events) {
1778
- const event = record(raw);
1941
+ const event = record$1(raw);
1779
1942
  if (!event || eventCallId(event) !== callId) continue;
1780
1943
  if (event.type === "tool/call") {
1781
- const data = record(event.data);
1944
+ const data = record$1(event.data);
1782
1945
  try {
1783
- const args = record(JSON.parse(String(data?.arguments ?? "{}")));
1784
- selector = record(args?.selector);
1785
- commandManifest = record(args?.command_manifest);
1946
+ const args = record$1(JSON.parse(String(data?.arguments ?? "{}")));
1947
+ selector = record$1(args?.selector);
1948
+ commandManifest = record$1(args?.command_manifest);
1786
1949
  } catch {
1787
1950
  return;
1788
1951
  }
@@ -1792,13 +1955,13 @@ function findResolution(events, callId, action) {
1792
1955
  const meta = producerMeta(event);
1793
1956
  if (meta?.semanticAction !== action || meta.evidenceRole !== "resolution" || meta.adapterVersion !== (action === "restart" ? "2.0.0" : PRODUCER_VERSION) || !selector || !commandManifest) return void 0;
1794
1957
  const target = tuple(meta.resolvedTarget);
1795
- const rawBinding = record(meta.gitBinding);
1796
- const rawManifest = record(rawBinding?.manifest);
1797
- const rawPrestate = record(rawBinding?.prestate);
1798
- const rawEnvelope = record(rawBinding?.envelope);
1799
- const rawExecutable = record(meta.executableIdentity);
1800
- const rawExpected = record(meta.expectedTransition);
1801
- const expectedParameters$1 = record(rawExpected?.parameters);
1958
+ const rawBinding = record$1(meta.gitBinding);
1959
+ const rawManifest = record$1(rawBinding?.manifest);
1960
+ const rawPrestate = record$1(rawBinding?.prestate);
1961
+ const rawEnvelope = record$1(rawBinding?.envelope);
1962
+ const rawExecutable = record$1(meta.executableIdentity);
1963
+ const rawExpected = record$1(meta.expectedTransition);
1964
+ const expectedParameters$1 = record$1(rawExpected?.parameters);
1802
1965
  const expectedTransition = rawExpected && typeof rawExpected.predicateId === "string" && rawExpected.version === 1 && rawExpected.predParamsKind === "inline" && expectedParameters$1 ? rawExpected : void 0;
1803
1966
  const expectedTransitionDigest = typeof meta.expectedTransitionDigest === "string" ? meta.expectedTransitionDigest : void 0;
1804
1967
  const interpreterIdentityValid = rawExecutable && (rawExecutable.interpreterRealpath === void 0 && rawExecutable.interpreterVersion === void 0 || typeof rawExecutable.interpreterRealpath === "string" && typeof rawExecutable.interpreterVersion === "string");
@@ -1822,14 +1985,14 @@ function findResolution(events, callId, action) {
1822
1985
  function findEffect(events, callId) {
1823
1986
  let call;
1824
1987
  for (const raw of events) {
1825
- const event = record(raw);
1988
+ const event = record$1(raw);
1826
1989
  if (!event) continue;
1827
1990
  const seq = typeof event.seq === "number" ? event.seq : -1;
1828
1991
  if (event.type === "tool/call" && eventCallId(event) === callId) {
1829
- const data = record(event.data);
1992
+ const data = record$1(event.data);
1830
1993
  let args = {};
1831
1994
  try {
1832
- args = record(JSON.parse(String(data?.arguments ?? "{}"))) ?? {};
1995
+ args = record$1(JSON.parse(String(data?.arguments ?? "{}"))) ?? {};
1833
1996
  } catch {
1834
1997
  args = {};
1835
1998
  }
@@ -1842,23 +2005,26 @@ function findEffect(events, callId) {
1842
2005
  };
1843
2006
  }
1844
2007
  if (event.type === "tool/result" && eventCallId(event) === callId && call) {
1845
- const data = record(event.data);
2008
+ const data = record$1(event.data);
1846
2009
  call.resultSeq = seq;
1847
- call.error = data?.error;
2010
+ call.error = persistedToolResultStatus(data, callId) !== "clean" ? {
2011
+ name: "HostResultError",
2012
+ code: "HOST_RESULT_UNTRUSTED"
2013
+ } : void 0;
1848
2014
  call.meta = data?.meta;
1849
- call.textContent = extractTextContent(record(data?.message)?.content ?? []);
2015
+ call.textContent = extractTextContent(record$1(data?.message)?.content ?? []);
1850
2016
  return call;
1851
2017
  }
1852
2018
  }
1853
2019
  }
1854
2020
  function actionCallMatches(events, callId, action, resolutionCallId, target) {
1855
2021
  for (const raw of events) {
1856
- const event = record(raw);
2022
+ const event = record$1(raw);
1857
2023
  if (!event || event.type !== "tool/call" || eventCallId(event) !== callId) continue;
1858
- const data = record(event.data);
2024
+ const data = record$1(event.data);
1859
2025
  if (data?.name !== ACTION_TOOL) return false;
1860
2026
  try {
1861
- const args = record(JSON.parse(String(data.arguments ?? "{}")));
2027
+ const args = record$1(JSON.parse(String(data.arguments ?? "{}")));
1862
2028
  return args?.semantic_action === action && args.resolution_call_id === resolutionCallId && args.target_digest === digest(target) && typeof args.contract_item_id === "string" && Number.isSafeInteger(args.contract_item_revision);
1863
2029
  } catch {
1864
2030
  return false;
@@ -1868,15 +2034,15 @@ function actionCallMatches(events, callId, action, resolutionCallId, target) {
1868
2034
  }
1869
2035
  function actionResultCompleted(events, callId) {
1870
2036
  for (const raw of events) {
1871
- const event = record(raw);
2037
+ const event = record$1(raw);
1872
2038
  if (!event || event.type !== "tool/result" || eventCallId(event) !== callId) continue;
1873
- return record(messageMeta(event)?.contextGuardAction)?.status === "completed";
2039
+ return record$1(messageMeta(event)?.contextGuardAction)?.status === "completed" && persistedToolResultStatus(event.data, callId) === "clean";
1874
2040
  }
1875
2041
  return false;
1876
2042
  }
1877
2043
  function plannedEffectDigest(manifest) {
1878
2044
  const name$1 = typeof manifest.planned_tool === "string" ? manifest.planned_tool : void 0;
1879
- const args = record(manifest.planned_arguments);
2045
+ const args = record$1(manifest.planned_arguments);
1880
2046
  return name$1 && args ? digest({
1881
2047
  name: name$1,
1882
2048
  arguments: args
@@ -1884,7 +2050,7 @@ function plannedEffectDigest(manifest) {
1884
2050
  }
1885
2051
  function plannedEffect(manifest) {
1886
2052
  const name$1 = typeof manifest.planned_tool === "string" ? manifest.planned_tool : void 0;
1887
- const args = record(manifest.planned_arguments);
2053
+ const args = record$1(manifest.planned_arguments);
1888
2054
  return name$1 && args ? {
1889
2055
  name: name$1,
1890
2056
  arguments: args,
@@ -1917,7 +2083,7 @@ function effectDigest(effect) {
1917
2083
  });
1918
2084
  }
1919
2085
  function cwdOf(agent) {
1920
- const header = record(agent.session.header);
2086
+ const header = record$1(agent.session.header);
1921
2087
  return typeof header?.cwd === "string" ? header.cwd : void 0;
1922
2088
  }
1923
2089
  function pathOf(selector, cwd) {
@@ -1935,7 +2101,7 @@ async function fileDigest(path) {
1935
2101
  }
1936
2102
  async function readJson(path) {
1937
2103
  try {
1938
- return record(JSON.parse(await readFile(path, "utf8")));
2104
+ return record$1(JSON.parse(await readFile(path, "utf8")));
1939
2105
  } catch {
1940
2106
  return;
1941
2107
  }
@@ -1959,7 +2125,7 @@ async function tgzIdentity(path) {
1959
2125
  if (name$1 === "package/package.json") {
1960
2126
  if (manifest || size$1 > 1024 * 1024) return void 0;
1961
2127
  try {
1962
- manifest = record(JSON.parse(tar.subarray(bodyStart, bodyEnd).toString("utf8")));
2128
+ manifest = record$1(JSON.parse(tar.subarray(bodyStart, bodyEnd).toString("utf8")));
1963
2129
  } catch {
1964
2130
  return;
1965
2131
  }
@@ -1969,7 +2135,7 @@ async function tgzIdentity(path) {
1969
2135
  if (typeof manifest?.name !== "string" || typeof manifest.version !== "string") return void 0;
1970
2136
  const gitHead = typeof manifest.gitHead === "string" && /^[0-9a-f]{40}$/.test(manifest.gitHead) ? manifest.gitHead : void 0;
1971
2137
  const repositoryField = manifest.repository;
1972
- const repository = typeof repositoryField === "string" ? repositoryField : record(repositoryField) && typeof record(repositoryField)?.url === "string" ? String(record(repositoryField).url) : void 0;
2138
+ const repository = typeof repositoryField === "string" ? repositoryField : record$1(repositoryField) && typeof record$1(repositoryField)?.url === "string" ? String(record$1(repositoryField).url) : void 0;
1973
2139
  return {
1974
2140
  name: manifest.name,
1975
2141
  version: manifest.version,
@@ -2037,10 +2203,10 @@ async function marketCapabilities(roots, signal) {
2037
2203
  redirect: "error"
2038
2204
  });
2039
2205
  if (!response.ok) return void 0;
2040
- const value = record(await response.json());
2206
+ const value = record$1(await response.json());
2041
2207
  if (value?.schema !== MARKET_SCHEMA || value.apiVersion !== 1 || value.marketVersion !== binding.version || value.profile !== binding.profile || value.bootId !== binding.bootId) return void 0;
2042
- const features = record(value.features);
2043
- const restart = record(value.restart);
2208
+ const features = record$1(value.features);
2209
+ const restart = record$1(value.restart);
2044
2210
  if (features?.restart !== true || restart?.supported !== true || restart.managedBy !== "market") return void 0;
2045
2211
  const provider = createHash("sha256").update(JSON.stringify([
2046
2212
  MARKET_SCHEMA,
@@ -2104,17 +2270,17 @@ async function profilePackage(profilePath, packageId) {
2104
2270
  }
2105
2271
  }
2106
2272
  async function registryIntegrity(registry, packageId, version, roots, signal) {
2107
- const canonical = canonicalRegistryBase(registry, { allowLoopbackHttp: roots.allowLoopbackHttpRegistry });
2108
- if (!canonical || canonical !== registry) return void 0;
2109
- const response = await (roots.fetcher ?? fetch)(new URL(npmEscapedPackageName(packageId), canonical), {
2273
+ const canonical$1 = canonicalRegistryBase(registry, { allowLoopbackHttp: roots.allowLoopbackHttpRegistry });
2274
+ if (!canonical$1 || canonical$1 !== registry) return void 0;
2275
+ const response = await (roots.fetcher ?? fetch)(new URL(npmEscapedPackageName(packageId), canonical$1), {
2110
2276
  signal,
2111
2277
  headers: { accept: "application/json" },
2112
2278
  redirect: "error"
2113
2279
  });
2114
2280
  if (!response.ok) return void 0;
2115
- const value = record(await response.json());
2116
- const release = record(record(value?.versions)?.[version]);
2117
- const dist = record(release?.dist);
2281
+ const value = record$1(await response.json());
2282
+ const release = record$1(record$1(value?.versions)?.[version]);
2283
+ const dist = record$1(release?.dist);
2118
2284
  return value?.name === packageId && release?.name === packageId && release.version === version && typeof dist?.integrity === "string" ? dist.integrity : void 0;
2119
2285
  }
2120
2286
  function windowsBatchCommand(file, args) {
@@ -2130,7 +2296,7 @@ async function windowsCommandInterpreter(signal) {
2130
2296
  const interpreterRealpath = await realpath(configured);
2131
2297
  const systemInterpreter = await realpath(resolve(systemRoot, "System32", "cmd.exe"));
2132
2298
  if (basename(interpreterRealpath).toLowerCase() !== "cmd.exe" || interpreterRealpath.toLowerCase() !== systemInterpreter.toLowerCase()) return void 0;
2133
- const { stdout, stderr } = await execFileAsync(interpreterRealpath, [
2299
+ const { stdout, stderr } = await execFileAsync$1(interpreterRealpath, [
2134
2300
  "/d",
2135
2301
  "/v:off",
2136
2302
  "/c",
@@ -2153,7 +2319,7 @@ async function execAuditedFile(file, args, options, interpreter) {
2153
2319
  if (process.platform === "win32" && /\.(?:cmd|bat)$/i.test(file)) {
2154
2320
  const command = windowsBatchCommand(file, args);
2155
2321
  if (!command || !interpreter) throw new Error("unsafe Windows batch invocation");
2156
- return execFileAsync(interpreter.interpreterRealpath, [
2322
+ return execFileAsync$1(interpreter.interpreterRealpath, [
2157
2323
  "/d",
2158
2324
  "/v:off",
2159
2325
  "/s",
@@ -2166,7 +2332,7 @@ async function execAuditedFile(file, args, options, interpreter) {
2166
2332
  windowsVerbatimArguments: true
2167
2333
  });
2168
2334
  }
2169
- return execFileAsync(file, args, {
2335
+ return execFileAsync$1(file, args, {
2170
2336
  ...options,
2171
2337
  encoding: "utf8"
2172
2338
  });
@@ -2202,14 +2368,14 @@ async function executableIdentity(executable, signal) {
2202
2368
  const candidate = resolve(directory, `${executable}${suffix}`);
2203
2369
  try {
2204
2370
  await access(candidate, constants.X_OK);
2205
- const canonical = await realpath(candidate);
2206
- const interpreter = process.platform === "win32" && /\.(?:cmd|bat)$/i.test(canonical) ? await windowsCommandInterpreter(signal) : void 0;
2207
- if (process.platform === "win32" && /\.(?:cmd|bat)$/i.test(canonical) && !interpreter) continue;
2208
- const { stdout, stderr } = await execAuditedFile(canonical, ["--version"], { signal }, interpreter);
2371
+ const canonical$1 = await realpath(candidate);
2372
+ const interpreter = process.platform === "win32" && /\.(?:cmd|bat)$/i.test(canonical$1) ? await windowsCommandInterpreter(signal) : void 0;
2373
+ if (process.platform === "win32" && /\.(?:cmd|bat)$/i.test(canonical$1) && !interpreter) continue;
2374
+ const { stdout, stderr } = await execAuditedFile(canonical$1, ["--version"], { signal }, interpreter);
2209
2375
  const version = `${stdout}${stderr}`.trim();
2210
2376
  if (version && !version.includes("\n") && !version.includes("\r")) return {
2211
2377
  executable,
2212
- realpath: canonical,
2378
+ realpath: canonical$1,
2213
2379
  version,
2214
2380
  ...interpreter
2215
2381
  };
@@ -2249,8 +2415,8 @@ async function executeGuardAction(action, resolution, roots, signal, executableI
2249
2415
  const capabilities = await marketCapabilities(roots, signal);
2250
2416
  if (!capabilities || !roots.marketOrigin || !resolutionCallId || !agent) return { status: "unavailable" };
2251
2417
  if (!sameMarketProvider(target.pre_generation, capabilities.generation)) return { status: "unavailable" };
2252
- if (capabilities.generation !== target.pre_generation) return restartIntent(snapshotSessionEvents(agent.session), resolutionCallId, target) ? { status: "completed" } : { status: "unavailable" };
2253
- if (restartIntent(snapshotSessionEvents(agent.session), resolutionCallId, target)) return { status: "handoff_pending" };
2418
+ if (capabilities.generation !== target.pre_generation) return roots.hasRestartIntent?.(resolutionCallId, String(target.service_id), String(target.pre_generation)) || restartIntent(snapshotSessionEvents(agent.session), resolutionCallId, target) ? { status: "completed" } : { status: "unavailable" };
2419
+ if (roots.hasRestartIntent?.(resolutionCallId, String(target.service_id), String(target.pre_generation)) || restartIntent(snapshotSessionEvents(agent.session), resolutionCallId, target)) return { status: "handoff_pending" };
2254
2420
  if (!roots.persistRestartIntent || !await roots.persistRestartIntent(agent, {
2255
2421
  resolutionCallId,
2256
2422
  serviceId: String(target.service_id),
@@ -2268,7 +2434,7 @@ async function executeGuardAction(action, resolution, roots, signal, executableI
2268
2434
  body: "{}"
2269
2435
  });
2270
2436
  if (!response.ok) return { status: "unavailable" };
2271
- return record(await response.json())?.schema === MARKET_SCHEMA ? { status: "handoff_pending" } : { status: "unavailable" };
2437
+ return record$1(await response.json())?.schema === MARKET_SCHEMA ? { status: "handoff_pending" } : { status: "unavailable" };
2272
2438
  }
2273
2439
  if (action === "commit" || action === "push" || action === "pull" || action === "fetch") {
2274
2440
  const binding = resolution.gitBinding;
@@ -2321,7 +2487,7 @@ async function executeGuardAction(action, resolution, roots, signal, executableI
2321
2487
  return { status: "unavailable" };
2322
2488
  }
2323
2489
  async function gitBytes(repository, args, signal, file = "git") {
2324
- const { stdout } = await execFileAsync(file, args, {
2490
+ const { stdout } = await execFileAsync$1(file, args, {
2325
2491
  cwd: repository,
2326
2492
  encoding: "buffer",
2327
2493
  signal,
@@ -2441,12 +2607,12 @@ function pickTarget(target, keys) {
2441
2607
  async function expectedTransitionForResolution(action, target, commandManifest) {
2442
2608
  let parameters;
2443
2609
  if (action === "create") {
2444
- const plannedArguments = record(commandManifest.planned_arguments);
2610
+ const plannedArguments = record$1(commandManifest.planned_arguments);
2445
2611
  const content = typeof plannedArguments?.content === "string" ? plannedArguments.content : void 0;
2446
2612
  if (content === void 0) return void 0;
2447
2613
  parameters = { post_digest: createHash("sha256").update(Buffer.from(content, "utf8")).digest("hex") };
2448
2614
  } else if (action === "modify") {
2449
- const plannedArguments = record(commandManifest.planned_arguments);
2615
+ const plannedArguments = record$1(commandManifest.planned_arguments);
2450
2616
  const oldString = requireString(plannedArguments ?? {}, "old_string");
2451
2617
  const newString = typeof plannedArguments?.new_string === "string" ? plannedArguments.new_string : void 0;
2452
2618
  const artifact = typeof target.artifact_id === "string" ? target.artifact_id : void 0;
@@ -2523,8 +2689,8 @@ async function resolveTarget(action, selector, commandManifest, cwd, roots, sign
2523
2689
  const service = requireString(selector, "service_id");
2524
2690
  if (service !== "dsh-web" || commandManifest.manifest_id !== "dshmarket.restart.v1" || !ACTION_MANIFEST.actions.restart.commandManifestIds.includes("dshmarket.restart.v1") || Object.keys(commandManifest).length !== 1) return void 0;
2525
2691
  const capabilities = await marketCapabilities(roots, signal);
2526
- const features = record(capabilities?.features);
2527
- const restart = record(capabilities?.restart);
2692
+ const features = record$1(capabilities?.features);
2693
+ const restart = record$1(capabilities?.restart);
2528
2694
  if (features?.restart !== true || restart?.supported !== true || restart.managedBy !== "market") return void 0;
2529
2695
  return { target: {
2530
2696
  service_id: service,
@@ -2753,6 +2919,7 @@ function normalizedRoots(options) {
2753
2919
  ...options.fetcher ? { fetcher: options.fetcher } : {},
2754
2920
  ...options.commandRunner ? { commandRunner: options.commandRunner } : {},
2755
2921
  ...options.persistRestartIntent ? { persistRestartIntent: options.persistRestartIntent } : {},
2922
+ ...options.hasRestartIntent ? { hasRestartIntent: options.hasRestartIntent } : {},
2756
2923
  ...options.hostCapability ? { hostCapability: options.hostCapability } : {},
2757
2924
  ...options.authorizeMutation ? { authorizeMutation: options.authorizeMutation } : {},
2758
2925
  ...options.prepareMutation ? { prepareMutation: options.prepareMutation } : {},
@@ -2766,7 +2933,7 @@ function createActionTool(options = {}) {
2766
2933
  const roots = normalizedRoots(options);
2767
2934
  return defineTool({
2768
2935
  name: ACTION_TOOL,
2769
- description: "Execute one explicit Guard-owned mutation after re-reading a persisted resolution and exact target digest. This tool changes package, Git, registry, or Web service state; its result echoes the bounded target and command-manifest digest.",
2936
+ description: "Compatibility entry for older sessions. Ordinary mutations return a migration diagnosis without side effects; only an explicitly adopted registry publication can use the controlled release path.",
2770
2937
  parameters: {
2771
2938
  semantic_action: {
2772
2939
  type: "string",
@@ -2854,6 +3021,11 @@ function createActionTool(options = {}) {
2854
3021
  target_digest: "",
2855
3022
  command_manifest_digest: ""
2856
3023
  };
3024
+ if (action !== "publish") return {
3025
+ status: "unavailable",
3026
+ reason_code: "ordinary_action_migrated_to_host_tools",
3027
+ ...empty
3028
+ };
2857
3029
  if (!agent || ![
2858
3030
  "install",
2859
3031
  "apply",
@@ -3022,7 +3194,7 @@ function createEvidenceTool(options = {}) {
3022
3194
  const roots = normalizedRoots(options);
3023
3195
  return defineTool({
3024
3196
  name: PRODUCER_TOOL,
3025
- description: "Create one trusted stateful resolution/effect/state fact from the live resource and persisted DSH tool events. Unsupported adapters fail closed.",
3197
+ description: "Observe a controlled registry publish. Ordinary work uses native host tools and read-only observers; older producer calls return migration diagnostics.",
3026
3198
  parameters: {
3027
3199
  semantic_action: {
3028
3200
  type: "string",
@@ -3228,6 +3400,17 @@ function createEvidenceTool(options = {}) {
3228
3400
  async execute(args, exec) {
3229
3401
  const action = args.semantic_action;
3230
3402
  const role = args.evidence_role;
3403
+ if ([
3404
+ "install",
3405
+ "apply",
3406
+ "create",
3407
+ "modify",
3408
+ "restart",
3409
+ "commit",
3410
+ "push",
3411
+ "pull",
3412
+ "fetch"
3413
+ ].includes(action)) return unavailable(action, role, "ordinary_evidence_migrated_to_host_facts", void 0, "Use the native host tool and its persisted result; request only a read-only Guard observer when an independent state fact is needed. Do not repeat an earlier effect.");
3231
3414
  if (!SUPPORTED.includes(action)) return unavailable(action, role, "adapter_unavailable_for_pinned_host");
3232
3415
  if (roots.hostCapability?.(action).status !== "supported" && roots.hostCapability) return unavailable(action, role, "host_capability_unavailable");
3233
3416
  const agent = exec.agent;
@@ -3236,9 +3419,9 @@ function createEvidenceTool(options = {}) {
3236
3419
  if (role === "resolution") {
3237
3420
  const recipe = actionPreparation(action);
3238
3421
  {
3239
- const manifest = record(args.command_manifest);
3240
- const plannedArgs = record(manifest?.planned_arguments);
3241
- const selector = record(args.selector);
3422
+ const manifest = record$1(args.command_manifest);
3423
+ const plannedArgs = record$1(manifest?.planned_arguments);
3424
+ const selector = record$1(args.selector);
3242
3425
  const needsManifestId = [
3243
3426
  "install",
3244
3427
  "apply",
@@ -3258,10 +3441,10 @@ function createEvidenceTool(options = {}) {
3258
3441
  const executable$1 = executableFor(action);
3259
3442
  const executableBinding = executable$1 ? await (roots.readExecutableIdentity ?? executableIdentity)(executable$1, exec.signal) : void 0;
3260
3443
  if (executable$1 && !executableBinding) return unavailable(action, role, "executable_identity_unavailable");
3261
- const resolved = await resolveTarget(action, record(args.selector) ?? {}, record(args.command_manifest) ?? {}, cwdOf(agent), roots, exec.signal, executableBinding);
3444
+ const resolved = await resolveTarget(action, record$1(args.selector) ?? {}, record$1(args.command_manifest) ?? {}, cwdOf(agent), roots, exec.signal, executableBinding);
3262
3445
  if (!resolved) return unavailable(action, role, action === "restart" && !roots.verifyMarketInstance ? "market_instance_binding_unavailable" : "resolution_unavailable");
3263
3446
  const gitBinding = resolved.gitBinding ? JSON.parse(JSON.stringify(resolved.gitBinding)) : void 0;
3264
- const commandManifest = record(args.command_manifest) ?? {};
3447
+ const commandManifest = record$1(args.command_manifest) ?? {};
3265
3448
  const expectedTransition = await expectedTransitionForResolution(action, resolved.target, commandManifest);
3266
3449
  if (!expectedTransition) return unavailable(action, role, "expected_transition_unavailable");
3267
3450
  return supported(action, role, resolved.target, {}, commandManifest, gitBinding, executableBinding, expectedTransition);
@@ -3353,21 +3536,27 @@ function createReleaseTool(options) {
3353
3536
  operations: releaseCoverage(contract$1),
3354
3537
  candidate: contract$1.candidate
3355
3538
  })),
3356
- reservations: projection.releaseReservations.map(({ contractId: contractId$1, operation: operation$1, callId: callId$1, startedAtSeq, observedArtifactSri }) => ({
3539
+ reservations: projection.releaseReservations.map(({ contractId: contractId$1, operation: operation$1, callId: callId$1, startedAtSeq, ledgerPosition, observedArtifactSri }) => ({
3357
3540
  contract_id: contractId$1,
3358
3541
  operation: operation$1,
3359
3542
  resolution_call_id: callId$1,
3360
- started_at_seq: startedAtSeq,
3543
+ ...ledgerPosition === void 0 ? { started_at_seq: startedAtSeq } : { record_position: {
3544
+ channel: "private_ledger",
3545
+ position: ledgerPosition
3546
+ } },
3361
3547
  observed_artifact_sri: observedArtifactSri ?? null,
3362
3548
  in_flight: inFlightReservation(projection, contractId$1, operation$1)?.callId === callId$1
3363
3549
  })),
3364
- settlements: projection.releaseSettlements.map(({ contractId: contractId$1, operation: operation$1, callId: callId$1, outcome: outcome$1, readback: readback$2, settledAtSeq }) => ({
3550
+ settlements: projection.releaseSettlements.map(({ contractId: contractId$1, operation: operation$1, callId: callId$1, outcome: outcome$1, readback: readback$2, settledAtSeq, ledgerPosition }) => ({
3365
3551
  contract_id: contractId$1,
3366
3552
  operation: operation$1,
3367
3553
  resolution_call_id: callId$1,
3368
3554
  outcome: outcome$1,
3369
3555
  readback: readback$2,
3370
- settled_at_seq: settledAtSeq
3556
+ ...ledgerPosition === void 0 ? { settled_at_seq: settledAtSeq } : { record_position: {
3557
+ channel: "private_ledger",
3558
+ position: ledgerPosition
3559
+ } }
3371
3560
  })),
3372
3561
  diagnostics: projection.releaseDiagnostics
3373
3562
  };
@@ -3434,6 +3623,518 @@ function createReleaseTool(options) {
3434
3623
  });
3435
3624
  }
3436
3625
 
3626
+ //#endregion
3627
+ //#region src/tools/observe.ts
3628
+ const execFileAsync = promisify(execFile);
3629
+ const record = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
3630
+ /** Read-only, post-effect file observer. The path comes from a persisted native edit call. */
3631
+ function createNativeFileObserver(host) {
3632
+ return defineTool({
3633
+ name: "context_guard_observe_file",
3634
+ description: "Read back the exact UTF-8 file after an already persisted native write or edit. This tool does not modify files or authorize the edit.",
3635
+ parameters: { effect_call_id: {
3636
+ type: "string",
3637
+ required: true
3638
+ } },
3639
+ output: {
3640
+ schema: {
3641
+ type: "object",
3642
+ additionalProperties: false,
3643
+ properties: {
3644
+ status: {
3645
+ type: "string",
3646
+ required: true,
3647
+ enum: ["observed", "unavailable"]
3648
+ },
3649
+ reason_code: {
3650
+ type: "string",
3651
+ required: true
3652
+ },
3653
+ effect_call_id: {
3654
+ type: "string",
3655
+ required: true
3656
+ },
3657
+ path: {
3658
+ type: "string",
3659
+ required: true
3660
+ },
3661
+ sha256: {
3662
+ type: "string",
3663
+ required: true
3664
+ },
3665
+ action: {
3666
+ type: "string",
3667
+ required: true,
3668
+ enum: [
3669
+ "create",
3670
+ "modify",
3671
+ "unknown"
3672
+ ]
3673
+ },
3674
+ canonical_path: { type: "string" },
3675
+ canonical_base: { type: "string" }
3676
+ }
3677
+ },
3678
+ render: (_args, value) => [{
3679
+ type: "text",
3680
+ text: JSON.stringify(value)
3681
+ }],
3682
+ presentationMeta: (_args, value) => value.status === "observed" ? { contextGuardNativeFile: {
3683
+ effectCallId: value.effect_call_id,
3684
+ path: value.path,
3685
+ sha256: value.sha256,
3686
+ action: value.action,
3687
+ ...value.canonical_path ? { canonicalPath: value.canonical_path } : {},
3688
+ ...value.canonical_base ? { canonicalBase: value.canonical_base } : {}
3689
+ } } : { contextGuardNativeFileUnavailable: { reasonCode: value.reason_code } }
3690
+ },
3691
+ async execute(args, exec) {
3692
+ const missing = (reason) => ({
3693
+ status: "unavailable",
3694
+ reason_code: reason,
3695
+ effect_call_id: args.effect_call_id,
3696
+ path: "",
3697
+ sha256: "",
3698
+ action: "unknown"
3699
+ });
3700
+ const agent = exec.agent;
3701
+ if (!agent || !host.fs || !host.flush) return missing("host_fs_unavailable");
3702
+ if (!await host.flush(agent.session)) return missing("native_effect_not_durable");
3703
+ let call;
3704
+ let result;
3705
+ let callSeq = -1;
3706
+ let resultSeq = -1;
3707
+ let duplicate = false;
3708
+ for (const raw of snapshotSessionEvents(agent.session)) {
3709
+ const event = record(raw);
3710
+ const data = record(event?.data);
3711
+ if (event?.type === "tool/call" && data?.callId === args.effect_call_id) {
3712
+ if (call) duplicate = true;
3713
+ call = data;
3714
+ callSeq = Number(event.seq);
3715
+ }
3716
+ if (event?.type === "tool/result" && record(record(data?.message)?.source)?.callId === args.effect_call_id) {
3717
+ if (result) duplicate = true;
3718
+ result = data;
3719
+ resultSeq = Number(event.seq);
3720
+ }
3721
+ }
3722
+ if (!call || !result || duplicate || callSeq >= resultSeq || call.turn !== result.turn || call.step !== result.step || ![
3723
+ "write",
3724
+ "write_file",
3725
+ "edit",
3726
+ "edit_file"
3727
+ ].includes(String(call.name))) return missing("native_effect_missing");
3728
+ const source = record(record(result.message)?.source);
3729
+ if (source?.kind !== "tool" || source.callId !== args.effect_call_id) return missing("native_effect_missing");
3730
+ const resultStatus = persistedToolResultStatus(result, args.effect_call_id);
3731
+ if (resultStatus !== "clean") return missing(resultStatus === "failure" ? "native_effect_failed" : "native_effect_untrusted");
3732
+ let effectArgs;
3733
+ try {
3734
+ effectArgs = record(JSON.parse(String(call.arguments)));
3735
+ } catch {
3736
+ return missing("native_effect_arguments_invalid");
3737
+ }
3738
+ const filePath = effectArgs?.file_path;
3739
+ if (typeof filePath !== "string" || !filePath) return missing("native_effect_target_missing");
3740
+ const action = String(call.name).startsWith("write") ? "create" : "modify";
3741
+ const cwd = record(agent.session.header)?.cwd;
3742
+ try {
3743
+ const target = await host.fs.resolve(filePath, {
3744
+ ...typeof cwd === "string" ? { cwd } : {},
3745
+ signal: exec.signal
3746
+ });
3747
+ const before = await host.fs.stat(target, exec.signal);
3748
+ if (!before || before.type !== "file" || before.size !== void 0 && before.size > 2e7) return missing("native_file_readback_unavailable");
3749
+ const content = await host.fs.readText(target, exec.signal);
3750
+ const after = await host.fs.stat(target, exec.signal);
3751
+ if (!after || after.type !== "file" || before.version !== after.version) return missing("native_file_readback_raced");
3752
+ let canonicalPath;
3753
+ let canonicalBase;
3754
+ if (typeof cwd === "string" && host.fs.processPath && host.fs.contains) {
3755
+ const base = await host.fs.resolve(cwd, { signal: exec.signal });
3756
+ const path = host.fs.processPath(target);
3757
+ const root = host.fs.processPath(base);
3758
+ const absoluteFlavor = (value) => value.startsWith("/") && !value.startsWith("//") && !value.includes("\\") && posix.normalize(value) === value ? "posix" : /^[A-Za-z]:\\/.test(value) && !value.includes("/") && !value.slice(3).includes("\\\\") && !value.slice(3).includes(":") && !value.split("\\").some((part) => part === "." || part === "..") ? "windows" : void 0;
3759
+ if (host.fs.contains(base, target) && absoluteFlavor(path) && absoluteFlavor(path) === absoluteFlavor(root)) {
3760
+ canonicalPath = path;
3761
+ canonicalBase = root;
3762
+ }
3763
+ }
3764
+ return {
3765
+ status: "observed",
3766
+ reason_code: "file_state_observed",
3767
+ effect_call_id: args.effect_call_id,
3768
+ path: target.displayPath,
3769
+ sha256: createHash("sha256").update(content, "utf8").digest("hex"),
3770
+ action,
3771
+ ...canonicalPath && canonicalBase ? {
3772
+ canonical_path: canonicalPath,
3773
+ canonical_base: canonicalBase
3774
+ } : {}
3775
+ };
3776
+ } catch {
3777
+ return missing("native_file_readback_unavailable");
3778
+ }
3779
+ }
3780
+ });
3781
+ }
3782
+ /** Fixed-argv Git readback for a persisted native shell commit/push result. */
3783
+ function createNativeGitObserver(host) {
3784
+ return defineTool({
3785
+ name: "context_guard_observe_git",
3786
+ description: "Read back a repository after a persisted native Git command; performs only fixed Git queries.",
3787
+ parameters: { effect_call_id: {
3788
+ type: "string",
3789
+ required: true
3790
+ } },
3791
+ output: {
3792
+ schema: {
3793
+ type: "object",
3794
+ additionalProperties: false,
3795
+ properties: {
3796
+ status: {
3797
+ type: "string",
3798
+ required: true,
3799
+ enum: ["observed", "unavailable"]
3800
+ },
3801
+ reason_code: {
3802
+ type: "string",
3803
+ required: true
3804
+ },
3805
+ effect_call_id: {
3806
+ type: "string",
3807
+ required: true
3808
+ },
3809
+ action: {
3810
+ type: "string",
3811
+ required: true,
3812
+ enum: [
3813
+ "commit",
3814
+ "push",
3815
+ "unknown"
3816
+ ]
3817
+ },
3818
+ repository: {
3819
+ type: "string",
3820
+ required: true
3821
+ },
3822
+ branch: {
3823
+ type: "string",
3824
+ required: true
3825
+ },
3826
+ remote: {
3827
+ type: "string",
3828
+ required: true
3829
+ },
3830
+ refspec: {
3831
+ type: "string",
3832
+ required: true
3833
+ },
3834
+ post_oid: {
3835
+ type: "string",
3836
+ required: true
3837
+ },
3838
+ parent_oid: {
3839
+ type: "string",
3840
+ required: true
3841
+ },
3842
+ tree_oid: {
3843
+ type: "string",
3844
+ required: true
3845
+ }
3846
+ }
3847
+ },
3848
+ render: (_args, value) => [{
3849
+ type: "text",
3850
+ text: JSON.stringify(value)
3851
+ }],
3852
+ presentationMeta: (_args, value) => value.status === "observed" ? { contextGuardNativeGit: {
3853
+ effectCallId: value.effect_call_id,
3854
+ action: value.action,
3855
+ repository: value.repository,
3856
+ branch: value.branch,
3857
+ remote: value.remote,
3858
+ refspec: value.refspec,
3859
+ postOid: value.post_oid,
3860
+ parentOid: value.parent_oid,
3861
+ treeOid: value.tree_oid
3862
+ } } : { contextGuardNativeGitUnavailable: { reasonCode: value.reason_code } }
3863
+ },
3864
+ async execute(args, exec) {
3865
+ const missing = (reason) => ({
3866
+ status: "unavailable",
3867
+ reason_code: reason,
3868
+ effect_call_id: args.effect_call_id,
3869
+ action: "unknown",
3870
+ repository: "",
3871
+ branch: "",
3872
+ remote: "",
3873
+ refspec: "",
3874
+ post_oid: "",
3875
+ parent_oid: "",
3876
+ tree_oid: ""
3877
+ });
3878
+ const session = exec.agent?.session;
3879
+ if (!session || !host.flush || !await host.flush(session)) return missing("native_effect_not_durable");
3880
+ let call;
3881
+ let result;
3882
+ let callSeq = -1;
3883
+ let resultSeq = -1;
3884
+ let duplicate = false;
3885
+ for (const raw of snapshotSessionEvents(session)) {
3886
+ const event = record(raw);
3887
+ const data = record(event?.data);
3888
+ if (event?.type === "tool/call" && data?.callId === args.effect_call_id) {
3889
+ if (call) duplicate = true;
3890
+ call = data;
3891
+ callSeq = Number(event.seq);
3892
+ }
3893
+ if (event?.type === "tool/result" && record(record(data?.message)?.source)?.callId === args.effect_call_id) {
3894
+ if (result) duplicate = true;
3895
+ result = data;
3896
+ resultSeq = Number(event.seq);
3897
+ }
3898
+ }
3899
+ if (!call || !result || duplicate || callSeq >= resultSeq || call.turn !== result.turn || call.step !== result.step || call.name !== "bash" && call.name !== "pwsh") return missing("native_effect_missing");
3900
+ const message = record(result.message);
3901
+ const source = record(message?.source);
3902
+ if (source?.kind !== "tool" || source.callId !== args.effect_call_id) return missing("native_effect_missing");
3903
+ const resultStatus = persistedToolResultStatus(result, args.effect_call_id);
3904
+ if (resultStatus !== "clean") return missing(resultStatus === "failure" ? "native_effect_failed" : "native_effect_untrusted");
3905
+ let effectArgs;
3906
+ try {
3907
+ effectArgs = record(JSON.parse(String(call.arguments)));
3908
+ } catch {
3909
+ return missing("native_effect_arguments_invalid");
3910
+ }
3911
+ const command = effectArgs?.command;
3912
+ const repository = effectArgs?.workdir;
3913
+ if (typeof command !== "string" || typeof repository !== "string" || !repository) return missing("native_git_target_missing");
3914
+ const parsed = canonicalArgvFromCommand(command, call.name);
3915
+ const argv = parsed.argv;
3916
+ if (parsed.status !== "supported" || argv[0] !== "git") return missing("native_git_command_unsupported");
3917
+ const action = argv[1];
3918
+ if (action !== "commit" && action !== "push") return missing("native_git_command_unsupported");
3919
+ const gitAction = action;
3920
+ const output = Array.isArray(message?.content) ? extractTextContent(message.content) : "";
3921
+ const git$1 = async (...query) => (await execFileAsync("git", [
3922
+ "-C",
3923
+ repository,
3924
+ ...query
3925
+ ], {
3926
+ encoding: "utf8",
3927
+ timeout: 5e3,
3928
+ maxBuffer: 1024 * 1024
3929
+ })).stdout.trim();
3930
+ try {
3931
+ const top = await git$1("rev-parse", "--show-toplevel");
3932
+ if (!top || await realpath(top) !== await realpath(repository)) return missing("native_git_repository_mismatch");
3933
+ const observedRepository = repository;
3934
+ const branch = await git$1("symbolic-ref", "--short", "HEAD");
3935
+ const postOid = await git$1("rev-parse", "HEAD");
3936
+ if (!/^[0-9a-f]{40,64}$/.test(postOid)) return missing("native_git_readback_unavailable");
3937
+ if (action === "commit") {
3938
+ if (argv.length !== 4 || argv[2] !== "-m" || !argv[3] || !(/* @__PURE__ */ new RegExp(`\\b${postOid.slice(0, 7)}[0-9a-f]*\\b`)).test(output)) return missing("native_git_effect_output_unbound");
3939
+ const parentOid = await git$1("rev-parse", "HEAD^");
3940
+ const treeOid = await git$1("rev-parse", "HEAD^{tree}");
3941
+ return {
3942
+ status: "observed",
3943
+ reason_code: "git_commit_observed",
3944
+ effect_call_id: args.effect_call_id,
3945
+ action: gitAction,
3946
+ repository: observedRepository,
3947
+ branch,
3948
+ remote: "",
3949
+ refspec: "",
3950
+ post_oid: postOid,
3951
+ parent_oid: parentOid,
3952
+ tree_oid: treeOid
3953
+ };
3954
+ }
3955
+ const remote = argv[2];
3956
+ const refspec = argv[3];
3957
+ if (argv.length !== 4 || !remote || !/^refs\/heads\/[^:]+:refs\/heads\/[^:]+$/.test(refspec)) return missing("native_git_refspec_unsupported");
3958
+ const [src, dst] = refspec.split(":");
3959
+ const localOid = await git$1("rev-parse", src);
3960
+ const remoteOid = (await git$1("ls-remote", "--exit-code", remote, dst)).split(/\s+/)[0];
3961
+ const destinationName = dst.slice(11);
3962
+ const reportedUpdate = output.includes(localOid.slice(0, 7)) || output.includes("[new branch]") && output.includes(`-> ${destinationName}`);
3963
+ if (remoteOid !== localOid || !reportedUpdate) return missing("native_git_push_readback_mismatch");
3964
+ return {
3965
+ status: "observed",
3966
+ reason_code: "git_push_observed",
3967
+ effect_call_id: args.effect_call_id,
3968
+ action: gitAction,
3969
+ repository: observedRepository,
3970
+ branch,
3971
+ remote,
3972
+ refspec,
3973
+ post_oid: remoteOid,
3974
+ parent_oid: "",
3975
+ tree_oid: ""
3976
+ };
3977
+ } catch {
3978
+ return missing("native_git_readback_unavailable");
3979
+ }
3980
+ }
3981
+ });
3982
+ }
3983
+ /** Specific package-script readiness, with a stable changed input for an
3984
+ * assessment. The observer never executes the script or infers success. */
3985
+ function createTestReadinessObserver(host) {
3986
+ return defineTool({
3987
+ name: "context_guard_observe_test_readiness",
3988
+ description: "Read a pending test or assessment script and its concrete inputs; never runs the script.",
3989
+ parameters: { item_id: {
3990
+ type: "string",
3991
+ required: true
3992
+ } },
3993
+ output: {
3994
+ schema: {
3995
+ type: "object",
3996
+ additionalProperties: false,
3997
+ properties: {
3998
+ status: {
3999
+ type: "string",
4000
+ required: true,
4001
+ enum: ["ready", "unavailable"]
4002
+ },
4003
+ reason_code: {
4004
+ type: "string",
4005
+ required: true
4006
+ },
4007
+ item_id: {
4008
+ type: "string",
4009
+ required: true
4010
+ },
4011
+ scope: {
4012
+ type: "string",
4013
+ required: true
4014
+ },
4015
+ manifest_sha256: {
4016
+ type: "string",
4017
+ required: true
4018
+ },
4019
+ predicate: {
4020
+ type: "string",
4021
+ required: true
4022
+ },
4023
+ script_name: {
4024
+ type: "string",
4025
+ required: true
4026
+ },
4027
+ selected_path: {
4028
+ type: "string",
4029
+ required: true
4030
+ },
4031
+ effect_call_id: {
4032
+ type: "string",
4033
+ required: true
4034
+ },
4035
+ input_sha256: {
4036
+ type: "string",
4037
+ required: true
4038
+ }
4039
+ }
4040
+ },
4041
+ render: (_args, value) => [{
4042
+ type: "text",
4043
+ text: JSON.stringify(value)
4044
+ }],
4045
+ presentationMeta: (_args, value) => value.status === "ready" ? { contextGuardTestReadiness: {
4046
+ itemId: value.item_id,
4047
+ scope: value.scope,
4048
+ manifestSha256: value.manifest_sha256,
4049
+ predicate: value.predicate,
4050
+ scriptName: value.script_name,
4051
+ selectedPath: value.selected_path,
4052
+ effectCallId: value.effect_call_id,
4053
+ inputSha256: value.input_sha256
4054
+ } } : { contextGuardTestReadinessUnavailable: { reasonCode: value.reason_code } }
4055
+ },
4056
+ async execute(args, exec) {
4057
+ const missing = (reason) => ({
4058
+ status: "unavailable",
4059
+ reason_code: reason,
4060
+ item_id: args.item_id,
4061
+ scope: "",
4062
+ manifest_sha256: "",
4063
+ predicate: "",
4064
+ script_name: "",
4065
+ selected_path: "",
4066
+ effect_call_id: "",
4067
+ input_sha256: ""
4068
+ });
4069
+ if (!exec.agent?.session || !host.flush || !host.fs || !await host.flush(exec.agent.session)) return missing("readiness_host_unavailable");
4070
+ const projection = host.getProjection();
4071
+ const item = projection?.items.get(args.item_id);
4072
+ if (!item || item.status !== "pending" || !["test", "verify"].includes(item.semanticAction ?? "") || item.authority !== "root_instruction" || item.authorityDisposition !== "executable_now" || item.legacyFlags?.length || item.waitAuthorization || item.condition || typeof item.requestedTarget?.scope !== "string") return missing("readiness_item_unsupported");
4073
+ const scope = item.requestedTarget.scope;
4074
+ const assessment = item.semanticAction === "verify";
4075
+ if (typeof item.requestedTarget.script_name === "string") return missing("readiness_script_capability_unavailable");
4076
+ const scriptName = assessment && /(?:吞吐|性能|时延|延迟|throughput|performance|latency)/iu.test(item.normalizedText) ? "benchmark" : "test";
4077
+ let selectedPath = "", effectCallId = "", inputSha256 = "";
4078
+ if (assessment) {
4079
+ const unitStart = item.unitId ? projection?.units.get(item.unitId)?.openedAtSeq : void 0;
4080
+ if (unitStart === void 0) return missing("assessment_unit_unavailable");
4081
+ const changes = [...projection?.evidence.values() ?? []].filter((fact) => fact.epoch === projection?.epoch && fact.toolResultSeq >= unitStart && fact.outcome === "success" && fact.parseStatus === "supported" && fact.semanticAction === "modify" && fact.evidenceRole === "effect").flatMap((fact) => (fact.operations ?? []).filter((op) => op.op === "modify" && typeof op.path === "string").map((op) => ({
4082
+ path: op.path,
4083
+ callId: fact.callId
4084
+ })));
4085
+ const paths = [...new Set(changes.map((change) => change.path))];
4086
+ if (paths.length > 1) return missing("assessment_input_ambiguous");
4087
+ if (paths.length === 1) {
4088
+ const change = changes.find((entry) => entry.path === paths[0]);
4089
+ selectedPath = change.path;
4090
+ effectCallId = change.callId;
4091
+ try {
4092
+ const changed = await host.fs.resolve(selectedPath, { signal: exec.signal });
4093
+ const before = await host.fs.stat(changed, exec.signal);
4094
+ if (!before || before.type !== "file" || before.size !== void 0 && before.size > 2e7) return missing("assessment_input_unavailable");
4095
+ const raw = await host.fs.readText(changed, exec.signal);
4096
+ const after = await host.fs.stat(changed, exec.signal);
4097
+ if (!after || after.type !== "file" || before.version !== after.version) return missing("assessment_input_raced");
4098
+ inputSha256 = createHash("sha256").update(raw, "utf8").digest("hex");
4099
+ } catch {
4100
+ return missing("assessment_input_unavailable");
4101
+ }
4102
+ }
4103
+ }
4104
+ try {
4105
+ if (/^[A-Za-z]:/.test(scope) && (!/^[A-Za-z]:\\/.test(scope) || scope.includes("/"))) return missing("readiness_scope_unavailable");
4106
+ const manifestPath = /^[A-Za-z]:\\/.test(scope) ? win32.join(scope, "package.json") : posix.join(scope, "package.json");
4107
+ const target = await host.fs.resolve(manifestPath, { signal: exec.signal });
4108
+ const before = await host.fs.stat(target, exec.signal);
4109
+ if (!before || before.type !== "file" || before.size !== void 0 && before.size > 2e6) return missing("readiness_manifest_unavailable");
4110
+ const raw = await host.fs.readText(target, exec.signal);
4111
+ const after = await host.fs.stat(target, exec.signal);
4112
+ if (!after || after.type !== "file" || before.version !== after.version) return missing("readiness_manifest_raced");
4113
+ const manifest = record(JSON.parse(raw));
4114
+ if (typeof record(manifest?.scripts)?.[scriptName] !== "string" || !String(record(manifest?.scripts)?.[scriptName]).trim()) return missing("readiness_script_missing");
4115
+ if (assessment && !selectedPath) {
4116
+ selectedPath = target.displayPath;
4117
+ inputSha256 = createHash("sha256").update(raw, "utf8").digest("hex");
4118
+ }
4119
+ return {
4120
+ status: "ready",
4121
+ reason_code: assessment ? "assessment_inputs_ready" : "package_test_script_ready",
4122
+ item_id: args.item_id,
4123
+ scope,
4124
+ manifest_sha256: createHash("sha256").update(raw, "utf8").digest("hex"),
4125
+ predicate: assessment ? "verification_passed" : "test_passed",
4126
+ script_name: scriptName,
4127
+ selected_path: selectedPath,
4128
+ effect_call_id: effectCallId,
4129
+ input_sha256: inputSha256
4130
+ };
4131
+ } catch {
4132
+ return missing("readiness_manifest_unavailable");
4133
+ }
4134
+ }
4135
+ });
4136
+ }
4137
+
3437
4138
  //#endregion
3438
4139
  //#region src/tools/external-operation.ts
3439
4140
  function createExternalOperationTool(read, capability) {
@@ -3525,14 +4226,17 @@ const PRESERVED_DIGEST_DOMAINS = [
3525
4226
  "ccg.proofManifest.v1"
3526
4227
  ];
3527
4228
  function migrationReport(projection) {
3528
- const v5 = projection.boundaryProtocol === 5;
4229
+ const v6 = projection.boundaryProtocol === 6;
4230
+ const v5 = projection.boundaryProtocol !== void 0 && projection.boundaryProtocol >= 5;
3529
4231
  const legacyItemIds = certifiableOpenItems(projection).filter((item) => item.unitId === void 0).map((item) => item.id);
3530
4232
  const closure = v5 ? certificateClosure(projection) : { itemIds: [] };
3531
4233
  const reasonCodes = [];
3532
4234
  if (!v5) reasonCodes.push("legacy_session_keeps_v4_contract");
3533
4235
  if (v5 && legacyItemIds.length > 0) reasonCodes.push("pre_v5_obligations_retained_in_closure");
4236
+ if (v6) reasonCodes.push("v6_ordinary_host_facts_and_legacy_review");
4237
+ if (v6 && projection.coreV2Reason) reasonCodes.push(`core_v2_${projection.coreV2Reason}`);
3534
4238
  return {
3535
- ruleMode: v5 ? "v5" : "legacy-v4",
4239
+ ruleMode: v6 ? "v6" : v5 ? "v5" : "legacy-v4",
3536
4240
  certificateVersion: v5 ? CERTIFICATE_VERSION_V2 : CERTIFICATE_VERSION,
3537
4241
  stopProtocolVersion: v5 ? STOP_PROTOCOL_VERSION_V2 : STOP_PROTOCOL_VERSION,
3538
4242
  unitClosure: v5,
@@ -3542,7 +4246,7 @@ function migrationReport(projection) {
3542
4246
  preservedDigestDomains: [...PRESERVED_DIGEST_DOMAINS],
3543
4247
  historyOnlyCertificateVersions: v5 ? [CERTIFICATE_VERSION] : [],
3544
4248
  rollbackRequiresStateSnapshot: v5,
3545
- 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.",
4249
+ rollbackInstruction: v6 ? "Restore a pre-v6 state snapshot before running 0.6.x. The v6 boundary, native-observation digest and migration review must not be read as v5 current authority or downgraded by hand." : 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.",
3546
4250
  reasonCodes
3547
4251
  };
3548
4252
  }
@@ -3636,17 +4340,23 @@ function releaseResponse(projection, rawInput) {
3636
4340
  operations: releaseCoverage(contract),
3637
4341
  expires_at_epoch_ms: contract.expiresAtEpochMs ?? null,
3638
4342
  consumed_operations: projection.releaseSettlements.filter((settlement) => settlement.contractId === contract.contractId && settlement.outcome === "settled").map((settlement) => settlement.operation),
3639
- 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 }) => ({
4343
+ 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, ledgerPosition }) => ({
3640
4344
  operation,
3641
4345
  call_id: callId,
3642
- started_at_seq: startedAtSeq
4346
+ ...ledgerPosition === void 0 ? { started_at_seq: startedAtSeq } : { record_position: {
4347
+ channel: "private_ledger",
4348
+ position: ledgerPosition
4349
+ } }
3643
4350
  })),
3644
- settlements: projection.releaseSettlements.filter((settlement) => settlement.contractId === contract.contractId).map(({ operation, callId, outcome, readback: readback$1, settledAtSeq }) => ({
4351
+ settlements: projection.releaseSettlements.filter((settlement) => settlement.contractId === contract.contractId).map(({ operation, callId, outcome, readback: readback$1, settledAtSeq, ledgerPosition }) => ({
3645
4352
  operation,
3646
4353
  call_id: callId,
3647
4354
  outcome,
3648
4355
  readback: readback$1,
3649
- settled_at_seq: settledAtSeq
4356
+ ...ledgerPosition === void 0 ? { settled_at_seq: settledAtSeq } : { record_position: {
4357
+ channel: "private_ledger",
4358
+ position: ledgerPosition
4359
+ } }
3650
4360
  }))
3651
4361
  }));
3652
4362
  return {
@@ -4628,10 +5338,385 @@ function resolveConfig(config) {
4628
5338
  };
4629
5339
  }
4630
5340
 
5341
+ //#endregion
5342
+ //#region src/domain/private-ledger.ts
5343
+ const normalizeContext = (value) => typeof value === "string" ? {
5344
+ sessionId: value,
5345
+ sessionHeader: { id: value },
5346
+ cwd: "/",
5347
+ hostLockDigest: "test-seam"
5348
+ } : value;
5349
+ const canonical = (value) => {
5350
+ if (value === null || typeof value === "boolean" || typeof value === "string") return JSON.stringify(value);
5351
+ if (typeof value === "number") {
5352
+ if (!Number.isFinite(value) || Object.is(value, -0)) throw new TypeError("private_ledger_non_json_number");
5353
+ return JSON.stringify(value);
5354
+ }
5355
+ if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
5356
+ if (value && typeof value === "object") return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`).join(",")}}`;
5357
+ throw new TypeError("private_ledger_non_json_value");
5358
+ };
5359
+ const digestRecord = (record$2) => sha256(canonical(record$2));
5360
+ const sessionDigest = (sessionId) => sha256(`dsh-completion-guard/private-ledger/v1\0${sessionId}`);
5361
+ const contextDigest = (context, root) => sha256(canonical({
5362
+ session_sha256: sessionDigest(context.sessionId),
5363
+ session_header: context.sessionHeader,
5364
+ cwd_sha256: sha256(context.cwd),
5365
+ host_lock_sha256: context.hostLockDigest,
5366
+ ledger_root_sha256: sha256(realpathSync(root))
5367
+ }));
5368
+ const ledgerPath = (root, context) => join(root, `${sessionDigest(context.sessionId)}.jsonl`);
5369
+ const anchorPath = (root) => join(root, "session-anchors.v1.jsonl");
5370
+ const rootLockPath = (root) => join(root, ".writer.lock");
5371
+ const privateLedgerContractDigest = (contract) => {
5372
+ if (!contract || typeof contract !== "object" || Array.isArray(contract)) return sha256(canonical(contract));
5373
+ const { revokedAtSeq: _mutableRevocation,...immutable } = contract;
5374
+ return sha256(canonical(immutable));
5375
+ };
5376
+ const privateLedgerTargetDigest = (target) => sha256(canonical(target));
5377
+ /** Mirrors the audited dsh-home-paths precedence without importing another host package. */
5378
+ function resolvePrivateLedgerRoot(configured, envHome, osHome) {
5379
+ const selected = configured ?? (envHome?.trim() ? envHome : join(osHome, ".dsh"));
5380
+ if (!selected || !osHome) return void 0;
5381
+ return join(resolve(selected === "~" ? osHome : selected.startsWith("~/") || selected.startsWith("~\\") ? join(osHome, selected.slice(2)) : selected), "completion-guard", "private-ledger-v1");
5382
+ }
5383
+ function ensureRoot(root) {
5384
+ if (resolve(root) !== root) throw new Error("private_ledger_root_not_normalized");
5385
+ mkdirSync(root, {
5386
+ recursive: true,
5387
+ mode: 448
5388
+ });
5389
+ const stat = lstatSync(root);
5390
+ if (!stat.isDirectory() || stat.isSymbolicLink()) throw new Error("private_ledger_root_unsafe");
5391
+ }
5392
+ function openRegular(path, flags, mode = 384) {
5393
+ const fd = openSync(path, flags | (process.platform === "win32" ? 0 : constants.O_NOFOLLOW), mode);
5394
+ const stat = fstatSync(fd);
5395
+ if (!stat.isFile()) {
5396
+ closeSync(fd);
5397
+ throw new Error("private_ledger_file_unsafe");
5398
+ }
5399
+ if (process.platform !== "win32" && (stat.mode & 63) !== 0) fchmodSync(fd, 384);
5400
+ return fd;
5401
+ }
5402
+ function writeAll(fd, text) {
5403
+ const bytes = Buffer.from(text);
5404
+ let offset = 0;
5405
+ while (offset < bytes.length) {
5406
+ const written = writeSync(fd, bytes, offset, bytes.length - offset);
5407
+ if (written <= 0) throw new Error("private_ledger_partial_write");
5408
+ offset += written;
5409
+ }
5410
+ }
5411
+ function syncDirectory(root) {
5412
+ if (process.platform === "win32") return;
5413
+ const fd = openSync(root, constants.O_RDONLY);
5414
+ try {
5415
+ fsyncSync(fd);
5416
+ } finally {
5417
+ closeSync(fd);
5418
+ }
5419
+ }
5420
+ function readAnchors(root) {
5421
+ const path = anchorPath(root);
5422
+ if (!existsSync(path)) return /* @__PURE__ */ new Map();
5423
+ const fd = openRegular(path, constants.O_RDONLY);
5424
+ let raw;
5425
+ try {
5426
+ raw = readFileSync(fd, "utf8");
5427
+ } finally {
5428
+ closeSync(fd);
5429
+ }
5430
+ if (raw && !raw.endsWith("\n")) throw new Error("private_ledger_anchor_truncated");
5431
+ const anchors = /* @__PURE__ */ new Map();
5432
+ for (const line of raw.split("\n").filter(Boolean)) {
5433
+ const value = JSON.parse(line);
5434
+ const unsigned = {
5435
+ version: 1,
5436
+ session_sha256: value.session_sha256,
5437
+ context_sha256: value.context_sha256
5438
+ };
5439
+ if (value.version !== 1 || typeof value.session_sha256 !== "string" || typeof value.context_sha256 !== "string" || value.anchor_sha256 !== sha256(canonical(unsigned))) throw new Error("private_ledger_anchor_invalid");
5440
+ const existing = anchors.get(value.session_sha256);
5441
+ if (existing && existing !== value.context_sha256) throw new Error("private_ledger_anchor_conflict");
5442
+ anchors.set(value.session_sha256, value.context_sha256);
5443
+ }
5444
+ return anchors;
5445
+ }
5446
+ function readPrivateLedger(root, input) {
5447
+ if (!root) return {
5448
+ records: [],
5449
+ damaged: true,
5450
+ anchored: false
5451
+ };
5452
+ try {
5453
+ const context = normalizeContext(input);
5454
+ if (!existsSync(root)) return {
5455
+ records: [],
5456
+ damaged: false,
5457
+ anchored: false
5458
+ };
5459
+ const rootStat = lstatSync(root);
5460
+ if (!rootStat.isDirectory() || rootStat.isSymbolicLink()) return {
5461
+ records: [],
5462
+ damaged: true,
5463
+ anchored: false
5464
+ };
5465
+ const session = sessionDigest(context.sessionId);
5466
+ const expectedContext = contextDigest(context, root);
5467
+ const anchored = readAnchors(root).get(session);
5468
+ if (anchored !== void 0 && anchored !== expectedContext) return {
5469
+ records: [],
5470
+ damaged: true,
5471
+ anchored: true
5472
+ };
5473
+ const path = ledgerPath(root, context);
5474
+ if (!existsSync(path)) return {
5475
+ records: [],
5476
+ damaged: anchored !== void 0,
5477
+ anchored: anchored !== void 0
5478
+ };
5479
+ if (anchored === void 0) return {
5480
+ records: [],
5481
+ damaged: true,
5482
+ anchored: false
5483
+ };
5484
+ const fd = openRegular(path, constants.O_RDONLY);
5485
+ let raw;
5486
+ try {
5487
+ raw = readFileSync(fd, "utf8");
5488
+ } finally {
5489
+ closeSync(fd);
5490
+ }
5491
+ if (raw && !raw.endsWith("\n")) return {
5492
+ records: [],
5493
+ damaged: true,
5494
+ anchored: true
5495
+ };
5496
+ const records = [];
5497
+ let prior = null;
5498
+ for (const [index, line] of raw.split("\n").filter(Boolean).entries()) {
5499
+ const value = JSON.parse(line);
5500
+ const { record_sha256,...unsigned } = value;
5501
+ if (value.version !== 1 || value.session_sha256 !== session || value.context_sha256 !== expectedContext || value.position !== index + 1 || value.prior_sha256 !== prior || ![
5502
+ "release_reservation",
5503
+ "release_settlement",
5504
+ "restart_intent"
5505
+ ].includes(value.kind) || !value.payload || typeof value.payload !== "object" || Array.isArray(value.payload) || record_sha256 !== digestRecord(unsigned)) return {
5506
+ records: [],
5507
+ damaged: true,
5508
+ anchored: true
5509
+ };
5510
+ records.push(value);
5511
+ prior = record_sha256;
5512
+ }
5513
+ return {
5514
+ records,
5515
+ damaged: false,
5516
+ anchored: true
5517
+ };
5518
+ } catch {
5519
+ return {
5520
+ records: [],
5521
+ damaged: true,
5522
+ anchored: false
5523
+ };
5524
+ }
5525
+ }
5526
+ /** Establish the provider-invisible anchor when a live runtime observes a new adoption. */
5527
+ function initializePrivateLedger(root, input) {
5528
+ if (!root) return false;
5529
+ let lockFd;
5530
+ try {
5531
+ const context = normalizeContext(input);
5532
+ ensureRoot(root);
5533
+ lockFd = openRegular(rootLockPath(root), constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL);
5534
+ const session = sessionDigest(context.sessionId);
5535
+ const expectedContext = contextDigest(context, root);
5536
+ const anchored = readAnchors(root).get(session);
5537
+ if (anchored !== void 0) return anchored === expectedContext;
5538
+ const unsignedAnchor = {
5539
+ version: 1,
5540
+ session_sha256: session,
5541
+ context_sha256: expectedContext
5542
+ };
5543
+ const fd = openRegular(anchorPath(root), constants.O_WRONLY | constants.O_CREAT | constants.O_APPEND);
5544
+ try {
5545
+ writeAll(fd, `${canonical({
5546
+ ...unsignedAnchor,
5547
+ anchor_sha256: sha256(canonical(unsignedAnchor))
5548
+ })}\n`);
5549
+ fsyncSync(fd);
5550
+ } finally {
5551
+ closeSync(fd);
5552
+ }
5553
+ const ledgerFd = openRegular(ledgerPath(root, context), constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL);
5554
+ try {
5555
+ fsyncSync(ledgerFd);
5556
+ } finally {
5557
+ closeSync(ledgerFd);
5558
+ }
5559
+ syncDirectory(root);
5560
+ return true;
5561
+ } catch {
5562
+ return false;
5563
+ } finally {
5564
+ if (lockFd !== void 0) {
5565
+ try {
5566
+ closeSync(lockFd);
5567
+ } catch {}
5568
+ try {
5569
+ unlinkSync(rootLockPath(root));
5570
+ } catch {}
5571
+ }
5572
+ }
5573
+ }
5574
+ function appendPrivateLedger(root, input, kind, payload) {
5575
+ if (!root) return false;
5576
+ let lockFd;
5577
+ try {
5578
+ const context = normalizeContext(input);
5579
+ ensureRoot(root);
5580
+ lockFd = openRegular(rootLockPath(root), constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL);
5581
+ const session = sessionDigest(context.sessionId);
5582
+ const expectedContext = contextDigest(context, root);
5583
+ const anchored = readAnchors(root).get(session);
5584
+ if (anchored !== void 0 && anchored !== expectedContext) return false;
5585
+ const snapshot = anchored === void 0 ? {
5586
+ records: [],
5587
+ damaged: false
5588
+ } : readPrivateLedger(root, context);
5589
+ if (snapshot.damaged) return false;
5590
+ if (anchored === void 0) {
5591
+ const unsignedAnchor = {
5592
+ version: 1,
5593
+ session_sha256: session,
5594
+ context_sha256: expectedContext
5595
+ };
5596
+ const fd$1 = openRegular(anchorPath(root), constants.O_WRONLY | constants.O_CREAT | constants.O_APPEND);
5597
+ try {
5598
+ writeAll(fd$1, `${canonical({
5599
+ ...unsignedAnchor,
5600
+ anchor_sha256: sha256(canonical(unsignedAnchor))
5601
+ })}\n`);
5602
+ fsyncSync(fd$1);
5603
+ } finally {
5604
+ closeSync(fd$1);
5605
+ }
5606
+ syncDirectory(root);
5607
+ }
5608
+ if (kind === "release_settlement") {
5609
+ const settlement = normalizeSettlement(payload);
5610
+ const reservation = settlement && [...snapshot.records].reverse().find((record$3) => record$3.kind === "release_reservation" && record$3.payload.contractId === settlement.contractId && record$3.payload.operation === settlement.operation && record$3.payload.callId === settlement.callId);
5611
+ if (!reservation) return false;
5612
+ payload = {
5613
+ ...payload,
5614
+ reservation_sha256: reservation.record_sha256,
5615
+ contract_sha256: reservation.payload.contract_sha256,
5616
+ target_sha256: reservation.payload.target_sha256
5617
+ };
5618
+ }
5619
+ const unsigned = {
5620
+ version: 1,
5621
+ session_sha256: session,
5622
+ context_sha256: expectedContext,
5623
+ position: snapshot.records.length + 1,
5624
+ prior_sha256: snapshot.records.at(-1)?.record_sha256 ?? null,
5625
+ kind,
5626
+ payload
5627
+ };
5628
+ const record$2 = {
5629
+ ...unsigned,
5630
+ record_sha256: digestRecord(unsigned)
5631
+ };
5632
+ const fd = openRegular(ledgerPath(root, context), constants.O_WRONLY | constants.O_CREAT | constants.O_APPEND);
5633
+ try {
5634
+ writeAll(fd, `${canonical(record$2)}\n`);
5635
+ fsyncSync(fd);
5636
+ } finally {
5637
+ closeSync(fd);
5638
+ }
5639
+ syncDirectory(root);
5640
+ return true;
5641
+ } catch {
5642
+ return false;
5643
+ } finally {
5644
+ if (lockFd !== void 0) {
5645
+ try {
5646
+ closeSync(lockFd);
5647
+ } catch {}
5648
+ try {
5649
+ unlinkSync(rootLockPath(root));
5650
+ } catch {}
5651
+ }
5652
+ }
5653
+ }
5654
+ function applyPrivateLedger(projection, snapshot) {
5655
+ if (snapshot.damaged || projection.releaseContracts.length > 0 && snapshot.anchored === false) {
5656
+ projection.releaseStateDamaged = true;
5657
+ if (!projection.releaseDiagnostics.some((row) => row.reasonCode === "private_ledger_damaged")) projection.releaseDiagnostics.push({
5658
+ seq: 0,
5659
+ reasonCode: "private_ledger_damaged"
5660
+ });
5661
+ return;
5662
+ }
5663
+ const reservations = /* @__PURE__ */ new Map();
5664
+ for (const record$2 of snapshot.records) if (record$2.kind === "release_reservation") {
5665
+ const normalized = normalizeReservation(record$2.payload);
5666
+ const contract = normalized && projection.releaseContracts.find((entry) => entry.contractId === normalized.contractId);
5667
+ if (!normalized || !contract || record$2.payload.contract_sha256 !== privateLedgerContractDigest(contract) || typeof record$2.payload.target_sha256 !== "string") {
5668
+ projection.releaseStateDamaged = true;
5669
+ continue;
5670
+ }
5671
+ const key = `${normalized.contractId}\0${normalized.operation}\0${normalized.callId}`;
5672
+ if (reservations.has(key)) {
5673
+ projection.releaseStateDamaged = true;
5674
+ continue;
5675
+ }
5676
+ reservations.set(key, record$2);
5677
+ const existing = projection.releaseReservations.find((entry) => entry.callId === normalized.callId);
5678
+ if (existing && (existing.contractId !== normalized.contractId || existing.operation !== normalized.operation)) {
5679
+ projection.releaseStateDamaged = true;
5680
+ continue;
5681
+ }
5682
+ if (!existing) projection.releaseReservations.push({
5683
+ ...normalized,
5684
+ startedAtSeq: 0,
5685
+ ledgerPosition: record$2.position
5686
+ });
5687
+ } else if (record$2.kind === "release_settlement") {
5688
+ const normalized = normalizeSettlement(record$2.payload);
5689
+ const key = normalized && `${normalized.contractId}\0${normalized.operation}\0${normalized.callId}`;
5690
+ const reservationRecord = key ? reservations.get(key) : void 0;
5691
+ const contract = normalized && projection.releaseContracts.find((entry) => entry.contractId === normalized.contractId);
5692
+ const source = record$2.payload.settlement_source;
5693
+ const readbackVerdict = normalized && contract ? readbackSettlesContract(contract, normalized.readback, reservationRecord ? normalizeReservation(reservationRecord.payload)?.observedArtifactSri : void 0) : void 0;
5694
+ if (!normalized || !reservationRecord || !contract || source !== "effect" && source !== "reconcile" || normalized.outcome === "not_effected" && source !== "effect" || source === "reconcile" && normalized.readback === "unavailable" || record$2.payload.reservation_sha256 !== reservationRecord.record_sha256 || record$2.payload.contract_sha256 !== reservationRecord.payload.contract_sha256 || record$2.payload.target_sha256 !== reservationRecord.payload.target_sha256 || normalized.outcome === "settled" && readbackVerdict !== "settled" || source === "reconcile" && readbackVerdict === "mismatch") {
5695
+ projection.releaseStateDamaged = true;
5696
+ continue;
5697
+ }
5698
+ const pinned = {
5699
+ ...normalized,
5700
+ settledAtSeq: 0,
5701
+ ledgerPosition: record$2.position
5702
+ };
5703
+ const index = projection.releaseSettlements.findIndex((entry) => entry.contractId === pinned.contractId && entry.operation === pinned.operation && entry.callId === pinned.callId);
5704
+ if (index < 0) projection.releaseSettlements.push(pinned);
5705
+ else if (OUTCOME_STRENGTH[pinned.outcome] >= OUTCOME_STRENGTH[projection.releaseSettlements[index].outcome]) projection.releaseSettlements[index] = pinned;
5706
+ }
5707
+ }
5708
+ function hasPrivateRestartIntent(snapshot, resolutionCallId, serviceId, preGeneration) {
5709
+ return !snapshot.damaged && snapshot.records.some((record$2) => record$2.kind === "restart_intent" && record$2.payload.resolution_call_id === resolutionCallId && record$2.payload.service_id === serviceId && record$2.payload.pre_generation === preGeneration);
5710
+ }
5711
+
4631
5712
  //#endregion
4632
5713
  //#region src/runtime.ts
4633
5714
  const name = "context-guard";
4634
- const inject = ["sessions", "commands"];
5715
+ const inject = [
5716
+ "sessions",
5717
+ "commands",
5718
+ "fs"
5719
+ ];
4635
5720
  /**
4636
5721
  * Bind an explicit mutation to one live root-owned contract item. Resolution
4637
5722
  * evidence is intentionally not authority: every effect rechecks the current
@@ -4884,13 +5969,13 @@ async function handleGuardTurnStopping(agent, runtime, access$1) {
4884
5969
  }
4885
5970
  return "root_pause_routed";
4886
5971
  }
4887
- const decision = decideTurnBoundary(runtime.projection);
5972
+ const decision = decideTurnBoundary(runtime.projection, rootInstruction?.text);
4888
5973
  if (decision.noProgressClaim) {
4889
- const record$1 = `${NO_PROGRESS_RECORD_PREFIX}${JSON.stringify(decision.noProgressClaim)}`;
5974
+ const record$2 = `${NO_PROGRESS_RECORD_PREFIX}${JSON.stringify(decision.noProgressClaim)}`;
4890
5975
  agent.session.append("user/message", createUserMessage({
4891
5976
  content: [{
4892
5977
  type: "text",
4893
- text: record$1
5978
+ text: record$2
4894
5979
  }],
4895
5980
  source: {
4896
5981
  kind: "plugin",
@@ -5013,7 +6098,7 @@ function sessionHeaderForDigest(session) {
5013
6098
  delegationDepth: typeof raw.delegationDepth === "number" ? raw.delegationDepth : 0
5014
6099
  };
5015
6100
  }
5016
- function createRuntime(agent, config, hostLock = DEFAULT_HOST_LOCK, readGoalState, refreshHostLock) {
6101
+ function createRuntime(agent, config, hostLock = DEFAULT_HOST_LOCK, readGoalState, refreshHostLock, readPrivateRecords, initializePrivateRecords) {
5017
6102
  const projection = createProjection();
5018
6103
  const session = agent.session;
5019
6104
  let pendingRecovery = false;
@@ -5024,11 +6109,14 @@ function createRuntime(agent, config, hostLock = DEFAULT_HOST_LOCK, readGoalStat
5024
6109
  let observedContractRevision = -1;
5025
6110
  let protocolV4Present = false;
5026
6111
  let protocolV5Present = false;
6112
+ let protocolV6Present = false;
5027
6113
  let realRootInputSeen = false;
5028
6114
  let lifecycle = "armed";
6115
+ let synchronizedOnce = false;
5029
6116
  const continuationAttempts = projection.continuationAttempts;
5030
6117
  const persistenceCorrectionAttempts = projection.persistenceCorrectionAttempts;
5031
6118
  const rebuild = () => {
6119
+ const previousReleaseContracts = projection.releaseContracts.length;
5032
6120
  if (refreshHostLock) hostLock = refreshHostLock();
5033
6121
  const header = session.header;
5034
6122
  const priorRecoveryDigest = projection.lastRecoveryDigest;
@@ -5050,6 +6138,18 @@ function createRuntime(agent, config, hostLock = DEFAULT_HOST_LOCK, readGoalStat
5050
6138
  sessionHeader
5051
6139
  }, durabilityConfirmed, hostLock);
5052
6140
  Object.assign(projection, derived.projection);
6141
+ if (readPrivateRecords) {
6142
+ let privateSnapshot = readPrivateRecords();
6143
+ if (!synchronizedOnce && events.length === 0 && !privateSnapshot.damaged && !privateSnapshot.anchored && initializePrivateRecords?.()) privateSnapshot = readPrivateRecords();
6144
+ if (projection.releaseContracts.length > 0 && !privateSnapshot.damaged && !privateSnapshot.anchored) if (synchronizedOnce && previousReleaseContracts === 0 && initializePrivateRecords?.()) privateSnapshot = readPrivateRecords();
6145
+ else privateSnapshot = {
6146
+ records: [],
6147
+ damaged: true,
6148
+ anchored: false
6149
+ };
6150
+ applyPrivateLedger(projection, privateSnapshot);
6151
+ }
6152
+ synchronizedOnce = true;
5053
6153
  if (!sessionHeader) {
5054
6154
  projection.integrity = "unknown";
5055
6155
  if (!projection.integrityViolations.includes("session_ref_unavailable")) projection.integrityViolations.push("session_ref_unavailable");
@@ -5068,8 +6168,19 @@ function createRuntime(agent, config, hostLock = DEFAULT_HOST_LOCK, readGoalStat
5068
6168
  projection.persistenceCorrectionAttempts = persistenceCorrectionAttempts;
5069
6169
  projection.lastRecoveryDigest = priorRecoveryDigest;
5070
6170
  projection.durabilityWatermark = durabilityWatermark;
6171
+ if (projection.boundaryProtocol === 6 && durabilityWatermark === "confirmed") try {
6172
+ const displayOrigins = /* @__PURE__ */ new Map();
6173
+ projection.coreV2 = projectSessionCoreV2(session.snapshotEvents(), projection, displayOrigins);
6174
+ projection.coreV2RequirementOrigins = projection.coreV2 ? displayOrigins : void 0;
6175
+ projection.coreV2Reason = projection.coreV2 ? void 0 : "source_not_projectable";
6176
+ } catch {
6177
+ projection.coreV2 = void 0;
6178
+ projection.coreV2RequirementOrigins = void 0;
6179
+ projection.coreV2Reason = "projection_failed";
6180
+ }
5071
6181
  protocolV4Present = derived.protocolV4Present;
5072
6182
  protocolV5Present = derived.boundaryV5;
6183
+ protocolV6Present = derived.boundaryV6;
5073
6184
  realRootInputSeen = derived.realRootInputSeen;
5074
6185
  lifecycle = lifecyclePhase({
5075
6186
  enabled: projection.enabled,
@@ -5120,6 +6231,9 @@ function createRuntime(agent, config, hostLock = DEFAULT_HOST_LOCK, readGoalStat
5120
6231
  get protocolV5Present() {
5121
6232
  return protocolV5Present;
5122
6233
  },
6234
+ get protocolV6Present() {
6235
+ return protocolV6Present;
6236
+ },
5123
6237
  sync,
5124
6238
  setEnabled,
5125
6239
  setDurability,
@@ -5161,7 +6275,12 @@ function revalidateCoreLock(config, expected) {
5161
6275
  goalAvailable: false,
5162
6276
  reasonCode: "host_lock_installed_graph_drift"
5163
6277
  };
5164
- return actual;
6278
+ const audited = auditedForegroundRenderers(config.hostLockRuntimeRoot, config.hostLockProfileRoot);
6279
+ return audited.length ? {
6280
+ ...actual,
6281
+ auditedForegroundRenderers: audited,
6282
+ digest: createHash("sha256").update(`dsh.core-host-renderer/v1\0${actual.digest}\0${audited.join(",")}`).digest("hex")
6283
+ } : actual;
5165
6284
  } catch {
5166
6285
  return {
5167
6286
  ...expected,
@@ -5171,6 +6290,41 @@ function revalidateCoreLock(config, expected) {
5171
6290
  };
5172
6291
  }
5173
6292
  }
6293
+ /** Observe one actual Host dispatch through Cordis without joining its gate. */
6294
+ function registerPassiveHostWorkdirObserver(agent, hostLockAtCall, attestedRouteAtCall, sourcedRootAtCall) {
6295
+ if (typeof agent.ctx.on !== "function") return;
6296
+ const pending = /* @__PURE__ */ new WeakMap();
6297
+ agent.ctx.on("tools/pre-execute", async (exec, next) => {
6298
+ if (exec.agent === agent && (exec.name === "bash" || exec.name === "pwsh")) try {
6299
+ const policy = agent.ctx.get("sandboxPolicy");
6300
+ const receipt = captureHostWorkdir(agent.session, exec, hostLockAtCall(), policy, await attestedRouteAtCall(exec.name, agent.ctx.get("shell"), policy), sourcedRootAtCall?.(exec) ?? null);
6301
+ if (receipt) pending.set(exec, receipt);
6302
+ } catch {}
6303
+ return next();
6304
+ });
6305
+ agent.ctx.on("tools/post-execute", async (exec, _result, next) => {
6306
+ const decision = await next();
6307
+ const receipt = pending.get(exec);
6308
+ pending.delete(exec);
6309
+ if (!receipt || exec.agent !== agent) return decision;
6310
+ const context = createUserMessage({
6311
+ content: [{
6312
+ type: "text",
6313
+ text: `${HOST_WORKDIR_PREFIX}${JSON.stringify(receipt)}`
6314
+ }],
6315
+ source: {
6316
+ kind: "plugin",
6317
+ plugin: "context-guard",
6318
+ form: "notice",
6319
+ summary: "read-only Host workdir observation"
6320
+ }
6321
+ });
6322
+ return {
6323
+ ...decision,
6324
+ additionalContexts: [...decision.additionalContexts ?? [], context]
6325
+ };
6326
+ });
6327
+ }
5174
6328
  function apply(ctx, rawConfig = {}, seams = {}) {
5175
6329
  const config = resolveConfig(rawConfig);
5176
6330
  const installedHostLock = seams.hostLock ?? evaluateHostLock(config.hostLockPackages ?? [], {
@@ -5178,7 +6332,14 @@ function apply(ctx, rawConfig = {}, seams = {}) {
5178
6332
  profileKind: config.hostLockProfile
5179
6333
  });
5180
6334
  const runtimes = /* @__PURE__ */ new Map();
6335
+ const privateLedgerRoot = seams.privateLedgerRoot ?? resolvePrivateLedgerRoot(void 0, process.env.DSH_HOME, homedir());
5181
6336
  const hostLocks = /* @__PURE__ */ new Map();
6337
+ const ledgerContext = (agent, fallback = installedHostLock) => ({
6338
+ sessionId: String(agent.session.id),
6339
+ sessionHeader: structuredClone(agent.session.header),
6340
+ cwd: sessionCwd(agent.session) ?? "",
6341
+ hostLockDigest: (hostLocks.get(agent) ?? fallback).digest
6342
+ });
5182
6343
  const registeredAgents = /* @__PURE__ */ new WeakSet();
5183
6344
  const ensure = (agent) => {
5184
6345
  let runtime = runtimes.get(agent);
@@ -5190,7 +6351,7 @@ function apply(ctx, rawConfig = {}, seams = {}) {
5190
6351
  return current;
5191
6352
  };
5192
6353
  const agentHostLock = refreshHostLock();
5193
- runtime = createRuntime(agent, config, agentHostLock, goals ? () => goals.get(agent) : void 0, refreshHostLock);
6354
+ runtime = createRuntime(agent, config, agentHostLock, goals ? () => goals.get(agent) : void 0, refreshHostLock, privateLedgerRoot ? () => readPrivateLedger(privateLedgerRoot, ledgerContext(agent, agentHostLock)) : void 0, privateLedgerRoot ? () => initializePrivateLedger(privateLedgerRoot, ledgerContext(agent, agentHostLock)) : void 0);
5194
6355
  runtimes.set(agent, runtime);
5195
6356
  hostLocks.set(agent, agentHostLock);
5196
6357
  }
@@ -5206,6 +6367,10 @@ function apply(ctx, rawConfig = {}, seams = {}) {
5206
6367
  }
5207
6368
  if (registeredAgents.has(agent)) return;
5208
6369
  registeredAgents.add(agent);
6370
+ registerPassiveHostWorkdirObserver(agent, () => seams.hostLock ?? revalidateCoreLock(config, installedHostLock), (tool, provider, policy) => config.hostLockRuntimeRoot && config.hostLockProfileRoot ? auditedDefaultWorkdirProvider(config.hostLockRuntimeRoot, config.hostLockProfileRoot, tool, provider, policy) : false, (exec) => {
6371
+ runtime.sync();
6372
+ return sourcedNamedTestRoot(runtime.projection, agent.session, exec.arguments);
6373
+ });
5209
6374
  agent.ctx.tools.register(createRebindTool(() => runtime.projection, async () => {
5210
6375
  const durable = await ctx.sessions.flush(agent.session);
5211
6376
  runtime.setDurability(durable);
@@ -5224,33 +6389,11 @@ function apply(ctx, rawConfig = {}, seams = {}) {
5224
6389
  runtime.sync();
5225
6390
  return durable;
5226
6391
  }, () => runtime.markRecoveryNeeded()));
5227
- /**
5228
- * Persist one C10 release record through the plugin-notice channel and make
5229
- * it durable before returning. A record that cannot be flushed is reported
5230
- * as a failure: an unflushed reservation is not an in-flight operation, and
5231
- * an unflushed settlement would let a consumed ticket look unused.
5232
- */
5233
- const persistReleaseRecord = async (toolAgent, prefix, payload) => {
5234
- const target = toolAgent.session;
5235
- target.append.bind(target)("user/message", createUserMessage({
5236
- content: [{
5237
- type: "text",
5238
- text: `${prefix}${JSON.stringify(payload)}`
5239
- }],
5240
- source: {
5241
- kind: "plugin",
5242
- plugin: "context-guard",
5243
- form: "notice",
5244
- summary: boundContextSummary("recording an explicit release record")
5245
- }
5246
- }), { surfaceOp: "append" });
5247
- let durable = false;
5248
- try {
5249
- durable = await ctx.sessions.flush(target);
5250
- } catch {
5251
- durable = false;
5252
- }
5253
- runtime.setDurability(durable);
6392
+ /** Persist release state outside provider-visible Session history. */
6393
+ const persistReleaseRecord = async (toolAgent, kind, payload) => {
6394
+ if (toolAgent.session !== agent.session) return false;
6395
+ if (!sessionCwd(agent.session)) return false;
6396
+ const durable = appendPrivateLedger(privateLedgerRoot, ledgerContext(agent), kind, payload);
5254
6397
  runtime.sync();
5255
6398
  return durable;
5256
6399
  };
@@ -5271,12 +6414,13 @@ function apply(ctx, rawConfig = {}, seams = {}) {
5271
6414
  return authorizeMutationFromProjection(runtime.projection, request);
5272
6415
  },
5273
6416
  marketOrigin: optionalMarketOrigin(ctx, agent),
6417
+ hasRestartIntent: (resolutionCallId, serviceId, preGeneration) => hasPrivateRestartIntent(readPrivateLedger(privateLedgerRoot, ledgerContext(agent)), resolutionCallId, serviceId, preGeneration),
5274
6418
  releaseGate: async (request) => {
5275
6419
  runtime.sync();
5276
6420
  const projection = runtime.projection;
5277
6421
  if (!(projection.policy === "release" || projection.releaseContracts.length > 0)) return {
5278
- status: "granted",
5279
- reasonCode: "release_profile_not_adopted"
6422
+ status: "denied",
6423
+ reasonCode: "release_contract_not_adopted"
5280
6424
  };
5281
6425
  const observed = { ...request.observed };
5282
6426
  const declaredRef = releaseContractFor(projection, request.operation)?.candidate.ref;
@@ -5297,12 +6441,19 @@ function apply(ctx, rawConfig = {}, seams = {}) {
5297
6441
  status: "denied",
5298
6442
  reasonCode: decision.reasonCode
5299
6443
  };
5300
- return await persistReleaseRecord(agent, RELEASE_RESERVATION_PREFIX, {
6444
+ const grantedContract = projection.releaseContracts.find((entry) => entry.contractId === decision.contractId);
6445
+ if (!grantedContract) return {
6446
+ status: "denied",
6447
+ reasonCode: "release_state_damaged"
6448
+ };
6449
+ return await persistReleaseRecord(agent, "release_reservation", {
5301
6450
  contractId: decision.contractId,
5302
6451
  operation: request.operation,
5303
6452
  callId: request.callId,
5304
6453
  startedAtSeq: 0,
5305
6454
  status: "in_flight",
6455
+ contract_sha256: privateLedgerContractDigest(grantedContract),
6456
+ target_sha256: privateLedgerTargetDigest(request.resolvedTarget),
5306
6457
  ...observed.artifactSri !== void 0 ? { observedArtifactSri: observed.artifactSri } : {}
5307
6458
  }) ? {
5308
6459
  status: "granted",
@@ -5319,40 +6470,41 @@ function apply(ctx, rawConfig = {}, seams = {}) {
5319
6470
  const reservation = reservationFor(runtime.projection, contractId, request.callId);
5320
6471
  let outcome = request.effect === "not_effected" ? "not_effected" : "unknown";
5321
6472
  if (request.effect === "completed" && contract) outcome = readbackSettlesContract(contract, request.readback, reservation?.observedArtifactSri) === "settled" ? "settled" : "unknown";
5322
- await persistReleaseRecord(agent, RELEASE_SETTLEMENT_PREFIX, {
6473
+ await persistReleaseRecord(agent, "release_settlement", {
5323
6474
  contractId,
5324
6475
  operation: request.operation,
5325
6476
  callId: request.callId,
5326
6477
  settledAtSeq: 0,
5327
6478
  readback: request.readback,
5328
- outcome
6479
+ outcome,
6480
+ settlement_source: "effect"
5329
6481
  });
5330
6482
  },
5331
6483
  persistRestartIntent: async (toolAgent, intent) => {
5332
- const session = toolAgent.session;
5333
- session.append.bind(session)("user/message", createUserMessage({
5334
- content: [{
5335
- type: "text",
5336
- text: `${RESTART_INTENT_PREFIX}${JSON.stringify({
5337
- resolution_call_id: intent.resolutionCallId,
5338
- service_id: intent.serviceId,
5339
- pre_generation: intent.preGeneration
5340
- })}`
5341
- }],
5342
- source: {
5343
- kind: "plugin",
5344
- plugin: "context-guard",
5345
- form: "notice",
5346
- summary: boundContextSummary("persisting a restart handoff intent")
5347
- }
5348
- }), { surfaceOp: "append" });
5349
- const durable = await ctx.sessions.flush(session);
5350
- runtime.setDurability(durable);
6484
+ if (toolAgent.session !== agent.session) return false;
6485
+ if (!sessionCwd(agent.session)) return false;
6486
+ const snapshot = readPrivateLedger(privateLedgerRoot, ledgerContext(agent));
6487
+ if (snapshot.damaged || !snapshot.anchored) return false;
6488
+ const durable = appendPrivateLedger(privateLedgerRoot, ledgerContext(agent), "restart_intent", {
6489
+ resolution_call_id: intent.resolutionCallId,
6490
+ service_id: intent.serviceId,
6491
+ pre_generation: intent.preGeneration
6492
+ });
5351
6493
  runtime.sync();
5352
6494
  return durable;
5353
6495
  }
5354
6496
  };
5355
6497
  agent.ctx.tools.register(createEvidenceTool(evidenceOptions));
6498
+ agent.ctx.tools.register(createNativeFileObserver({
6499
+ fs: ctx.fs,
6500
+ flush: (session) => ctx.sessions.flush(session)
6501
+ }));
6502
+ agent.ctx.tools.register(createNativeGitObserver({ flush: (session) => ctx.sessions.flush(session) }));
6503
+ agent.ctx.tools.register(createTestReadinessObserver({
6504
+ getProjection: () => runtime.projection,
6505
+ fs: ctx.fs,
6506
+ flush: (session) => ctx.sessions.flush(session)
6507
+ }));
5356
6508
  agent.ctx.tools.register(createActionTool(evidenceOptions));
5357
6509
  agent.ctx.tools.register(createPrepareTool({
5358
6510
  getProjection: () => runtime.projection,
@@ -5384,13 +6536,14 @@ function apply(ctx, rawConfig = {}, seams = {}) {
5384
6536
  getProjection: () => runtime.projection,
5385
6537
  fetcher: evidenceOptions.fetcher,
5386
6538
  ...evidenceOptions.allowLoopbackHttpRegistry ? { allowLoopbackHttpRegistry: true } : {},
5387
- persistSettlement: async (request) => persistReleaseRecord(request.agent, RELEASE_SETTLEMENT_PREFIX, {
6539
+ persistSettlement: async (request) => persistReleaseRecord(request.agent, "release_settlement", {
5388
6540
  contractId: request.contractId,
5389
6541
  operation: request.operation,
5390
6542
  callId: request.callId,
5391
6543
  settledAtSeq: 0,
5392
6544
  readback: request.readback,
5393
- outcome: request.outcome
6545
+ outcome: request.outcome,
6546
+ settlement_source: "reconcile"
5394
6547
  })
5395
6548
  }));
5396
6549
  agent.ctx.tools.register(createExternalOperationTool((id, toolAgent) => readExternalOperation(ctx, toolAgent, id), () => evaluateExternalWaitCapability(hostLocks.get(agent) ?? installedHostLock)));
@@ -5405,11 +6558,13 @@ function apply(ctx, rawConfig = {}, seams = {}) {
5405
6558
  if (decision.kind !== "enter") return decision;
5406
6559
  const injected = [];
5407
6560
  const delegated = isDelegatedSession(agent.session);
5408
- let boundaryPending = !runtime.protocolV5Present;
6561
+ let boundaryPending = !runtime.protocolV6Present;
5409
6562
  const firstStep = previewFirstStepInjection({
5410
6563
  activation: config.activation,
5411
6564
  enabled: runtime.projection.enabled,
5412
6565
  boundaryV5Present: runtime.protocolV5Present,
6566
+ boundaryV6Present: runtime.protocolV6Present,
6567
+ targetProtocol: 6,
5413
6568
  boundaryPresent: runtime.protocolV4Present,
5414
6569
  delegated,
5415
6570
  policy: runtime.projection.policy
@@ -5427,7 +6582,7 @@ function apply(ctx, rawConfig = {}, seams = {}) {
5427
6582
  if (recovery && digest$2 !== runtime.projection.lastRecoveryDigest) {
5428
6583
  runtime.projection.lastRecoveryDigest = digest$2;
5429
6584
  if (boundaryPending && !delegated) {
5430
- injected.push(pluginNoticeMessage(PROTOCOL_V5_NOTICE, "Context Guard recorded a replay version boundary"));
6585
+ injected.push(pluginNoticeMessage(PROTOCOL_V6_NOTICE, "Context Guard recorded a replay version boundary"));
5431
6586
  boundaryPending = false;
5432
6587
  }
5433
6588
  injected.push(createUserMessage({
@@ -5548,12 +6703,12 @@ function optionalGoalService(ctx, agent) {
5548
6703
  }
5549
6704
  function normalizeGoalState(value) {
5550
6705
  if (!value || typeof value !== "object") return void 0;
5551
- const record$1 = value;
5552
- const goal = record$1.goal && typeof record$1.goal === "object" ? record$1.goal : record$1;
6706
+ const record$2 = value;
6707
+ const goal = record$2.goal && typeof record$2.goal === "object" ? record$2.goal : record$2;
5553
6708
  const id = goal.id;
5554
6709
  const revision = goal.revision;
5555
6710
  const phase = goal.phase;
5556
- const activation = record$1.activation ?? goal.activation;
6711
+ const activation = record$2.activation ?? goal.activation;
5557
6712
  if (typeof id !== "string" || typeof revision !== "number") return void 0;
5558
6713
  if (![
5559
6714
  "active",
@@ -5571,4 +6726,112 @@ function normalizeGoalState(value) {
5571
6726
  }
5572
6727
 
5573
6728
  //#endregion
5574
- 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, CLEANUP_CONDITION_RULE, CLEANUP_CONDITION_RULE_COMPACT, CLEANUP_CONDITION_RULE_SHORT, COMMAND_SURFACE_MANIFEST, CONFIRM_LINE_PATTERN, CONTROL_RECORD_PREFIX, Config, DEFAULT_DELEGATION_TOOL_NAMES, DEFAULT_HOST_LOCK, DEFAULT_RECOVERY_CHAR_BUDGET, DEPENDENCY_FREE_ONLY_CONDITION, EXPECTED_HOST_PACKAGES, FIRST_STEP_GUIDANCE, GIT_COMMAND_MANIFEST_IDS, GIT_COMMAND_TEMPLATES, GOAL_HOST_PACKAGES, GRANTED_QUALIFICATION, HOST_CAPABILITY_PACKAGE_GROUPS, HOST_COHORTS, HostProfileError, LATEST_SUPPORTED_HOST_VERSION, LEGACY_HOST_COHORTS, LEGACY_QUALIFICATION, 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, actionHasCertificationPath, actionVerbMatches, admissibleForRemoval, apply, applyUpgradeEligibility, authorityCaptureCounts, availableBoundaryQualifications, bindExecutableIdentity, bindLiveGoalCapability, bindProofToProjection, bindProofV2ToProjection, bindingSatisfies, boundedArtifactChoiceMatches, canonicalArgvFromCommand, canonicalProjection, canonicalizePath, capabilityConsequence, capabilityFactOf, capabilityRemedyPhrase, captureClause, captureItem, carriesCleanupCondition, certifyCheckpoint, claimedBatchHasRealRootInput, clarifiedSpanOf, classifyClause, classifyCompletionClaim, classifyTaskIntent, classifyUserInteraction, clauseAsksOwnQuestion, clauseIsGoverned, clauseIsProtected, cleanupConditionFor, closingHint, combineHostPolicy, commitIndexSnapshotDigest, commitTreeSnapshotDigest, compareHostVersions, confirmRebind, createGitPrestateEnvelope, createProjection, createProofManifest, createProofManifestV2, currentContractDigest, decideTurnBoundary, decideTurnStopping, decisionBoundaryKey, deriveItemDiagnosis, deriveProjection, digestStrings, effectuateBoundary, environmentDefaultRepositoryTarget, evaluateExternalWaitCapability, evaluateHostCapability, evaluateHostLock, evaluateMinimumHostVersion, evaluateToolSurfaceCapability, evidenceAvailabilityReason, evidenceCoverage, evidenceFromPersistedToolResult, evidenceMatchesItem, executeRevalidatedGitEffect, explanationHasActionResidue, extractArtifactPaths, extractMethod, extractOperation, extractTextContent, extractToolSubject, firstStepGuidance, gitCommandMatchesTarget, goalCompletionDenial, governedClauseRestrictsExecution, hasCurrentCertificate, hasOrderedCoordination, hasQuestionScope, hostLockContextFromComposedDump, hostLockRowsFromComposedDump, hostVersionFromPackages, inject, injectActiveProfileHostLock, inspectTargetHostGraph, interpretClause, interpretMessage, introducesActionClause, isCurrentAcceptedBoundary, isDeterministicCheck, isExecutableItem, isExplanationScope, isFrozenV042RebindResponse, isInformationalFragment, isInformationalMessage, isOpenObligation, isQuestionScopeNeedingReview, isRestatement, isRootPauseRequest, isRunExecutable, isStatefulAction, isVerifyingCapability, isWholeTaskCompletionClaim, itemDiagnosis, itemHoldsExecutionAuthority, kindOfScope, latestAssistantText, latestRootInstruction, legacyQuestionReadingIsInformational, legacyRecordsNeedingReview, lifecyclePhase, maskCodeSpans, maskQuotedSpans, name, namedActions, normalizeClause, observeAssistantOutcome, openItems, opensWithDirective, packageRowsFromActiveGraph, packageRowsFromPnpmLock, parseConfirmationMessage, parseGitCommandManifest, parseHostVersion, parsePwshCommand, parseShellCommand, partialFailureOf, previewFirstStepInjection, progressFingerprint, proofCapabilityReport, proofDigest, proofDigestV2, proofEvidenceConstraints, proofHostSurfacesOf, proofOperationMatches, proofV2Rejection, proposeRebind, proposeRebindOutcome, proposeRebindV042, qualificationOfClause, qualifyBoundary, questionHeadsClause, readActiveHostGraph, rebindAttemptKey, rebindResponse, recoveryDigest, relevantEvidence, removalIsComplete, removalIsPartiallyKnown, renderRecoveryPacket, replayRebindResult, reportingHeadGoverns, requestedIdentityKey, requestedTargetAuthorizesMutation, requestedTargetMatchesResolved, requiredSubjectsOf, resolveActiveProfileHostLock, resolveInstalledHostLock, restatedContentOf, revalidateGitPrestate, sanitizeClauseText, sanitizeUrl, satisfiesSupportedHostRange, scopeCoverageDigest, segmentAuthorityBlocks, segmentClauses, selectHostCohort, semanticActionFromCommand, semanticActionFromText, semanticActionOfScope, sessionQuery, sessionQueryV2, sha256, snapshotSessionEvents, splitTextFragments, statefulActionsOfScope, supersedeItem, validateActionManifest, validateActionTarget, validateManifest, validateProofManifest, validateProofManifestV2, verbIsNegated, verifiedLinearCommitReadback, verifyComposedHostLockDump, withDurability };
6729
+ //#region src/raw-replay.ts
6730
+ /** Local synthetic replay using the actual Session, derivation and registered
6731
+ * Stop handler. It neither executes tools nor asserts a real model outcome. */
6732
+ async function replayRawV2(input) {
6733
+ const cwd = input.cwd ?? "/work";
6734
+ const id = SessionId("raw-v2-replay");
6735
+ const session = Session.create(id, void 0, {
6736
+ version: SESSION_FORMAT_VERSION,
6737
+ isSeeded: false,
6738
+ id,
6739
+ createdAt: 1,
6740
+ cwd
6741
+ });
6742
+ session.append("user/message", createUserMessage({
6743
+ content: [{
6744
+ type: "text",
6745
+ text: PROTOCOL_V6_NOTICE
6746
+ }],
6747
+ source: {
6748
+ kind: "plugin",
6749
+ plugin: "context-guard",
6750
+ form: "notice",
6751
+ summary: "v6 replay boundary"
6752
+ }
6753
+ }), { surfaceOp: "append" });
6754
+ session.append("turn/start", { turn: 1 });
6755
+ session.append("user/message", createUserMessage({
6756
+ content: [{
6757
+ type: "text",
6758
+ text: input.root
6759
+ }],
6760
+ source: { kind: "user" }
6761
+ }), { surfaceOp: "append" });
6762
+ const appendEvent = session.append.bind(session);
6763
+ for (const event of input.events ?? []) {
6764
+ if (event.type === "turn/end") throw new Error("turn/end is emitted only after the Stop callback in this replay");
6765
+ appendEvent(event.type, event.data, event.type === "tool/call" ? void 0 : { surfaceOp: "append" });
6766
+ }
6767
+ session.append("assistant/message", {
6768
+ turn: 1,
6769
+ step: 1,
6770
+ message: {
6771
+ role: "assistant",
6772
+ content: [{
6773
+ type: "text",
6774
+ text: input.final
6775
+ }]
6776
+ }
6777
+ }, { surfaceOp: "append" });
6778
+ const lock = evaluateHostLock(EXPECTED_HOST_PACKAGES, {
6779
+ platform: "posix",
6780
+ profileKind: "web"
6781
+ });
6782
+ const steers = [];
6783
+ const agent = {
6784
+ session,
6785
+ steer: (message) => {
6786
+ steers.push(message);
6787
+ }
6788
+ };
6789
+ const runtime = createRuntime(agent, { activation: "always" }, lock, () => void 0);
6790
+ runtime.setDurability(true);
6791
+ runtime.sync();
6792
+ const snapshot = sessionCoreSnapshot(session.snapshotEvents(), runtime.projection);
6793
+ const stopCore = runtime.projection.coreV2 ?? null;
6794
+ const stop = await handleGuardTurnStopping(agent, runtime, {
6795
+ flush: async () => true,
6796
+ hostSupported: true,
6797
+ readExternalOperation: () => void 0
6798
+ });
6799
+ session.append("turn/end", {
6800
+ turn: 1,
6801
+ reason: { kind: "completed" }
6802
+ });
6803
+ runtime.sync();
6804
+ const projection = runtime.projection;
6805
+ const postSnapshot = sessionCoreSnapshot(session.snapshotEvents(), projection);
6806
+ return {
6807
+ stop_core_snapshot: snapshot ?? null,
6808
+ stop_core_projection: stopCore,
6809
+ stop,
6810
+ post_turn_core_snapshot: postSnapshot ?? null,
6811
+ post_turn_core_projection: projection.coreV2 ?? null,
6812
+ goal_complete_denial: goalCompletionDenial(projection, "update_goal", {
6813
+ action: "complete",
6814
+ goal_id: projection.currentGoalRef?.id,
6815
+ revision: projection.currentGoalRef?.revision
6816
+ }) ?? null,
6817
+ assistant_observation: observeAssistantOutcome(input.final),
6818
+ steers: steers.length,
6819
+ items: [...projection.items.values()].map((item) => ({
6820
+ id: item.id,
6821
+ status: item.status,
6822
+ action: item.semanticAction,
6823
+ authority: item.authority,
6824
+ disposition: item.authorityDisposition,
6825
+ review: item.needsReview?.reason ?? null
6826
+ })),
6827
+ durable_seq: session.seq,
6828
+ event_types: session.snapshotEvents().map((event) => ({
6829
+ seq: event.seq,
6830
+ type: event.type
6831
+ })),
6832
+ boundary_protocol: projection.boundaryProtocol
6833
+ };
6834
+ }
6835
+
6836
+ //#endregion
6837
+ 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, CLEANUP_CONDITION_RULE, CLEANUP_CONDITION_RULE_COMPACT, CLEANUP_CONDITION_RULE_SHORT, COMMAND_SURFACE_MANIFEST, CONFIRM_LINE_PATTERN, CONTROL_RECORD_PREFIX, Config, DEFAULT_DELEGATION_TOOL_NAMES, DEFAULT_HOST_LOCK, DEFAULT_RECOVERY_CHAR_BUDGET, DEPENDENCY_FREE_ONLY_CONDITION, EXPECTED_HOST_PACKAGES, FIRST_STEP_GUIDANCE, GIT_COMMAND_MANIFEST_IDS, GIT_COMMAND_TEMPLATES, GOAL_HOST_PACKAGES, GRANTED_QUALIFICATION, HOST_CAPABILITY_PACKAGE_GROUPS, HOST_COHORTS, HostProfileError, LATEST_SUPPORTED_HOST_VERSION, LEGACY_HOST_COHORTS, LEGACY_QUALIFICATION, 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, PROTOCOL_V6_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, actionHasCertificationPath, actionVerbMatches, activeRendererModule, admissibleForRemoval, apply, applyUpgradeEligibility, assessmentAction, assessmentOutcomePredicate, auditedDefaultWorkdirHost, auditedDefaultWorkdirProvider, auditedForegroundRenderers, authorityCaptureCounts, availableBoundaryQualifications, bindExecutableIdentity, bindLiveGoalCapability, bindProofToProjection, bindProofV2ToProjection, bindingSatisfies, boundedArtifactChoiceMatches, canonicalArgvFromCommand, canonicalProjection, canonicalizePath, capabilityConsequence, capabilityFactOf, capabilityRemedyPhrase, captureClause, captureItem, carriesCleanupCondition, certifyCheckpoint, claimedBatchHasRealRootInput, clarifiedSpanOf, classifyClause, classifyCompletionClaim, classifyTaskIntent, classifyUserInteraction, clauseAsksOwnQuestion, clauseIsGoverned, clauseIsProtected, cleanupConditionFor, closingHint, combineHostPolicy, commitIndexSnapshotDigest, commitTreeSnapshotDigest, compareHostVersions, confirmRebind, createGitPrestateEnvelope, createProjection, createProofManifest, createProofManifestV2, currentActionBases, currentContractDigest, decideTurnBoundary, decideTurnStopping, decisionBoundaryKey, deriveItemDiagnosis, deriveProjection, digestStrings, effectuateBoundary, environmentDefaultRepositoryTarget, evaluateExternalWaitCapability, evaluateHostCapability, evaluateHostLock, evaluateMinimumHostVersion, evaluateToolSurfaceCapability, evidenceAvailabilityReason, evidenceCoverage, evidenceFromPersistedToolResult, evidenceMatchesItem, executeRevalidatedGitEffect, explanationHasActionResidue, extractArtifactPaths, extractMethod, extractOperation, extractTextContent, extractToolSubject, firstStepGuidance, firstStepGuidanceV6, gitCommandMatchesTarget, goalCompletionDenial, governedClauseRestrictsExecution, hasCurrentCertificate, hasOrderedCoordination, hasQuestionScope, hasWorkPredicate, hostLockContextFromComposedDump, hostLockRowsFromComposedDump, hostVersionFromPackages, inject, injectActiveProfileHostLock, inspectTargetHostGraph, interpretClause, interpretMessage, introducesActionClause, isCurrentAcceptedBoundary, isDeterministicCheck, isExecutableItem, isExplanationScope, isFrozenV042RebindResponse, isInformationalFragment, isInformationalMessage, isOpenObligation, isQuestionScopeNeedingReview, isRestatement, isRootPauseRequest, isRunExecutable, isStatefulAction, isVerifyingCapability, isWholeTaskCompletionClaim, itemDiagnosis, itemHoldsExecutionAuthority, kindOfScope, latestAssistantText, latestRootInstruction, legacyQuestionReadingIsInformational, legacyRecordsNeedingReview, lifecyclePhase, maskCodeSpans, maskQuotedSpans, name, namedActions, normalizeClause, observeAssistantOutcome, openItems, opensConditionLead, opensWithDirective, packageRowsFromActiveGraph, packageRowsFromPnpmLock, parseConfirmationMessage, parseGitCommandManifest, parseHostVersion, parsePwshCommand, parseShellCommand, partialFailureOf, persistedToolResultStatus, presentExplanationHead, previewFirstStepInjection, progressFingerprint, projectCoreV2, projectSessionCoreV2, proofCapabilityReport, proofDigest, proofDigestV2, proofEvidenceConstraints, proofHostSurfacesOf, proofOperationMatches, proofV2Rejection, proposeRebind, proposeRebindOutcome, proposeRebindV042, qualificationOfClause, qualifyBoundary, questionHeadsClause, readActiveHostGraph, rebindAttemptKey, rebindResponse, recoveryDigest, relevantEvidence, removalIsComplete, removalIsPartiallyKnown, renderRecoveryPacket, replayRawV2, replayRebindResult, reportingHeadGoverns, requestedIdentityKey, requestedTargetAuthorizesMutation, requestedTargetMatchesResolved, requiredSubjectsOf, resolveActiveProfileHostLock, resolveInstalledHostLock, restatedContentOf, revalidateGitPrestate, rootLocatorFlavor, sanitizeClauseText, sanitizeUrl, satisfiesSupportedHostRange, scopeCoverageDigest, segmentAuthorityBlocks, segmentClauses, selectHostCohort, semanticActionFromCommand, semanticActionFromText, semanticActionOfScope, sessionQuery, sessionQueryV2, sha256, snapshotSessionEvents, splitTextFragments, statefulActionsOfScope, supersedeItem, testOutcomePredicate, v6TestPredicate, validateActionManifest, validateActionTarget, validateManifest, validateProofManifest, validateProofManifestV2, verbIsNegated, verifiedLinearCommitReadback, verifyComposedHostLockDump, withDurability };