dsh-completion-guard 0.6.3 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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 supersedeItem, $i as STOP_PROTOCOL_VERSION, $n as NO_PROGRESS_TURNS_BEFORE_STOP, $r as extractArtifactPaths, $t as canonicalProjection, A as firstStepGuidanceV6, Ai as kindOfScope, An as v6CurrentRootBoundaries, Ar as rebindAttemptKey, At as LATEST_SUPPORTED_HOST_VERSION, B as SessionApiError, Bi as reportingHeadGoverns, Bn as normalizeReservation, Br as relevantEvidence, Bt as RC1_HOST_PACKAGES, C as gitCommandMatchesTarget, Ci as isExecutableItem, Cn as carriesCleanupCondition, Cr as qualifyBoundary, Ct as bindLiveGoalCapability, D as FIRST_STEP_GUIDANCE, Di as isQuestionScopeNeedingReview, Dn as recoveryDigest, Dr as proposeRebind, Dt as evaluateToolSurfaceCapability, E as verifiedLinearCommitReadback, Ei as isOpenObligation, En as openItems, Er as confirmRebind, Et as evaluateHostLock, F as HOST_WORKDIR_PREFIX, Fi as opensConditionLead, Fn as RELEASE_OPERATIONS, Fr as parseConfirmationMessage, Ft as evaluateMinimumHostVersion, G as PROTOCOL_V3_NOTICE, Gi as verbIsNegated, Gn as releasePreEffectDecision, Gr as capabilityFactOf, Gt as PROOF_CAPABILITY_MATRIX, H as projectCoreV2, Hi as semanticActionOfScope, Hn as readbackSettlesContract, Hr as actionHasCertificationPath, Ht as authorityCaptureCounts, I as captureHostWorkdir, Ii as opensWithDirective, In as RELEASE_OPERATION_SURFACES, Ir as capabilityRemedyPhrase, It as parseHostVersion, J as PROTOCOL_V6_NOTICE, Ji as BOUNDED_ARTIFACT_TYPES, Jn as evidenceCoverage, Jr as removalIsPartiallyKnown, Jt as PROOF_MANIFEST_DOMAIN_V2, K as PROTOCOL_V4_NOTICE, Ki as ACTION_MANIFEST, Kn as reservationFor, Kr as partialFailureOf, Kt as PROOF_KINDS, L as sourcedNamedTestRoot, Li as presentExplanationHead, Ln as contractById, Lr as deriveItemDiagnosis, Lt as satisfiesSupportedHostRange, M as previewFirstStepInjection, Mi as maskCodeSpans, Mn as isV6PendingRootWait, Mr as replayRebindResult, Mt as SUPPORTED_HOST_RANGE, N as projectSessionCoreV2, Ni as maskQuotedSpans, Nn as sourceItemForCoreRequirement, Nr as CONFIRM_LINE_PATTERN, Nt as SUPPORTED_HOST_VERSIONS, O as claimedBatchHasRealRootInput, Oi as isRestatement, On as recoveryTitle, Or as proposeRebindOutcome, Ot as hostVersionFromPackages, P as sessionCoreSnapshot, Pi as namedActions, Pn as OUTCOME_STRENGTH, Pr as isFrozenV042RebindResponse, Pt as compareHostVersions, Q as rootLocatorFlavor, Qi as STATEFUL_ACTIONS, Qn as NO_PROGRESS_RECORD_PREFIX, Qr as environmentDefaultRepositoryTarget, Qt as bindProofV2ToProjection, R as SESSION_API_UNSUPPORTED, Ri as qualificationOfClause, Rn as inFlightReservation, Rr as evidenceAvailabilityReason, Rt as RC015_RC2_HOST_PACKAGES, S as executeRevalidatedGitEffect, Si as introducesActionClause, Sn as V6_ORDINARY_COMPLETION_RULE_SHORT, Sr as isCurrentAcceptedBoundary, St as bindExecutableIdentity, T as revalidateGitPrestate, Ti as isInformationalFragment, Tn as closingHint, Tr as createProjection, Tt as evaluateHostCapability, U as CAPTURE_V042_NOTICE, Ui as splitTextFragments, Un as releaseContractFor, Ur as admissibleForRemoval, Ut as segmentAuthorityBlocks, V as snapshotSessionEvents, Vi as restatedContentOf, Vn as normalizeSettlement, Vr as DEPENDENCY_FREE_ONLY_CONDITION, Vt as ALPHA3_HOST_PACKAGES, W as DEFAULT_DELEGATION_TOOL_NAMES, Wi as statefulActionsOfScope, Wn as releaseCoverage, Wr as capabilityConsequence, Wt as certifyCheckpoint, X as deriveProjection, Xi as CERTIFICATE_VERSION_V2, Xn as isVerifyingCapability, Xr as captureItem, Xt as PROOF_PROTOCOL_VERSION_V2, Y as applyUpgradeEligibility, Yi as CERTIFICATE_VERSION, Yn as evidenceMatchesItem, Yr as captureClause, Yt as PROOF_PROTOCOL_VERSION, Z as legacyRecordsNeedingReview, Zi as SEMANTIC_ACTIONS, Zn as CONTROL_RECORD_PREFIX, Zr as classifyClause, Zt as bindProofToProjection, _ as GIT_COMMAND_MANIFEST_IDS, _a as sanitizeClauseText, _i as hasOrderedCoordination, _n as CLEANUP_CONDITION_RULE_SHORT, _r as certifiableOpenItems, _t as EXPECTED_HOST_PACKAGES, a as auditedForegroundRenderers, aa as requestedIdentityKey, ai as npmEscapedPackageName, an as proofEvidenceConstraints, ar as decideTurnStopping, at as withDurability, b as commitTreeSnapshotDigest, bi as interpretClause, bn as V6_ORDINARY_COMPLETION_RULE, br as availableBoundaryQualifications, bt as HOST_COHORTS, c as hostLockRowsFromComposedDump, ca as semanticActionFromCommand, ci as GRANTED_QUALIFICATION, cn as proofV2Rejection, cr as isWholeTaskCompletionClaim, ct as parsePwshCommand, d as packageRowsFromActiveGraph, da as validateActionTarget, di as clarifiedSpanOf, dn as sessionQuery, dr as observeAssistantOutcome, dt as ACTIVE_HOST_COHORT_IDS, ea as STOP_PROTOCOL_VERSION_V2, ei as extractMethod, en as createProofManifest, er as assessmentAction, et as evidenceFromPersistedToolResult, f as packageRowsFromPnpmLock, fa as COMMAND_SURFACE_MANIFEST, fi as clauseAsksOwnQuestion, fn as sessionQueryV2, fr as progressFingerprint, ft as ACTIVE_HOST_LAUNCHER_VERSION, g as verifyComposedHostLockDump, ga as normalizeClause, gi as governedClauseRestrictsExecution, gn as CLEANUP_CONDITION_RULE_COMPACT, gr as hasCurrentCertificate, gt as DEFAULT_HOST_LOCK, h as resolveInstalledHostLock, ha as digestStrings, hi as explanationHasActionResidue, hn as CLEANUP_CONDITION_RULE, hr as goalCompletionDenial, ht as BASE_HOST_PACKAGES, i as auditedDefaultWorkdirProvider, ia as isStatefulAction, ii as canonicalRegistryBase, in as proofDigestV2, ir as decideTurnBoundary, it as persistedToolResultStatus, j as lifecyclePhase, ji as legacyQuestionReadingIsInformational, jn as currentV6Feedback, jr as rebindResponse, jt as MIN_SUPPORTED_HOST_VERSION, k as firstStepGuidance, ki as itemHoldsExecutionAuthority, kn as renderRecoveryPacket, kr as proposeRebindV042, kt as selectHostCohort, l as injectActiveProfileHostLock, la as semanticActionFromText, li as LEGACY_QUALIFICATION, ln as requiredSubjectsOf, lr as latestAssistantText, lt as parseShellCommand, m as resolveActiveProfileHostLock, ma as canonicalizePath, mi as clauseIsProtected, mn as validateProofManifestV2, mr as v6TestPredicate, mt as ALPHA2_HOST_PACKAGES, n as activeRendererModule, na as actionCompatible, ni as isInformationalMessage, nn as proofCapabilityReport, nr as classifyCompletionClaim, nt as extractToolSubject, o as combineHostPolicy, oa as requestedTargetAuthorizesMutation, oi as classifyTaskIntent, on as proofHostSurfacesOf, or as decisionBoundaryKey, ot as canonicalArgvFromCommand, p as readActiveHostGraph, pa as validateManifest, pi as clauseIsGoverned, pn as validateProofManifest, pr as testOutcomePredicate, pt as ALPHA2_DSHMARKET_139_HOST_PACKAGES, q as PROTOCOL_V5_NOTICE, qi as ACTION_MANIFEST_VERSION, qn as bindingSatisfies, qr as removalIsComplete, qt as PROOF_KINDS_V2, r as auditedDefaultWorkdirHost, ra as boundedArtifactChoiceMatches, ri as segmentClauses, rn as proofDigest, rr as currentActionBases, rt as isDeterministicCheck, s as hostLockContextFromComposedDump, sa as requestedTargetMatchesResolved, si as classifyUserInteraction, sn as proofOperationMatches, sr as isRootPauseRequest, st as isRunExecutable, t as HostProfileError, ta as SUPPORTED_EVIDENCE_ADAPTERS, ti as extractOperation, tn as createProofManifestV2, tr as assessmentOutcomePredicate, tt as extractTextContent, u as inspectTargetHostGraph, ua as validateActionManifest, ui as actionVerbMatches, un as scopeCoverageDigest, ur as latestRootInstruction, ut as ACTIVE_HOST_COHORT_ID, v as GIT_COMMAND_TEMPLATES, va as sanitizeUrl, vi as hasQuestionScope, vn as DEFAULT_RECOVERY_CHAR_BUDGET, vr as certificateClosure, vt as GOAL_HOST_PACKAGES, w as parseGitCommandManifest, wi as isExplanationScope, wn as cleanupConditionFor, wr as currentContractDigest, wt as evaluateExternalWaitCapability, x as createGitPrestateEnvelope, xi as interpretMessage, xn as V6_ORDINARY_COMPLETION_RULE_COMPACT, xr as effectuateBoundary, xt as LEGACY_HOST_COHORTS, y as commitIndexSnapshotDigest, ya as sha256, yi as hasWorkPredicate, yn as MIN_RECOVERY_CHAR_BUDGET, yr as unitDescendantIds, yt as HOST_CAPABILITY_PACKAGE_GROUPS, z as SESSION_EVENT_ENVELOPE_INVALID, zi as questionHeadsClause, zn as normalizeReleaseContract, zr as itemDiagnosis, zt as RC015_HOST_PACKAGES } from "./domain-DbPbaoXp.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,54 @@ 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
+ const isProhibition = sourced?.item.kind === "prohibition";
727
+ return {
728
+ id,
729
+ reason_code: currentFeedback.predicates[id],
730
+ ...sourced ? {
731
+ source_item_id: sourced.item.id,
732
+ revision: sourced.item.revision,
733
+ kind: sourced.item.kind,
734
+ text: sourced.item.normalizedText
735
+ } : {},
736
+ ...sourced?.origin ? {
737
+ source_start: sourced.origin.sourceStart,
738
+ source_end: sourced.origin.sourceEnd,
739
+ semantic_action: sourced.origin.action,
740
+ target: sourced.origin.target
741
+ } : sourced?.item.semanticAction ? { semantic_action: sourced.item.semanticAction } : {},
742
+ next_step: isProhibition ? "This recorded prohibition stays in force; do not perform the action." : "Answer this sourced requirement using the current Host observation or final delivery; ordinary Guard bindings are not required."
743
+ };
744
+ });
745
+ const constraints = Object.entries(currentFeedback.predicates).filter(([, state]) => state === "constraint_active" || state === "constraint_unresolved" || state === "constraint_violated").map(([id, state]) => {
746
+ const sourced = sourceItemForCoreRequirement(projection, id);
747
+ return {
748
+ id,
749
+ reason_code: state,
750
+ ...sourced ? {
751
+ revision: sourced.item.revision,
752
+ text: sourced.item.normalizedText
753
+ } : {}
754
+ };
755
+ });
756
+ return checkpointPage(projection, args, {
757
+ status: currentFeedback.status,
758
+ reason_code: currentFeedback.reasonCode,
759
+ current_feedback: true,
760
+ contract_revision: projection.contractRevision,
761
+ blocking_total: openRows.length,
762
+ open_items: openRows,
763
+ active_constraints: constraints,
764
+ available_evidence: [],
765
+ available_qualifications: [],
766
+ rejected_bindings: [],
767
+ current_actions: currentFeedback.currentActions
768
+ });
769
+ }
673
770
  const bindings = args.bindings.map((binding) => ({
674
771
  itemId: binding.item_id,
675
772
  evidenceIds: binding.evidence_ids,
@@ -796,6 +893,8 @@ function createCheckpointTool(getProjection, onRejected, prepare = async () => t
796
893
  open_digest: result.checkpoint.openDigest,
797
894
  evidence_sha256: result.checkpoint.evidenceSha256,
798
895
  binding_digest: result.checkpoint.bindingDigest,
896
+ ...result.checkpoint.nativeObservations ? { native_observations: result.checkpoint.nativeObservations } : {},
897
+ ...result.checkpoint.rootLocatorIdentity ? { root_locator_identity: result.checkpoint.rootLocatorIdentity } : {},
799
898
  certification_digest: result.checkpoint.certificationDigest,
800
899
  ...result.checkpoint.unitId !== void 0 ? {
801
900
  unit_id: result.checkpoint.unitId,
@@ -1234,8 +1333,13 @@ const encodeCursor = (cursor) => Buffer.from(JSON.stringify(cursor), "utf8").toS
1234
1333
  * are reached by item ID, not re-listed here (0.6.1, W060-03).
1235
1334
  */
1236
1335
  function discoveryItemIds(p) {
1336
+ const current = currentV6Feedback(p);
1337
+ if (current && current.status !== "unknown") {
1338
+ const standing = Object.entries(current.predicates).filter(([, state]) => state === "constraint_active").map(([id]) => id).sort().filter((id) => !current.openIds.includes(id));
1339
+ return [...current.openIds, ...standing];
1340
+ }
1237
1341
  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);
1342
+ if (p.boundaryProtocol === void 0 || p.boundaryProtocol < 5) return pending.map((item) => item.id);
1239
1343
  const closureUnits = new Set([...p.currentUnitId !== void 0 ? [p.currentUnitId, ...unitDescendantIds(p, p.currentUnitId)] : []]);
1240
1344
  return pending.filter((item) => item.unitId === void 0 || item.unitId !== void 0 && closureUnits.has(item.unitId)).map((item) => item.id);
1241
1345
  }
@@ -1251,7 +1355,7 @@ function discoveryItemIds(p) {
1251
1355
  function createPrepareTool(options) {
1252
1356
  return defineTool({
1253
1357
  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.",
1358
+ 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
1359
  parameters: {
1256
1360
  item_id: { type: "string" },
1257
1361
  item_revision: { type: "number" },
@@ -1292,8 +1396,106 @@ function createPrepareTool(options) {
1292
1396
  status: "unknown",
1293
1397
  reason_code: "guard_unavailable"
1294
1398
  };
1399
+ const currentFeedback = currentV6Feedback(p);
1400
+ if (currentFeedback?.status === "unknown") {
1401
+ if (args.item_id !== void 0) {
1402
+ const item$1 = sourceItemForCoreRequirement(p, args.item_id)?.item ?? p.items.get(args.item_id);
1403
+ if (item$1) {
1404
+ if (args.item_revision !== void 0 && args.item_revision !== item$1.revision) return {
1405
+ status: "rejected",
1406
+ reason_code: "item_revision_mismatch",
1407
+ item_revision: item$1.revision
1408
+ };
1409
+ return {
1410
+ status: "unknown",
1411
+ reason_code: currentFeedback.reasonCode,
1412
+ item: {
1413
+ id: item$1.id,
1414
+ revision: item$1.revision,
1415
+ kind: item$1.kind,
1416
+ text: item$1.normalizedText,
1417
+ ...item$1.waitAuthorization !== void 0 || item$1.authorityDisposition === "conditional_wait" ? {
1418
+ recorded_wait: {
1419
+ resume_event: item$1.resumeEvent ?? null,
1420
+ condition: item$1.condition ?? null
1421
+ },
1422
+ ...isV6PendingRootWait(p, item$1) ? { wait: "root_condition_pending" } : {}
1423
+ } : {}
1424
+ },
1425
+ next_step: "The recorded text above is a durable read-only fact only; the closure, release, and authorization state stays unknown until the named condition is restored."
1426
+ };
1427
+ }
1428
+ }
1429
+ return {
1430
+ status: "unknown",
1431
+ reason_code: currentFeedback.reasonCode
1432
+ };
1433
+ }
1434
+ if (p.boundaryProtocol === 6 && args.item_id !== void 0) {
1435
+ const sourced = currentFeedback ? sourceItemForCoreRequirement(p, args.item_id) : void 0;
1436
+ const current = sourced?.item ?? p.items.get(args.item_id);
1437
+ if (!current) return {
1438
+ status: "rejected",
1439
+ reason_code: "item_not_found"
1440
+ };
1441
+ if (args.item_revision !== void 0 && args.item_revision !== current.revision) return {
1442
+ status: "rejected",
1443
+ reason_code: "item_revision_mismatch"
1444
+ };
1445
+ if (current.kind === "prohibition" && currentFeedback) {
1446
+ const state = currentFeedback.predicates[args.item_id];
1447
+ if (state === "constraint_active" || state === "constraint_unresolved" || state === "constraint_violated" || state === "legacy_review") return {
1448
+ status: state === "constraint_active" ? "active" : state === "constraint_violated" ? "incomplete" : "unknown",
1449
+ reason_code: state,
1450
+ item: {
1451
+ id: current.id,
1452
+ revision: current.revision,
1453
+ kind: current.kind,
1454
+ status: state,
1455
+ text: current.normalizedText
1456
+ },
1457
+ next_step: state === "constraint_active" ? "This sourced prohibition remains active." : state === "constraint_unresolved" ? "The current Host facts cannot establish whether this prohibition was respected." : state === "constraint_violated" ? "A sourced host mutation violated this prohibition." : "This recorded prohibition stays in force as recorded history; current confirmed facts cannot establish its compliance state. Do not perform the action."
1458
+ };
1459
+ }
1460
+ if (current.semanticAction !== "publish" && currentFeedback) {
1461
+ const exactDerived = sourced?.origin !== void 0;
1462
+ const related = Object.entries(currentFeedback.predicates).filter(([id]) => exactDerived ? id === args.item_id : id === args.item_id || sourceItemForCoreRequirement(p, id)?.item.id === current.id);
1463
+ const state = related.length === 0 ? void 0 : related.every(([, value]) => value === "satisfied") ? "satisfied" : "insufficient";
1464
+ return {
1465
+ status: state === void 0 || state === "satisfied" ? "observed" : "incomplete",
1466
+ reason_code: state === void 0 ? "historical_item_not_current" : state === "satisfied" ? "ordinary_current_predicate_observed" : "current_predicate_insufficient",
1467
+ item: {
1468
+ id: args.item_id,
1469
+ source_item_id: current.id,
1470
+ revision: current.revision,
1471
+ status: state ?? "historical",
1472
+ related_requirement_ids: related.map(([id]) => id),
1473
+ text: current.normalizedText,
1474
+ ...current.waitAuthorization !== void 0 || current.authorityDisposition === "conditional_wait" ? {
1475
+ recorded_wait: {
1476
+ resume_event: current.resumeEvent ?? null,
1477
+ condition: current.condition ?? null
1478
+ },
1479
+ ...isV6PendingRootWait(p, current) ? { wait: "root_condition_pending" } : {}
1480
+ } : {}
1481
+ },
1482
+ 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."
1483
+ };
1484
+ }
1485
+ if (current.semanticAction !== "publish") return {
1486
+ status: "observed",
1487
+ reason_code: "ordinary_execution_host_owned",
1488
+ item: {
1489
+ id: current.id,
1490
+ revision: current.revision,
1491
+ status: current.status
1492
+ },
1493
+ 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."
1494
+ };
1495
+ }
1295
1496
  if (args.item_id === void 0) {
1296
1497
  const filter = args.semantic_action ?? null;
1498
+ const coreIdentity = currentFeedback ? sha256(JSON.stringify(p.coreV2 ?? null)) : void 0;
1297
1499
  const invalidCursor = (reason_code, note) => ({
1298
1500
  status: "rejected",
1299
1501
  reason_code,
@@ -1307,18 +1509,23 @@ function createPrepareTool(options) {
1307
1509
  try {
1308
1510
  if (args.page_cursor.length <= 1024) {
1309
1511
  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;
1512
+ 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
1513
  }
1312
1514
  } catch {
1313
1515
  parsed = void 0;
1314
1516
  }
1315
1517
  if (!parsed) return invalidCursor("discovery_cursor_malformed");
1316
1518
  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.`);
1519
+ if (parsed.c !== coreIdentity) return invalidCursor("discovery_cursor_stale", "The current observation changed. Re-run discovery without page_cursor.");
1317
1520
  if ((parsed.f ?? null) !== (filter ?? null)) return invalidCursor("discovery_cursor_filter_mismatch");
1318
1521
  startAfter = parsed.k;
1319
1522
  }
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;
1523
+ const eligible = discoveryItemIds(p).map((id) => ({
1524
+ id,
1525
+ sourced: currentFeedback ? sourceItemForCoreRequirement(p, id) : void 0,
1526
+ item: currentFeedback ? sourceItemForCoreRequirement(p, id)?.item : p.items.get(id)
1527
+ })).filter((entry) => entry.item !== void 0).filter(({ item: item$1, sourced }) => filter === null || (sourced?.origin?.action ?? item$1.semanticAction ?? "generic_run") === filter);
1528
+ const startIndex = startAfter === void 0 ? 0 : eligible.findIndex(({ id, item: item$1 }) => item$1.revision === startAfter[0] && id === startAfter[1]) + 1;
1322
1529
  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
1530
  const page = eligible.slice(startIndex, startIndex + DISCOVERY_ITEM_LIMIT);
1324
1531
  const hasMore = startIndex + page.length < eligible.length;
@@ -1330,15 +1537,21 @@ function createPrepareTool(options) {
1330
1537
  total_open: eligible.length,
1331
1538
  listed: page.length,
1332
1539
  has_more: hasMore,
1333
- items: page.map((item$1) => {
1540
+ items: page.map(({ id, item: item$1, sourced }) => {
1334
1541
  const diagnosis$1 = deriveItemDiagnosis(p, item$1);
1335
1542
  return {
1336
- id: item$1.id,
1543
+ id,
1544
+ ...sourced?.origin ? {
1545
+ source_item_id: item$1.id,
1546
+ source_start: sourced.origin.sourceStart,
1547
+ source_end: sourced.origin.sourceEnd,
1548
+ target: sourced.origin.target
1549
+ } : {},
1337
1550
  revision: item$1.revision,
1338
1551
  kind: item$1.kind,
1339
1552
  ...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,
1553
+ semantic_action: sourced?.origin?.action ?? item$1.semanticAction ?? "generic_run",
1554
+ reason_code: currentFeedback ? currentFeedback.predicates[id] ?? "current_predicate_insufficient" : diagnosis$1.reason_code,
1342
1555
  text: item$1.normalizedText
1343
1556
  };
1344
1557
  }),
@@ -1346,10 +1559,11 @@ function createPrepareTool(options) {
1346
1559
  v: 1,
1347
1560
  r: p.contractRevision,
1348
1561
  f: filter,
1349
- k: [page[page.length - 1].revision, page[page.length - 1].id]
1562
+ k: [page[page.length - 1].item.revision, page[page.length - 1].id],
1563
+ ...coreIdentity ? { c: coreIdentity } : {}
1350
1564
  }) } : {},
1351
1565
  ...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."
1566
+ note: "Re-run with one item_id for a read-only diagnosis, or pass page_cursor for the next page."
1353
1567
  };
1354
1568
  }
1355
1569
  const item = p.items.get(args.item_id ?? "");
@@ -1498,9 +1712,9 @@ function parsePartition(args, extent) {
1498
1712
  if (!Array.isArray(raw)) return void 0;
1499
1713
  const spans = [];
1500
1714
  for (const entry of raw) {
1501
- const record$1 = entry;
1502
- const start = record$1?.start;
1503
- const end = record$1?.end;
1715
+ const record$2 = entry;
1716
+ const start = record$2?.start;
1717
+ const end = record$2?.end;
1504
1718
  if (typeof start !== "number" || !Number.isSafeInteger(start) || typeof end !== "number" || !Number.isSafeInteger(end) || start >= end) return void 0;
1505
1719
  spans.push({
1506
1720
  start,
@@ -1630,7 +1844,7 @@ function createInterpretTool(options) {
1630
1844
 
1631
1845
  //#endregion
1632
1846
  //#region src/tools/evidence.ts
1633
- const execFileAsync = promisify(execFile);
1847
+ const execFileAsync$1 = promisify(execFile);
1634
1848
  const PRODUCER_VERSION = "1.0.0";
1635
1849
  const PRODUCER_TOOL = "context_guard_evidence";
1636
1850
  const ACTION_TOOL = "context_guard_action";
@@ -1649,17 +1863,17 @@ const SUPPORTED = [
1649
1863
  const RESTART_INTENT_PREFIX = "Context Guard restart intent v1: ";
1650
1864
  function restartIntent(events, resolutionCallId, target) {
1651
1865
  for (const raw of events) {
1652
- const event = record(raw);
1866
+ const event = record$1(raw);
1653
1867
  if (!event || event.type !== "user/message") continue;
1654
- const data = record(event.data);
1655
- const source = record(data?.source);
1868
+ const data = record$1(event.data);
1869
+ const source = record$1(data?.source);
1656
1870
  if (source?.kind !== "plugin" || source.plugin !== "context-guard" || source.form !== "notice") continue;
1657
1871
  const content = Array.isArray(data?.content) ? data.content : [];
1658
- const block = content.length === 1 ? record(content[0]) : void 0;
1872
+ const block = content.length === 1 ? record$1(content[0]) : void 0;
1659
1873
  const text = typeof block?.text === "string" ? block.text : "";
1660
1874
  if (!text.startsWith(RESTART_INTENT_PREFIX)) continue;
1661
1875
  try {
1662
- const value = record(JSON.parse(text.slice(33)));
1876
+ const value = record$1(JSON.parse(text.slice(33)));
1663
1877
  if (value?.resolution_call_id === resolutionCallId && value.service_id === target.service_id && value.pre_generation === target.pre_generation) return true;
1664
1878
  } catch {}
1665
1879
  }
@@ -1687,7 +1901,7 @@ function installedProfile(moduleUrl = import.meta.url) {
1687
1901
  directory = parent;
1688
1902
  }
1689
1903
  }
1690
- function record(value) {
1904
+ function record$1(value) {
1691
1905
  return value && typeof value === "object" ? value : void 0;
1692
1906
  }
1693
1907
  function stable(value) {
@@ -1711,7 +1925,7 @@ function jsonExpectedTransition(transition) {
1711
1925
  };
1712
1926
  }
1713
1927
  function tuple(value) {
1714
- return record(value);
1928
+ return record$1(value);
1715
1929
  }
1716
1930
  function adapterId(action) {
1717
1931
  if (["create", "modify"].includes(action)) return "context-guard.artifact.v1";
@@ -1760,29 +1974,29 @@ function supported(action, role, resolved, observed = {}, commandManifest = {},
1760
1974
  };
1761
1975
  }
1762
1976
  function messageMeta(event) {
1763
- return record(record(event.data)?.meta);
1977
+ return record$1(record$1(event.data)?.meta);
1764
1978
  }
1765
1979
  function producerMeta(event) {
1766
- return record(messageMeta(event)?.contextGuard);
1980
+ return record$1(messageMeta(event)?.contextGuard);
1767
1981
  }
1768
1982
  function eventCallId(event) {
1769
- const data = record(event.data);
1983
+ const data = record$1(event.data);
1770
1984
  if (event.type === "tool/call") return typeof data?.callId === "string" ? data.callId : void 0;
1771
- const source = record(record(data?.message)?.source);
1985
+ const source = record$1(record$1(data?.message)?.source);
1772
1986
  return typeof source?.callId === "string" ? source.callId : void 0;
1773
1987
  }
1774
1988
  function findResolution(events, callId, action) {
1775
1989
  let selector;
1776
1990
  let commandManifest;
1777
1991
  for (const raw of events) {
1778
- const event = record(raw);
1992
+ const event = record$1(raw);
1779
1993
  if (!event || eventCallId(event) !== callId) continue;
1780
1994
  if (event.type === "tool/call") {
1781
- const data = record(event.data);
1995
+ const data = record$1(event.data);
1782
1996
  try {
1783
- const args = record(JSON.parse(String(data?.arguments ?? "{}")));
1784
- selector = record(args?.selector);
1785
- commandManifest = record(args?.command_manifest);
1997
+ const args = record$1(JSON.parse(String(data?.arguments ?? "{}")));
1998
+ selector = record$1(args?.selector);
1999
+ commandManifest = record$1(args?.command_manifest);
1786
2000
  } catch {
1787
2001
  return;
1788
2002
  }
@@ -1792,13 +2006,13 @@ function findResolution(events, callId, action) {
1792
2006
  const meta = producerMeta(event);
1793
2007
  if (meta?.semanticAction !== action || meta.evidenceRole !== "resolution" || meta.adapterVersion !== (action === "restart" ? "2.0.0" : PRODUCER_VERSION) || !selector || !commandManifest) return void 0;
1794
2008
  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);
2009
+ const rawBinding = record$1(meta.gitBinding);
2010
+ const rawManifest = record$1(rawBinding?.manifest);
2011
+ const rawPrestate = record$1(rawBinding?.prestate);
2012
+ const rawEnvelope = record$1(rawBinding?.envelope);
2013
+ const rawExecutable = record$1(meta.executableIdentity);
2014
+ const rawExpected = record$1(meta.expectedTransition);
2015
+ const expectedParameters$1 = record$1(rawExpected?.parameters);
1802
2016
  const expectedTransition = rawExpected && typeof rawExpected.predicateId === "string" && rawExpected.version === 1 && rawExpected.predParamsKind === "inline" && expectedParameters$1 ? rawExpected : void 0;
1803
2017
  const expectedTransitionDigest = typeof meta.expectedTransitionDigest === "string" ? meta.expectedTransitionDigest : void 0;
1804
2018
  const interpreterIdentityValid = rawExecutable && (rawExecutable.interpreterRealpath === void 0 && rawExecutable.interpreterVersion === void 0 || typeof rawExecutable.interpreterRealpath === "string" && typeof rawExecutable.interpreterVersion === "string");
@@ -1822,14 +2036,14 @@ function findResolution(events, callId, action) {
1822
2036
  function findEffect(events, callId) {
1823
2037
  let call;
1824
2038
  for (const raw of events) {
1825
- const event = record(raw);
2039
+ const event = record$1(raw);
1826
2040
  if (!event) continue;
1827
2041
  const seq = typeof event.seq === "number" ? event.seq : -1;
1828
2042
  if (event.type === "tool/call" && eventCallId(event) === callId) {
1829
- const data = record(event.data);
2043
+ const data = record$1(event.data);
1830
2044
  let args = {};
1831
2045
  try {
1832
- args = record(JSON.parse(String(data?.arguments ?? "{}"))) ?? {};
2046
+ args = record$1(JSON.parse(String(data?.arguments ?? "{}"))) ?? {};
1833
2047
  } catch {
1834
2048
  args = {};
1835
2049
  }
@@ -1842,23 +2056,26 @@ function findEffect(events, callId) {
1842
2056
  };
1843
2057
  }
1844
2058
  if (event.type === "tool/result" && eventCallId(event) === callId && call) {
1845
- const data = record(event.data);
2059
+ const data = record$1(event.data);
1846
2060
  call.resultSeq = seq;
1847
- call.error = data?.error;
2061
+ call.error = persistedToolResultStatus(data, callId) !== "clean" ? {
2062
+ name: "HostResultError",
2063
+ code: "HOST_RESULT_UNTRUSTED"
2064
+ } : void 0;
1848
2065
  call.meta = data?.meta;
1849
- call.textContent = extractTextContent(record(data?.message)?.content ?? []);
2066
+ call.textContent = extractTextContent(record$1(data?.message)?.content ?? []);
1850
2067
  return call;
1851
2068
  }
1852
2069
  }
1853
2070
  }
1854
2071
  function actionCallMatches(events, callId, action, resolutionCallId, target) {
1855
2072
  for (const raw of events) {
1856
- const event = record(raw);
2073
+ const event = record$1(raw);
1857
2074
  if (!event || event.type !== "tool/call" || eventCallId(event) !== callId) continue;
1858
- const data = record(event.data);
2075
+ const data = record$1(event.data);
1859
2076
  if (data?.name !== ACTION_TOOL) return false;
1860
2077
  try {
1861
- const args = record(JSON.parse(String(data.arguments ?? "{}")));
2078
+ const args = record$1(JSON.parse(String(data.arguments ?? "{}")));
1862
2079
  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
2080
  } catch {
1864
2081
  return false;
@@ -1868,15 +2085,15 @@ function actionCallMatches(events, callId, action, resolutionCallId, target) {
1868
2085
  }
1869
2086
  function actionResultCompleted(events, callId) {
1870
2087
  for (const raw of events) {
1871
- const event = record(raw);
2088
+ const event = record$1(raw);
1872
2089
  if (!event || event.type !== "tool/result" || eventCallId(event) !== callId) continue;
1873
- return record(messageMeta(event)?.contextGuardAction)?.status === "completed";
2090
+ return record$1(messageMeta(event)?.contextGuardAction)?.status === "completed" && persistedToolResultStatus(event.data, callId) === "clean";
1874
2091
  }
1875
2092
  return false;
1876
2093
  }
1877
2094
  function plannedEffectDigest(manifest) {
1878
2095
  const name$1 = typeof manifest.planned_tool === "string" ? manifest.planned_tool : void 0;
1879
- const args = record(manifest.planned_arguments);
2096
+ const args = record$1(manifest.planned_arguments);
1880
2097
  return name$1 && args ? digest({
1881
2098
  name: name$1,
1882
2099
  arguments: args
@@ -1884,7 +2101,7 @@ function plannedEffectDigest(manifest) {
1884
2101
  }
1885
2102
  function plannedEffect(manifest) {
1886
2103
  const name$1 = typeof manifest.planned_tool === "string" ? manifest.planned_tool : void 0;
1887
- const args = record(manifest.planned_arguments);
2104
+ const args = record$1(manifest.planned_arguments);
1888
2105
  return name$1 && args ? {
1889
2106
  name: name$1,
1890
2107
  arguments: args,
@@ -1917,7 +2134,7 @@ function effectDigest(effect) {
1917
2134
  });
1918
2135
  }
1919
2136
  function cwdOf(agent) {
1920
- const header = record(agent.session.header);
2137
+ const header = record$1(agent.session.header);
1921
2138
  return typeof header?.cwd === "string" ? header.cwd : void 0;
1922
2139
  }
1923
2140
  function pathOf(selector, cwd) {
@@ -1935,7 +2152,7 @@ async function fileDigest(path) {
1935
2152
  }
1936
2153
  async function readJson(path) {
1937
2154
  try {
1938
- return record(JSON.parse(await readFile(path, "utf8")));
2155
+ return record$1(JSON.parse(await readFile(path, "utf8")));
1939
2156
  } catch {
1940
2157
  return;
1941
2158
  }
@@ -1959,7 +2176,7 @@ async function tgzIdentity(path) {
1959
2176
  if (name$1 === "package/package.json") {
1960
2177
  if (manifest || size$1 > 1024 * 1024) return void 0;
1961
2178
  try {
1962
- manifest = record(JSON.parse(tar.subarray(bodyStart, bodyEnd).toString("utf8")));
2179
+ manifest = record$1(JSON.parse(tar.subarray(bodyStart, bodyEnd).toString("utf8")));
1963
2180
  } catch {
1964
2181
  return;
1965
2182
  }
@@ -1969,7 +2186,7 @@ async function tgzIdentity(path) {
1969
2186
  if (typeof manifest?.name !== "string" || typeof manifest.version !== "string") return void 0;
1970
2187
  const gitHead = typeof manifest.gitHead === "string" && /^[0-9a-f]{40}$/.test(manifest.gitHead) ? manifest.gitHead : void 0;
1971
2188
  const repositoryField = manifest.repository;
1972
- const repository = typeof repositoryField === "string" ? repositoryField : record(repositoryField) && typeof record(repositoryField)?.url === "string" ? String(record(repositoryField).url) : void 0;
2189
+ const repository = typeof repositoryField === "string" ? repositoryField : record$1(repositoryField) && typeof record$1(repositoryField)?.url === "string" ? String(record$1(repositoryField).url) : void 0;
1973
2190
  return {
1974
2191
  name: manifest.name,
1975
2192
  version: manifest.version,
@@ -2037,10 +2254,10 @@ async function marketCapabilities(roots, signal) {
2037
2254
  redirect: "error"
2038
2255
  });
2039
2256
  if (!response.ok) return void 0;
2040
- const value = record(await response.json());
2257
+ const value = record$1(await response.json());
2041
2258
  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);
2259
+ const features = record$1(value.features);
2260
+ const restart = record$1(value.restart);
2044
2261
  if (features?.restart !== true || restart?.supported !== true || restart.managedBy !== "market") return void 0;
2045
2262
  const provider = createHash("sha256").update(JSON.stringify([
2046
2263
  MARKET_SCHEMA,
@@ -2104,17 +2321,17 @@ async function profilePackage(profilePath, packageId) {
2104
2321
  }
2105
2322
  }
2106
2323
  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), {
2324
+ const canonical$1 = canonicalRegistryBase(registry, { allowLoopbackHttp: roots.allowLoopbackHttpRegistry });
2325
+ if (!canonical$1 || canonical$1 !== registry) return void 0;
2326
+ const response = await (roots.fetcher ?? fetch)(new URL(npmEscapedPackageName(packageId), canonical$1), {
2110
2327
  signal,
2111
2328
  headers: { accept: "application/json" },
2112
2329
  redirect: "error"
2113
2330
  });
2114
2331
  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);
2332
+ const value = record$1(await response.json());
2333
+ const release = record$1(record$1(value?.versions)?.[version]);
2334
+ const dist = record$1(release?.dist);
2118
2335
  return value?.name === packageId && release?.name === packageId && release.version === version && typeof dist?.integrity === "string" ? dist.integrity : void 0;
2119
2336
  }
2120
2337
  function windowsBatchCommand(file, args) {
@@ -2130,7 +2347,7 @@ async function windowsCommandInterpreter(signal) {
2130
2347
  const interpreterRealpath = await realpath(configured);
2131
2348
  const systemInterpreter = await realpath(resolve(systemRoot, "System32", "cmd.exe"));
2132
2349
  if (basename(interpreterRealpath).toLowerCase() !== "cmd.exe" || interpreterRealpath.toLowerCase() !== systemInterpreter.toLowerCase()) return void 0;
2133
- const { stdout, stderr } = await execFileAsync(interpreterRealpath, [
2350
+ const { stdout, stderr } = await execFileAsync$1(interpreterRealpath, [
2134
2351
  "/d",
2135
2352
  "/v:off",
2136
2353
  "/c",
@@ -2153,7 +2370,7 @@ async function execAuditedFile(file, args, options, interpreter) {
2153
2370
  if (process.platform === "win32" && /\.(?:cmd|bat)$/i.test(file)) {
2154
2371
  const command = windowsBatchCommand(file, args);
2155
2372
  if (!command || !interpreter) throw new Error("unsafe Windows batch invocation");
2156
- return execFileAsync(interpreter.interpreterRealpath, [
2373
+ return execFileAsync$1(interpreter.interpreterRealpath, [
2157
2374
  "/d",
2158
2375
  "/v:off",
2159
2376
  "/s",
@@ -2166,7 +2383,7 @@ async function execAuditedFile(file, args, options, interpreter) {
2166
2383
  windowsVerbatimArguments: true
2167
2384
  });
2168
2385
  }
2169
- return execFileAsync(file, args, {
2386
+ return execFileAsync$1(file, args, {
2170
2387
  ...options,
2171
2388
  encoding: "utf8"
2172
2389
  });
@@ -2202,14 +2419,14 @@ async function executableIdentity(executable, signal) {
2202
2419
  const candidate = resolve(directory, `${executable}${suffix}`);
2203
2420
  try {
2204
2421
  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);
2422
+ const canonical$1 = await realpath(candidate);
2423
+ const interpreter = process.platform === "win32" && /\.(?:cmd|bat)$/i.test(canonical$1) ? await windowsCommandInterpreter(signal) : void 0;
2424
+ if (process.platform === "win32" && /\.(?:cmd|bat)$/i.test(canonical$1) && !interpreter) continue;
2425
+ const { stdout, stderr } = await execAuditedFile(canonical$1, ["--version"], { signal }, interpreter);
2209
2426
  const version = `${stdout}${stderr}`.trim();
2210
2427
  if (version && !version.includes("\n") && !version.includes("\r")) return {
2211
2428
  executable,
2212
- realpath: canonical,
2429
+ realpath: canonical$1,
2213
2430
  version,
2214
2431
  ...interpreter
2215
2432
  };
@@ -2249,8 +2466,8 @@ async function executeGuardAction(action, resolution, roots, signal, executableI
2249
2466
  const capabilities = await marketCapabilities(roots, signal);
2250
2467
  if (!capabilities || !roots.marketOrigin || !resolutionCallId || !agent) return { status: "unavailable" };
2251
2468
  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" };
2469
+ 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" };
2470
+ if (roots.hasRestartIntent?.(resolutionCallId, String(target.service_id), String(target.pre_generation)) || restartIntent(snapshotSessionEvents(agent.session), resolutionCallId, target)) return { status: "handoff_pending" };
2254
2471
  if (!roots.persistRestartIntent || !await roots.persistRestartIntent(agent, {
2255
2472
  resolutionCallId,
2256
2473
  serviceId: String(target.service_id),
@@ -2268,7 +2485,7 @@ async function executeGuardAction(action, resolution, roots, signal, executableI
2268
2485
  body: "{}"
2269
2486
  });
2270
2487
  if (!response.ok) return { status: "unavailable" };
2271
- return record(await response.json())?.schema === MARKET_SCHEMA ? { status: "handoff_pending" } : { status: "unavailable" };
2488
+ return record$1(await response.json())?.schema === MARKET_SCHEMA ? { status: "handoff_pending" } : { status: "unavailable" };
2272
2489
  }
2273
2490
  if (action === "commit" || action === "push" || action === "pull" || action === "fetch") {
2274
2491
  const binding = resolution.gitBinding;
@@ -2321,7 +2538,7 @@ async function executeGuardAction(action, resolution, roots, signal, executableI
2321
2538
  return { status: "unavailable" };
2322
2539
  }
2323
2540
  async function gitBytes(repository, args, signal, file = "git") {
2324
- const { stdout } = await execFileAsync(file, args, {
2541
+ const { stdout } = await execFileAsync$1(file, args, {
2325
2542
  cwd: repository,
2326
2543
  encoding: "buffer",
2327
2544
  signal,
@@ -2441,12 +2658,12 @@ function pickTarget(target, keys) {
2441
2658
  async function expectedTransitionForResolution(action, target, commandManifest) {
2442
2659
  let parameters;
2443
2660
  if (action === "create") {
2444
- const plannedArguments = record(commandManifest.planned_arguments);
2661
+ const plannedArguments = record$1(commandManifest.planned_arguments);
2445
2662
  const content = typeof plannedArguments?.content === "string" ? plannedArguments.content : void 0;
2446
2663
  if (content === void 0) return void 0;
2447
2664
  parameters = { post_digest: createHash("sha256").update(Buffer.from(content, "utf8")).digest("hex") };
2448
2665
  } else if (action === "modify") {
2449
- const plannedArguments = record(commandManifest.planned_arguments);
2666
+ const plannedArguments = record$1(commandManifest.planned_arguments);
2450
2667
  const oldString = requireString(plannedArguments ?? {}, "old_string");
2451
2668
  const newString = typeof plannedArguments?.new_string === "string" ? plannedArguments.new_string : void 0;
2452
2669
  const artifact = typeof target.artifact_id === "string" ? target.artifact_id : void 0;
@@ -2523,8 +2740,8 @@ async function resolveTarget(action, selector, commandManifest, cwd, roots, sign
2523
2740
  const service = requireString(selector, "service_id");
2524
2741
  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
2742
  const capabilities = await marketCapabilities(roots, signal);
2526
- const features = record(capabilities?.features);
2527
- const restart = record(capabilities?.restart);
2743
+ const features = record$1(capabilities?.features);
2744
+ const restart = record$1(capabilities?.restart);
2528
2745
  if (features?.restart !== true || restart?.supported !== true || restart.managedBy !== "market") return void 0;
2529
2746
  return { target: {
2530
2747
  service_id: service,
@@ -2753,6 +2970,7 @@ function normalizedRoots(options) {
2753
2970
  ...options.fetcher ? { fetcher: options.fetcher } : {},
2754
2971
  ...options.commandRunner ? { commandRunner: options.commandRunner } : {},
2755
2972
  ...options.persistRestartIntent ? { persistRestartIntent: options.persistRestartIntent } : {},
2973
+ ...options.hasRestartIntent ? { hasRestartIntent: options.hasRestartIntent } : {},
2756
2974
  ...options.hostCapability ? { hostCapability: options.hostCapability } : {},
2757
2975
  ...options.authorizeMutation ? { authorizeMutation: options.authorizeMutation } : {},
2758
2976
  ...options.prepareMutation ? { prepareMutation: options.prepareMutation } : {},
@@ -2766,7 +2984,7 @@ function createActionTool(options = {}) {
2766
2984
  const roots = normalizedRoots(options);
2767
2985
  return defineTool({
2768
2986
  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.",
2987
+ 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
2988
  parameters: {
2771
2989
  semantic_action: {
2772
2990
  type: "string",
@@ -2854,6 +3072,11 @@ function createActionTool(options = {}) {
2854
3072
  target_digest: "",
2855
3073
  command_manifest_digest: ""
2856
3074
  };
3075
+ if (action !== "publish") return {
3076
+ status: "unavailable",
3077
+ reason_code: "ordinary_action_migrated_to_host_tools",
3078
+ ...empty
3079
+ };
2857
3080
  if (!agent || ![
2858
3081
  "install",
2859
3082
  "apply",
@@ -3022,7 +3245,7 @@ function createEvidenceTool(options = {}) {
3022
3245
  const roots = normalizedRoots(options);
3023
3246
  return defineTool({
3024
3247
  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.",
3248
+ description: "Observe a controlled registry publish. Ordinary work uses native host tools and read-only observers; older producer calls return migration diagnostics.",
3026
3249
  parameters: {
3027
3250
  semantic_action: {
3028
3251
  type: "string",
@@ -3228,6 +3451,17 @@ function createEvidenceTool(options = {}) {
3228
3451
  async execute(args, exec) {
3229
3452
  const action = args.semantic_action;
3230
3453
  const role = args.evidence_role;
3454
+ if ([
3455
+ "install",
3456
+ "apply",
3457
+ "create",
3458
+ "modify",
3459
+ "restart",
3460
+ "commit",
3461
+ "push",
3462
+ "pull",
3463
+ "fetch"
3464
+ ].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
3465
  if (!SUPPORTED.includes(action)) return unavailable(action, role, "adapter_unavailable_for_pinned_host");
3232
3466
  if (roots.hostCapability?.(action).status !== "supported" && roots.hostCapability) return unavailable(action, role, "host_capability_unavailable");
3233
3467
  const agent = exec.agent;
@@ -3236,9 +3470,9 @@ function createEvidenceTool(options = {}) {
3236
3470
  if (role === "resolution") {
3237
3471
  const recipe = actionPreparation(action);
3238
3472
  {
3239
- const manifest = record(args.command_manifest);
3240
- const plannedArgs = record(manifest?.planned_arguments);
3241
- const selector = record(args.selector);
3473
+ const manifest = record$1(args.command_manifest);
3474
+ const plannedArgs = record$1(manifest?.planned_arguments);
3475
+ const selector = record$1(args.selector);
3242
3476
  const needsManifestId = [
3243
3477
  "install",
3244
3478
  "apply",
@@ -3258,10 +3492,10 @@ function createEvidenceTool(options = {}) {
3258
3492
  const executable$1 = executableFor(action);
3259
3493
  const executableBinding = executable$1 ? await (roots.readExecutableIdentity ?? executableIdentity)(executable$1, exec.signal) : void 0;
3260
3494
  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);
3495
+ const resolved = await resolveTarget(action, record$1(args.selector) ?? {}, record$1(args.command_manifest) ?? {}, cwdOf(agent), roots, exec.signal, executableBinding);
3262
3496
  if (!resolved) return unavailable(action, role, action === "restart" && !roots.verifyMarketInstance ? "market_instance_binding_unavailable" : "resolution_unavailable");
3263
3497
  const gitBinding = resolved.gitBinding ? JSON.parse(JSON.stringify(resolved.gitBinding)) : void 0;
3264
- const commandManifest = record(args.command_manifest) ?? {};
3498
+ const commandManifest = record$1(args.command_manifest) ?? {};
3265
3499
  const expectedTransition = await expectedTransitionForResolution(action, resolved.target, commandManifest);
3266
3500
  if (!expectedTransition) return unavailable(action, role, "expected_transition_unavailable");
3267
3501
  return supported(action, role, resolved.target, {}, commandManifest, gitBinding, executableBinding, expectedTransition);
@@ -3353,21 +3587,27 @@ function createReleaseTool(options) {
3353
3587
  operations: releaseCoverage(contract$1),
3354
3588
  candidate: contract$1.candidate
3355
3589
  })),
3356
- reservations: projection.releaseReservations.map(({ contractId: contractId$1, operation: operation$1, callId: callId$1, startedAtSeq, observedArtifactSri }) => ({
3590
+ reservations: projection.releaseReservations.map(({ contractId: contractId$1, operation: operation$1, callId: callId$1, startedAtSeq, ledgerPosition, observedArtifactSri }) => ({
3357
3591
  contract_id: contractId$1,
3358
3592
  operation: operation$1,
3359
3593
  resolution_call_id: callId$1,
3360
- started_at_seq: startedAtSeq,
3594
+ ...ledgerPosition === void 0 ? { started_at_seq: startedAtSeq } : { record_position: {
3595
+ channel: "private_ledger",
3596
+ position: ledgerPosition
3597
+ } },
3361
3598
  observed_artifact_sri: observedArtifactSri ?? null,
3362
3599
  in_flight: inFlightReservation(projection, contractId$1, operation$1)?.callId === callId$1
3363
3600
  })),
3364
- settlements: projection.releaseSettlements.map(({ contractId: contractId$1, operation: operation$1, callId: callId$1, outcome: outcome$1, readback: readback$2, settledAtSeq }) => ({
3601
+ settlements: projection.releaseSettlements.map(({ contractId: contractId$1, operation: operation$1, callId: callId$1, outcome: outcome$1, readback: readback$2, settledAtSeq, ledgerPosition }) => ({
3365
3602
  contract_id: contractId$1,
3366
3603
  operation: operation$1,
3367
3604
  resolution_call_id: callId$1,
3368
3605
  outcome: outcome$1,
3369
3606
  readback: readback$2,
3370
- settled_at_seq: settledAtSeq
3607
+ ...ledgerPosition === void 0 ? { settled_at_seq: settledAtSeq } : { record_position: {
3608
+ channel: "private_ledger",
3609
+ position: ledgerPosition
3610
+ } }
3371
3611
  })),
3372
3612
  diagnostics: projection.releaseDiagnostics
3373
3613
  };
@@ -3434,6 +3674,518 @@ function createReleaseTool(options) {
3434
3674
  });
3435
3675
  }
3436
3676
 
3677
+ //#endregion
3678
+ //#region src/tools/observe.ts
3679
+ const execFileAsync = promisify(execFile);
3680
+ const record = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
3681
+ /** Read-only, post-effect file observer. The path comes from a persisted native edit call. */
3682
+ function createNativeFileObserver(host) {
3683
+ return defineTool({
3684
+ name: "context_guard_observe_file",
3685
+ 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.",
3686
+ parameters: { effect_call_id: {
3687
+ type: "string",
3688
+ required: true
3689
+ } },
3690
+ output: {
3691
+ schema: {
3692
+ type: "object",
3693
+ additionalProperties: false,
3694
+ properties: {
3695
+ status: {
3696
+ type: "string",
3697
+ required: true,
3698
+ enum: ["observed", "unavailable"]
3699
+ },
3700
+ reason_code: {
3701
+ type: "string",
3702
+ required: true
3703
+ },
3704
+ effect_call_id: {
3705
+ type: "string",
3706
+ required: true
3707
+ },
3708
+ path: {
3709
+ type: "string",
3710
+ required: true
3711
+ },
3712
+ sha256: {
3713
+ type: "string",
3714
+ required: true
3715
+ },
3716
+ action: {
3717
+ type: "string",
3718
+ required: true,
3719
+ enum: [
3720
+ "create",
3721
+ "modify",
3722
+ "unknown"
3723
+ ]
3724
+ },
3725
+ canonical_path: { type: "string" },
3726
+ canonical_base: { type: "string" }
3727
+ }
3728
+ },
3729
+ render: (_args, value) => [{
3730
+ type: "text",
3731
+ text: JSON.stringify(value)
3732
+ }],
3733
+ presentationMeta: (_args, value) => value.status === "observed" ? { contextGuardNativeFile: {
3734
+ effectCallId: value.effect_call_id,
3735
+ path: value.path,
3736
+ sha256: value.sha256,
3737
+ action: value.action,
3738
+ ...value.canonical_path ? { canonicalPath: value.canonical_path } : {},
3739
+ ...value.canonical_base ? { canonicalBase: value.canonical_base } : {}
3740
+ } } : { contextGuardNativeFileUnavailable: { reasonCode: value.reason_code } }
3741
+ },
3742
+ async execute(args, exec) {
3743
+ const missing = (reason) => ({
3744
+ status: "unavailable",
3745
+ reason_code: reason,
3746
+ effect_call_id: args.effect_call_id,
3747
+ path: "",
3748
+ sha256: "",
3749
+ action: "unknown"
3750
+ });
3751
+ const agent = exec.agent;
3752
+ if (!agent || !host.fs || !host.flush) return missing("host_fs_unavailable");
3753
+ if (!await host.flush(agent.session)) return missing("native_effect_not_durable");
3754
+ let call;
3755
+ let result;
3756
+ let callSeq = -1;
3757
+ let resultSeq = -1;
3758
+ let duplicate = false;
3759
+ for (const raw of snapshotSessionEvents(agent.session)) {
3760
+ const event = record(raw);
3761
+ const data = record(event?.data);
3762
+ if (event?.type === "tool/call" && data?.callId === args.effect_call_id) {
3763
+ if (call) duplicate = true;
3764
+ call = data;
3765
+ callSeq = Number(event.seq);
3766
+ }
3767
+ if (event?.type === "tool/result" && record(record(data?.message)?.source)?.callId === args.effect_call_id) {
3768
+ if (result) duplicate = true;
3769
+ result = data;
3770
+ resultSeq = Number(event.seq);
3771
+ }
3772
+ }
3773
+ if (!call || !result || duplicate || callSeq >= resultSeq || call.turn !== result.turn || call.step !== result.step || ![
3774
+ "write",
3775
+ "write_file",
3776
+ "edit",
3777
+ "edit_file"
3778
+ ].includes(String(call.name))) return missing("native_effect_missing");
3779
+ const source = record(record(result.message)?.source);
3780
+ if (source?.kind !== "tool" || source.callId !== args.effect_call_id) return missing("native_effect_missing");
3781
+ const resultStatus = persistedToolResultStatus(result, args.effect_call_id);
3782
+ if (resultStatus !== "clean") return missing(resultStatus === "failure" ? "native_effect_failed" : "native_effect_untrusted");
3783
+ let effectArgs;
3784
+ try {
3785
+ effectArgs = record(JSON.parse(String(call.arguments)));
3786
+ } catch {
3787
+ return missing("native_effect_arguments_invalid");
3788
+ }
3789
+ const filePath = effectArgs?.file_path;
3790
+ if (typeof filePath !== "string" || !filePath) return missing("native_effect_target_missing");
3791
+ const action = String(call.name).startsWith("write") ? "create" : "modify";
3792
+ const cwd = record(agent.session.header)?.cwd;
3793
+ try {
3794
+ const target = await host.fs.resolve(filePath, {
3795
+ ...typeof cwd === "string" ? { cwd } : {},
3796
+ signal: exec.signal
3797
+ });
3798
+ const before = await host.fs.stat(target, exec.signal);
3799
+ if (!before || before.type !== "file" || before.size !== void 0 && before.size > 2e7) return missing("native_file_readback_unavailable");
3800
+ const content = await host.fs.readText(target, exec.signal);
3801
+ const after = await host.fs.stat(target, exec.signal);
3802
+ if (!after || after.type !== "file" || before.version !== after.version) return missing("native_file_readback_raced");
3803
+ let canonicalPath;
3804
+ let canonicalBase;
3805
+ if (typeof cwd === "string" && host.fs.processPath && host.fs.contains) {
3806
+ const base = await host.fs.resolve(cwd, { signal: exec.signal });
3807
+ const path = host.fs.processPath(target);
3808
+ const root = host.fs.processPath(base);
3809
+ 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;
3810
+ if (host.fs.contains(base, target) && absoluteFlavor(path) && absoluteFlavor(path) === absoluteFlavor(root)) {
3811
+ canonicalPath = path;
3812
+ canonicalBase = root;
3813
+ }
3814
+ }
3815
+ return {
3816
+ status: "observed",
3817
+ reason_code: "file_state_observed",
3818
+ effect_call_id: args.effect_call_id,
3819
+ path: target.displayPath,
3820
+ sha256: createHash("sha256").update(content, "utf8").digest("hex"),
3821
+ action,
3822
+ ...canonicalPath && canonicalBase ? {
3823
+ canonical_path: canonicalPath,
3824
+ canonical_base: canonicalBase
3825
+ } : {}
3826
+ };
3827
+ } catch {
3828
+ return missing("native_file_readback_unavailable");
3829
+ }
3830
+ }
3831
+ });
3832
+ }
3833
+ /** Fixed-argv Git readback for a persisted native shell commit/push result. */
3834
+ function createNativeGitObserver(host) {
3835
+ return defineTool({
3836
+ name: "context_guard_observe_git",
3837
+ description: "Read back a repository after a persisted native Git command; performs only fixed Git queries.",
3838
+ parameters: { effect_call_id: {
3839
+ type: "string",
3840
+ required: true
3841
+ } },
3842
+ output: {
3843
+ schema: {
3844
+ type: "object",
3845
+ additionalProperties: false,
3846
+ properties: {
3847
+ status: {
3848
+ type: "string",
3849
+ required: true,
3850
+ enum: ["observed", "unavailable"]
3851
+ },
3852
+ reason_code: {
3853
+ type: "string",
3854
+ required: true
3855
+ },
3856
+ effect_call_id: {
3857
+ type: "string",
3858
+ required: true
3859
+ },
3860
+ action: {
3861
+ type: "string",
3862
+ required: true,
3863
+ enum: [
3864
+ "commit",
3865
+ "push",
3866
+ "unknown"
3867
+ ]
3868
+ },
3869
+ repository: {
3870
+ type: "string",
3871
+ required: true
3872
+ },
3873
+ branch: {
3874
+ type: "string",
3875
+ required: true
3876
+ },
3877
+ remote: {
3878
+ type: "string",
3879
+ required: true
3880
+ },
3881
+ refspec: {
3882
+ type: "string",
3883
+ required: true
3884
+ },
3885
+ post_oid: {
3886
+ type: "string",
3887
+ required: true
3888
+ },
3889
+ parent_oid: {
3890
+ type: "string",
3891
+ required: true
3892
+ },
3893
+ tree_oid: {
3894
+ type: "string",
3895
+ required: true
3896
+ }
3897
+ }
3898
+ },
3899
+ render: (_args, value) => [{
3900
+ type: "text",
3901
+ text: JSON.stringify(value)
3902
+ }],
3903
+ presentationMeta: (_args, value) => value.status === "observed" ? { contextGuardNativeGit: {
3904
+ effectCallId: value.effect_call_id,
3905
+ action: value.action,
3906
+ repository: value.repository,
3907
+ branch: value.branch,
3908
+ remote: value.remote,
3909
+ refspec: value.refspec,
3910
+ postOid: value.post_oid,
3911
+ parentOid: value.parent_oid,
3912
+ treeOid: value.tree_oid
3913
+ } } : { contextGuardNativeGitUnavailable: { reasonCode: value.reason_code } }
3914
+ },
3915
+ async execute(args, exec) {
3916
+ const missing = (reason) => ({
3917
+ status: "unavailable",
3918
+ reason_code: reason,
3919
+ effect_call_id: args.effect_call_id,
3920
+ action: "unknown",
3921
+ repository: "",
3922
+ branch: "",
3923
+ remote: "",
3924
+ refspec: "",
3925
+ post_oid: "",
3926
+ parent_oid: "",
3927
+ tree_oid: ""
3928
+ });
3929
+ const session = exec.agent?.session;
3930
+ if (!session || !host.flush || !await host.flush(session)) return missing("native_effect_not_durable");
3931
+ let call;
3932
+ let result;
3933
+ let callSeq = -1;
3934
+ let resultSeq = -1;
3935
+ let duplicate = false;
3936
+ for (const raw of snapshotSessionEvents(session)) {
3937
+ const event = record(raw);
3938
+ const data = record(event?.data);
3939
+ if (event?.type === "tool/call" && data?.callId === args.effect_call_id) {
3940
+ if (call) duplicate = true;
3941
+ call = data;
3942
+ callSeq = Number(event.seq);
3943
+ }
3944
+ if (event?.type === "tool/result" && record(record(data?.message)?.source)?.callId === args.effect_call_id) {
3945
+ if (result) duplicate = true;
3946
+ result = data;
3947
+ resultSeq = Number(event.seq);
3948
+ }
3949
+ }
3950
+ 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");
3951
+ const message = record(result.message);
3952
+ const source = record(message?.source);
3953
+ if (source?.kind !== "tool" || source.callId !== args.effect_call_id) return missing("native_effect_missing");
3954
+ const resultStatus = persistedToolResultStatus(result, args.effect_call_id);
3955
+ if (resultStatus !== "clean") return missing(resultStatus === "failure" ? "native_effect_failed" : "native_effect_untrusted");
3956
+ let effectArgs;
3957
+ try {
3958
+ effectArgs = record(JSON.parse(String(call.arguments)));
3959
+ } catch {
3960
+ return missing("native_effect_arguments_invalid");
3961
+ }
3962
+ const command = effectArgs?.command;
3963
+ const repository = effectArgs?.workdir;
3964
+ if (typeof command !== "string" || typeof repository !== "string" || !repository) return missing("native_git_target_missing");
3965
+ const parsed = canonicalArgvFromCommand(command, call.name);
3966
+ const argv = parsed.argv;
3967
+ if (parsed.status !== "supported" || argv[0] !== "git") return missing("native_git_command_unsupported");
3968
+ const action = argv[1];
3969
+ if (action !== "commit" && action !== "push") return missing("native_git_command_unsupported");
3970
+ const gitAction = action;
3971
+ const output = Array.isArray(message?.content) ? extractTextContent(message.content) : "";
3972
+ const git$1 = async (...query) => (await execFileAsync("git", [
3973
+ "-C",
3974
+ repository,
3975
+ ...query
3976
+ ], {
3977
+ encoding: "utf8",
3978
+ timeout: 5e3,
3979
+ maxBuffer: 1024 * 1024
3980
+ })).stdout.trim();
3981
+ try {
3982
+ const top = await git$1("rev-parse", "--show-toplevel");
3983
+ if (!top || await realpath(top) !== await realpath(repository)) return missing("native_git_repository_mismatch");
3984
+ const observedRepository = repository;
3985
+ const branch = await git$1("symbolic-ref", "--short", "HEAD");
3986
+ const postOid = await git$1("rev-parse", "HEAD");
3987
+ if (!/^[0-9a-f]{40,64}$/.test(postOid)) return missing("native_git_readback_unavailable");
3988
+ if (action === "commit") {
3989
+ 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");
3990
+ const parentOid = await git$1("rev-parse", "HEAD^");
3991
+ const treeOid = await git$1("rev-parse", "HEAD^{tree}");
3992
+ return {
3993
+ status: "observed",
3994
+ reason_code: "git_commit_observed",
3995
+ effect_call_id: args.effect_call_id,
3996
+ action: gitAction,
3997
+ repository: observedRepository,
3998
+ branch,
3999
+ remote: "",
4000
+ refspec: "",
4001
+ post_oid: postOid,
4002
+ parent_oid: parentOid,
4003
+ tree_oid: treeOid
4004
+ };
4005
+ }
4006
+ const remote = argv[2];
4007
+ const refspec = argv[3];
4008
+ if (argv.length !== 4 || !remote || !/^refs\/heads\/[^:]+:refs\/heads\/[^:]+$/.test(refspec)) return missing("native_git_refspec_unsupported");
4009
+ const [src, dst] = refspec.split(":");
4010
+ const localOid = await git$1("rev-parse", src);
4011
+ const remoteOid = (await git$1("ls-remote", "--exit-code", remote, dst)).split(/\s+/)[0];
4012
+ const destinationName = dst.slice(11);
4013
+ const reportedUpdate = output.includes(localOid.slice(0, 7)) || output.includes("[new branch]") && output.includes(`-> ${destinationName}`);
4014
+ if (remoteOid !== localOid || !reportedUpdate) return missing("native_git_push_readback_mismatch");
4015
+ return {
4016
+ status: "observed",
4017
+ reason_code: "git_push_observed",
4018
+ effect_call_id: args.effect_call_id,
4019
+ action: gitAction,
4020
+ repository: observedRepository,
4021
+ branch,
4022
+ remote,
4023
+ refspec,
4024
+ post_oid: remoteOid,
4025
+ parent_oid: "",
4026
+ tree_oid: ""
4027
+ };
4028
+ } catch {
4029
+ return missing("native_git_readback_unavailable");
4030
+ }
4031
+ }
4032
+ });
4033
+ }
4034
+ /** Specific package-script readiness, with a stable changed input for an
4035
+ * assessment. The observer never executes the script or infers success. */
4036
+ function createTestReadinessObserver(host) {
4037
+ return defineTool({
4038
+ name: "context_guard_observe_test_readiness",
4039
+ description: "Read a pending test or assessment script and its concrete inputs; never runs the script.",
4040
+ parameters: { item_id: {
4041
+ type: "string",
4042
+ required: true
4043
+ } },
4044
+ output: {
4045
+ schema: {
4046
+ type: "object",
4047
+ additionalProperties: false,
4048
+ properties: {
4049
+ status: {
4050
+ type: "string",
4051
+ required: true,
4052
+ enum: ["ready", "unavailable"]
4053
+ },
4054
+ reason_code: {
4055
+ type: "string",
4056
+ required: true
4057
+ },
4058
+ item_id: {
4059
+ type: "string",
4060
+ required: true
4061
+ },
4062
+ scope: {
4063
+ type: "string",
4064
+ required: true
4065
+ },
4066
+ manifest_sha256: {
4067
+ type: "string",
4068
+ required: true
4069
+ },
4070
+ predicate: {
4071
+ type: "string",
4072
+ required: true
4073
+ },
4074
+ script_name: {
4075
+ type: "string",
4076
+ required: true
4077
+ },
4078
+ selected_path: {
4079
+ type: "string",
4080
+ required: true
4081
+ },
4082
+ effect_call_id: {
4083
+ type: "string",
4084
+ required: true
4085
+ },
4086
+ input_sha256: {
4087
+ type: "string",
4088
+ required: true
4089
+ }
4090
+ }
4091
+ },
4092
+ render: (_args, value) => [{
4093
+ type: "text",
4094
+ text: JSON.stringify(value)
4095
+ }],
4096
+ presentationMeta: (_args, value) => value.status === "ready" ? { contextGuardTestReadiness: {
4097
+ itemId: value.item_id,
4098
+ scope: value.scope,
4099
+ manifestSha256: value.manifest_sha256,
4100
+ predicate: value.predicate,
4101
+ scriptName: value.script_name,
4102
+ selectedPath: value.selected_path,
4103
+ effectCallId: value.effect_call_id,
4104
+ inputSha256: value.input_sha256
4105
+ } } : { contextGuardTestReadinessUnavailable: { reasonCode: value.reason_code } }
4106
+ },
4107
+ async execute(args, exec) {
4108
+ const missing = (reason) => ({
4109
+ status: "unavailable",
4110
+ reason_code: reason,
4111
+ item_id: args.item_id,
4112
+ scope: "",
4113
+ manifest_sha256: "",
4114
+ predicate: "",
4115
+ script_name: "",
4116
+ selected_path: "",
4117
+ effect_call_id: "",
4118
+ input_sha256: ""
4119
+ });
4120
+ if (!exec.agent?.session || !host.flush || !host.fs || !await host.flush(exec.agent.session)) return missing("readiness_host_unavailable");
4121
+ const projection = host.getProjection();
4122
+ const item = projection?.items.get(args.item_id);
4123
+ 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");
4124
+ const scope = item.requestedTarget.scope;
4125
+ const assessment = item.semanticAction === "verify";
4126
+ if (typeof item.requestedTarget.script_name === "string") return missing("readiness_script_capability_unavailable");
4127
+ const scriptName = assessment && /(?:吞吐|性能|时延|延迟|throughput|performance|latency)/iu.test(item.normalizedText) ? "benchmark" : "test";
4128
+ let selectedPath = "", effectCallId = "", inputSha256 = "";
4129
+ if (assessment) {
4130
+ const unitStart = item.unitId ? projection?.units.get(item.unitId)?.openedAtSeq : void 0;
4131
+ if (unitStart === void 0) return missing("assessment_unit_unavailable");
4132
+ 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) => ({
4133
+ path: op.path,
4134
+ callId: fact.callId
4135
+ })));
4136
+ const paths = [...new Set(changes.map((change) => change.path))];
4137
+ if (paths.length > 1) return missing("assessment_input_ambiguous");
4138
+ if (paths.length === 1) {
4139
+ const change = changes.find((entry) => entry.path === paths[0]);
4140
+ selectedPath = change.path;
4141
+ effectCallId = change.callId;
4142
+ try {
4143
+ const changed = await host.fs.resolve(selectedPath, { signal: exec.signal });
4144
+ const before = await host.fs.stat(changed, exec.signal);
4145
+ if (!before || before.type !== "file" || before.size !== void 0 && before.size > 2e7) return missing("assessment_input_unavailable");
4146
+ const raw = await host.fs.readText(changed, exec.signal);
4147
+ const after = await host.fs.stat(changed, exec.signal);
4148
+ if (!after || after.type !== "file" || before.version !== after.version) return missing("assessment_input_raced");
4149
+ inputSha256 = createHash("sha256").update(raw, "utf8").digest("hex");
4150
+ } catch {
4151
+ return missing("assessment_input_unavailable");
4152
+ }
4153
+ }
4154
+ }
4155
+ try {
4156
+ if (/^[A-Za-z]:/.test(scope) && (!/^[A-Za-z]:\\/.test(scope) || scope.includes("/"))) return missing("readiness_scope_unavailable");
4157
+ const manifestPath = /^[A-Za-z]:\\/.test(scope) ? win32.join(scope, "package.json") : posix.join(scope, "package.json");
4158
+ const target = await host.fs.resolve(manifestPath, { signal: exec.signal });
4159
+ const before = await host.fs.stat(target, exec.signal);
4160
+ if (!before || before.type !== "file" || before.size !== void 0 && before.size > 2e6) return missing("readiness_manifest_unavailable");
4161
+ const raw = await host.fs.readText(target, exec.signal);
4162
+ const after = await host.fs.stat(target, exec.signal);
4163
+ if (!after || after.type !== "file" || before.version !== after.version) return missing("readiness_manifest_raced");
4164
+ const manifest = record(JSON.parse(raw));
4165
+ if (typeof record(manifest?.scripts)?.[scriptName] !== "string" || !String(record(manifest?.scripts)?.[scriptName]).trim()) return missing("readiness_script_missing");
4166
+ if (assessment && !selectedPath) {
4167
+ selectedPath = target.displayPath;
4168
+ inputSha256 = createHash("sha256").update(raw, "utf8").digest("hex");
4169
+ }
4170
+ return {
4171
+ status: "ready",
4172
+ reason_code: assessment ? "assessment_inputs_ready" : "package_test_script_ready",
4173
+ item_id: args.item_id,
4174
+ scope,
4175
+ manifest_sha256: createHash("sha256").update(raw, "utf8").digest("hex"),
4176
+ predicate: assessment ? "verification_passed" : "test_passed",
4177
+ script_name: scriptName,
4178
+ selected_path: selectedPath,
4179
+ effect_call_id: effectCallId,
4180
+ input_sha256: inputSha256
4181
+ };
4182
+ } catch {
4183
+ return missing("readiness_manifest_unavailable");
4184
+ }
4185
+ }
4186
+ });
4187
+ }
4188
+
3437
4189
  //#endregion
3438
4190
  //#region src/tools/external-operation.ts
3439
4191
  function createExternalOperationTool(read, capability) {
@@ -3525,14 +4277,17 @@ const PRESERVED_DIGEST_DOMAINS = [
3525
4277
  "ccg.proofManifest.v1"
3526
4278
  ];
3527
4279
  function migrationReport(projection) {
3528
- const v5 = projection.boundaryProtocol === 5;
4280
+ const v6 = projection.boundaryProtocol === 6;
4281
+ const v5 = projection.boundaryProtocol !== void 0 && projection.boundaryProtocol >= 5;
3529
4282
  const legacyItemIds = certifiableOpenItems(projection).filter((item) => item.unitId === void 0).map((item) => item.id);
3530
4283
  const closure = v5 ? certificateClosure(projection) : { itemIds: [] };
3531
4284
  const reasonCodes = [];
3532
4285
  if (!v5) reasonCodes.push("legacy_session_keeps_v4_contract");
3533
4286
  if (v5 && legacyItemIds.length > 0) reasonCodes.push("pre_v5_obligations_retained_in_closure");
4287
+ if (v6) reasonCodes.push("v6_ordinary_host_facts_and_legacy_review");
4288
+ if (v6 && projection.coreV2Reason) reasonCodes.push(`core_v2_${projection.coreV2Reason}`);
3534
4289
  return {
3535
- ruleMode: v5 ? "v5" : "legacy-v4",
4290
+ ruleMode: v6 ? "v6" : v5 ? "v5" : "legacy-v4",
3536
4291
  certificateVersion: v5 ? CERTIFICATE_VERSION_V2 : CERTIFICATE_VERSION,
3537
4292
  stopProtocolVersion: v5 ? STOP_PROTOCOL_VERSION_V2 : STOP_PROTOCOL_VERSION,
3538
4293
  unitClosure: v5,
@@ -3542,7 +4297,7 @@ function migrationReport(projection) {
3542
4297
  preservedDigestDomains: [...PRESERVED_DIGEST_DOMAINS],
3543
4298
  historyOnlyCertificateVersions: v5 ? [CERTIFICATE_VERSION] : [],
3544
4299
  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.",
4300
+ 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
4301
  reasonCodes
3547
4302
  };
3548
4303
  }
@@ -3636,17 +4391,23 @@ function releaseResponse(projection, rawInput) {
3636
4391
  operations: releaseCoverage(contract),
3637
4392
  expires_at_epoch_ms: contract.expiresAtEpochMs ?? null,
3638
4393
  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 }) => ({
4394
+ 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
4395
  operation,
3641
4396
  call_id: callId,
3642
- started_at_seq: startedAtSeq
4397
+ ...ledgerPosition === void 0 ? { started_at_seq: startedAtSeq } : { record_position: {
4398
+ channel: "private_ledger",
4399
+ position: ledgerPosition
4400
+ } }
3643
4401
  })),
3644
- settlements: projection.releaseSettlements.filter((settlement) => settlement.contractId === contract.contractId).map(({ operation, callId, outcome, readback: readback$1, settledAtSeq }) => ({
4402
+ settlements: projection.releaseSettlements.filter((settlement) => settlement.contractId === contract.contractId).map(({ operation, callId, outcome, readback: readback$1, settledAtSeq, ledgerPosition }) => ({
3645
4403
  operation,
3646
4404
  call_id: callId,
3647
4405
  outcome,
3648
4406
  readback: readback$1,
3649
- settled_at_seq: settledAtSeq
4407
+ ...ledgerPosition === void 0 ? { settled_at_seq: settledAtSeq } : { record_position: {
4408
+ channel: "private_ledger",
4409
+ position: ledgerPosition
4410
+ } }
3650
4411
  }))
3651
4412
  }));
3652
4413
  return {
@@ -4628,10 +5389,385 @@ function resolveConfig(config) {
4628
5389
  };
4629
5390
  }
4630
5391
 
5392
+ //#endregion
5393
+ //#region src/domain/private-ledger.ts
5394
+ const normalizeContext = (value) => typeof value === "string" ? {
5395
+ sessionId: value,
5396
+ sessionHeader: { id: value },
5397
+ cwd: "/",
5398
+ hostLockDigest: "test-seam"
5399
+ } : value;
5400
+ const canonical = (value) => {
5401
+ if (value === null || typeof value === "boolean" || typeof value === "string") return JSON.stringify(value);
5402
+ if (typeof value === "number") {
5403
+ if (!Number.isFinite(value) || Object.is(value, -0)) throw new TypeError("private_ledger_non_json_number");
5404
+ return JSON.stringify(value);
5405
+ }
5406
+ if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
5407
+ if (value && typeof value === "object") return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`).join(",")}}`;
5408
+ throw new TypeError("private_ledger_non_json_value");
5409
+ };
5410
+ const digestRecord = (record$2) => sha256(canonical(record$2));
5411
+ const sessionDigest = (sessionId) => sha256(`dsh-completion-guard/private-ledger/v1\0${sessionId}`);
5412
+ const contextDigest = (context, root) => sha256(canonical({
5413
+ session_sha256: sessionDigest(context.sessionId),
5414
+ session_header: context.sessionHeader,
5415
+ cwd_sha256: sha256(context.cwd),
5416
+ host_lock_sha256: context.hostLockDigest,
5417
+ ledger_root_sha256: sha256(realpathSync(root))
5418
+ }));
5419
+ const ledgerPath = (root, context) => join(root, `${sessionDigest(context.sessionId)}.jsonl`);
5420
+ const anchorPath = (root) => join(root, "session-anchors.v1.jsonl");
5421
+ const rootLockPath = (root) => join(root, ".writer.lock");
5422
+ const privateLedgerContractDigest = (contract) => {
5423
+ if (!contract || typeof contract !== "object" || Array.isArray(contract)) return sha256(canonical(contract));
5424
+ const { revokedAtSeq: _mutableRevocation,...immutable } = contract;
5425
+ return sha256(canonical(immutable));
5426
+ };
5427
+ const privateLedgerTargetDigest = (target) => sha256(canonical(target));
5428
+ /** Mirrors the audited dsh-home-paths precedence without importing another host package. */
5429
+ function resolvePrivateLedgerRoot(configured, envHome, osHome) {
5430
+ const selected = configured ?? (envHome?.trim() ? envHome : join(osHome, ".dsh"));
5431
+ if (!selected || !osHome) return void 0;
5432
+ return join(resolve(selected === "~" ? osHome : selected.startsWith("~/") || selected.startsWith("~\\") ? join(osHome, selected.slice(2)) : selected), "completion-guard", "private-ledger-v1");
5433
+ }
5434
+ function ensureRoot(root) {
5435
+ if (resolve(root) !== root) throw new Error("private_ledger_root_not_normalized");
5436
+ mkdirSync(root, {
5437
+ recursive: true,
5438
+ mode: 448
5439
+ });
5440
+ const stat = lstatSync(root);
5441
+ if (!stat.isDirectory() || stat.isSymbolicLink()) throw new Error("private_ledger_root_unsafe");
5442
+ }
5443
+ function openRegular(path, flags, mode = 384) {
5444
+ const fd = openSync(path, flags | (process.platform === "win32" ? 0 : constants.O_NOFOLLOW), mode);
5445
+ const stat = fstatSync(fd);
5446
+ if (!stat.isFile()) {
5447
+ closeSync(fd);
5448
+ throw new Error("private_ledger_file_unsafe");
5449
+ }
5450
+ if (process.platform !== "win32" && (stat.mode & 63) !== 0) fchmodSync(fd, 384);
5451
+ return fd;
5452
+ }
5453
+ function writeAll(fd, text) {
5454
+ const bytes = Buffer.from(text);
5455
+ let offset = 0;
5456
+ while (offset < bytes.length) {
5457
+ const written = writeSync(fd, bytes, offset, bytes.length - offset);
5458
+ if (written <= 0) throw new Error("private_ledger_partial_write");
5459
+ offset += written;
5460
+ }
5461
+ }
5462
+ function syncDirectory(root) {
5463
+ if (process.platform === "win32") return;
5464
+ const fd = openSync(root, constants.O_RDONLY);
5465
+ try {
5466
+ fsyncSync(fd);
5467
+ } finally {
5468
+ closeSync(fd);
5469
+ }
5470
+ }
5471
+ function readAnchors(root) {
5472
+ const path = anchorPath(root);
5473
+ if (!existsSync(path)) return /* @__PURE__ */ new Map();
5474
+ const fd = openRegular(path, constants.O_RDONLY);
5475
+ let raw;
5476
+ try {
5477
+ raw = readFileSync(fd, "utf8");
5478
+ } finally {
5479
+ closeSync(fd);
5480
+ }
5481
+ if (raw && !raw.endsWith("\n")) throw new Error("private_ledger_anchor_truncated");
5482
+ const anchors = /* @__PURE__ */ new Map();
5483
+ for (const line of raw.split("\n").filter(Boolean)) {
5484
+ const value = JSON.parse(line);
5485
+ const unsigned = {
5486
+ version: 1,
5487
+ session_sha256: value.session_sha256,
5488
+ context_sha256: value.context_sha256
5489
+ };
5490
+ 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");
5491
+ const existing = anchors.get(value.session_sha256);
5492
+ if (existing && existing !== value.context_sha256) throw new Error("private_ledger_anchor_conflict");
5493
+ anchors.set(value.session_sha256, value.context_sha256);
5494
+ }
5495
+ return anchors;
5496
+ }
5497
+ function readPrivateLedger(root, input) {
5498
+ if (!root) return {
5499
+ records: [],
5500
+ damaged: true,
5501
+ anchored: false
5502
+ };
5503
+ try {
5504
+ const context = normalizeContext(input);
5505
+ if (!existsSync(root)) return {
5506
+ records: [],
5507
+ damaged: false,
5508
+ anchored: false
5509
+ };
5510
+ const rootStat = lstatSync(root);
5511
+ if (!rootStat.isDirectory() || rootStat.isSymbolicLink()) return {
5512
+ records: [],
5513
+ damaged: true,
5514
+ anchored: false
5515
+ };
5516
+ const session = sessionDigest(context.sessionId);
5517
+ const expectedContext = contextDigest(context, root);
5518
+ const anchored = readAnchors(root).get(session);
5519
+ if (anchored !== void 0 && anchored !== expectedContext) return {
5520
+ records: [],
5521
+ damaged: true,
5522
+ anchored: true
5523
+ };
5524
+ const path = ledgerPath(root, context);
5525
+ if (!existsSync(path)) return {
5526
+ records: [],
5527
+ damaged: anchored !== void 0,
5528
+ anchored: anchored !== void 0
5529
+ };
5530
+ if (anchored === void 0) return {
5531
+ records: [],
5532
+ damaged: true,
5533
+ anchored: false
5534
+ };
5535
+ const fd = openRegular(path, constants.O_RDONLY);
5536
+ let raw;
5537
+ try {
5538
+ raw = readFileSync(fd, "utf8");
5539
+ } finally {
5540
+ closeSync(fd);
5541
+ }
5542
+ if (raw && !raw.endsWith("\n")) return {
5543
+ records: [],
5544
+ damaged: true,
5545
+ anchored: true
5546
+ };
5547
+ const records = [];
5548
+ let prior = null;
5549
+ for (const [index, line] of raw.split("\n").filter(Boolean).entries()) {
5550
+ const value = JSON.parse(line);
5551
+ const { record_sha256,...unsigned } = value;
5552
+ if (value.version !== 1 || value.session_sha256 !== session || value.context_sha256 !== expectedContext || value.position !== index + 1 || value.prior_sha256 !== prior || ![
5553
+ "release_reservation",
5554
+ "release_settlement",
5555
+ "restart_intent"
5556
+ ].includes(value.kind) || !value.payload || typeof value.payload !== "object" || Array.isArray(value.payload) || record_sha256 !== digestRecord(unsigned)) return {
5557
+ records: [],
5558
+ damaged: true,
5559
+ anchored: true
5560
+ };
5561
+ records.push(value);
5562
+ prior = record_sha256;
5563
+ }
5564
+ return {
5565
+ records,
5566
+ damaged: false,
5567
+ anchored: true
5568
+ };
5569
+ } catch {
5570
+ return {
5571
+ records: [],
5572
+ damaged: true,
5573
+ anchored: false
5574
+ };
5575
+ }
5576
+ }
5577
+ /** Establish the provider-invisible anchor when a live runtime observes a new adoption. */
5578
+ function initializePrivateLedger(root, input) {
5579
+ if (!root) return false;
5580
+ let lockFd;
5581
+ try {
5582
+ const context = normalizeContext(input);
5583
+ ensureRoot(root);
5584
+ lockFd = openRegular(rootLockPath(root), constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL);
5585
+ const session = sessionDigest(context.sessionId);
5586
+ const expectedContext = contextDigest(context, root);
5587
+ const anchored = readAnchors(root).get(session);
5588
+ if (anchored !== void 0) return anchored === expectedContext;
5589
+ const unsignedAnchor = {
5590
+ version: 1,
5591
+ session_sha256: session,
5592
+ context_sha256: expectedContext
5593
+ };
5594
+ const fd = openRegular(anchorPath(root), constants.O_WRONLY | constants.O_CREAT | constants.O_APPEND);
5595
+ try {
5596
+ writeAll(fd, `${canonical({
5597
+ ...unsignedAnchor,
5598
+ anchor_sha256: sha256(canonical(unsignedAnchor))
5599
+ })}\n`);
5600
+ fsyncSync(fd);
5601
+ } finally {
5602
+ closeSync(fd);
5603
+ }
5604
+ const ledgerFd = openRegular(ledgerPath(root, context), constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL);
5605
+ try {
5606
+ fsyncSync(ledgerFd);
5607
+ } finally {
5608
+ closeSync(ledgerFd);
5609
+ }
5610
+ syncDirectory(root);
5611
+ return true;
5612
+ } catch {
5613
+ return false;
5614
+ } finally {
5615
+ if (lockFd !== void 0) {
5616
+ try {
5617
+ closeSync(lockFd);
5618
+ } catch {}
5619
+ try {
5620
+ unlinkSync(rootLockPath(root));
5621
+ } catch {}
5622
+ }
5623
+ }
5624
+ }
5625
+ function appendPrivateLedger(root, input, kind, payload) {
5626
+ if (!root) return false;
5627
+ let lockFd;
5628
+ try {
5629
+ const context = normalizeContext(input);
5630
+ ensureRoot(root);
5631
+ lockFd = openRegular(rootLockPath(root), constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL);
5632
+ const session = sessionDigest(context.sessionId);
5633
+ const expectedContext = contextDigest(context, root);
5634
+ const anchored = readAnchors(root).get(session);
5635
+ if (anchored !== void 0 && anchored !== expectedContext) return false;
5636
+ const snapshot = anchored === void 0 ? {
5637
+ records: [],
5638
+ damaged: false
5639
+ } : readPrivateLedger(root, context);
5640
+ if (snapshot.damaged) return false;
5641
+ if (anchored === void 0) {
5642
+ const unsignedAnchor = {
5643
+ version: 1,
5644
+ session_sha256: session,
5645
+ context_sha256: expectedContext
5646
+ };
5647
+ const fd$1 = openRegular(anchorPath(root), constants.O_WRONLY | constants.O_CREAT | constants.O_APPEND);
5648
+ try {
5649
+ writeAll(fd$1, `${canonical({
5650
+ ...unsignedAnchor,
5651
+ anchor_sha256: sha256(canonical(unsignedAnchor))
5652
+ })}\n`);
5653
+ fsyncSync(fd$1);
5654
+ } finally {
5655
+ closeSync(fd$1);
5656
+ }
5657
+ syncDirectory(root);
5658
+ }
5659
+ if (kind === "release_settlement") {
5660
+ const settlement = normalizeSettlement(payload);
5661
+ 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);
5662
+ if (!reservation) return false;
5663
+ payload = {
5664
+ ...payload,
5665
+ reservation_sha256: reservation.record_sha256,
5666
+ contract_sha256: reservation.payload.contract_sha256,
5667
+ target_sha256: reservation.payload.target_sha256
5668
+ };
5669
+ }
5670
+ const unsigned = {
5671
+ version: 1,
5672
+ session_sha256: session,
5673
+ context_sha256: expectedContext,
5674
+ position: snapshot.records.length + 1,
5675
+ prior_sha256: snapshot.records.at(-1)?.record_sha256 ?? null,
5676
+ kind,
5677
+ payload
5678
+ };
5679
+ const record$2 = {
5680
+ ...unsigned,
5681
+ record_sha256: digestRecord(unsigned)
5682
+ };
5683
+ const fd = openRegular(ledgerPath(root, context), constants.O_WRONLY | constants.O_CREAT | constants.O_APPEND);
5684
+ try {
5685
+ writeAll(fd, `${canonical(record$2)}\n`);
5686
+ fsyncSync(fd);
5687
+ } finally {
5688
+ closeSync(fd);
5689
+ }
5690
+ syncDirectory(root);
5691
+ return true;
5692
+ } catch {
5693
+ return false;
5694
+ } finally {
5695
+ if (lockFd !== void 0) {
5696
+ try {
5697
+ closeSync(lockFd);
5698
+ } catch {}
5699
+ try {
5700
+ unlinkSync(rootLockPath(root));
5701
+ } catch {}
5702
+ }
5703
+ }
5704
+ }
5705
+ function applyPrivateLedger(projection, snapshot) {
5706
+ if (snapshot.damaged || projection.releaseContracts.length > 0 && snapshot.anchored === false) {
5707
+ projection.releaseStateDamaged = true;
5708
+ if (!projection.releaseDiagnostics.some((row) => row.reasonCode === "private_ledger_damaged")) projection.releaseDiagnostics.push({
5709
+ seq: 0,
5710
+ reasonCode: "private_ledger_damaged"
5711
+ });
5712
+ return;
5713
+ }
5714
+ const reservations = /* @__PURE__ */ new Map();
5715
+ for (const record$2 of snapshot.records) if (record$2.kind === "release_reservation") {
5716
+ const normalized = normalizeReservation(record$2.payload);
5717
+ const contract = normalized && projection.releaseContracts.find((entry) => entry.contractId === normalized.contractId);
5718
+ if (!normalized || !contract || record$2.payload.contract_sha256 !== privateLedgerContractDigest(contract) || typeof record$2.payload.target_sha256 !== "string") {
5719
+ projection.releaseStateDamaged = true;
5720
+ continue;
5721
+ }
5722
+ const key = `${normalized.contractId}\0${normalized.operation}\0${normalized.callId}`;
5723
+ if (reservations.has(key)) {
5724
+ projection.releaseStateDamaged = true;
5725
+ continue;
5726
+ }
5727
+ reservations.set(key, record$2);
5728
+ const existing = projection.releaseReservations.find((entry) => entry.callId === normalized.callId);
5729
+ if (existing && (existing.contractId !== normalized.contractId || existing.operation !== normalized.operation)) {
5730
+ projection.releaseStateDamaged = true;
5731
+ continue;
5732
+ }
5733
+ if (!existing) projection.releaseReservations.push({
5734
+ ...normalized,
5735
+ startedAtSeq: 0,
5736
+ ledgerPosition: record$2.position
5737
+ });
5738
+ } else if (record$2.kind === "release_settlement") {
5739
+ const normalized = normalizeSettlement(record$2.payload);
5740
+ const key = normalized && `${normalized.contractId}\0${normalized.operation}\0${normalized.callId}`;
5741
+ const reservationRecord = key ? reservations.get(key) : void 0;
5742
+ const contract = normalized && projection.releaseContracts.find((entry) => entry.contractId === normalized.contractId);
5743
+ const source = record$2.payload.settlement_source;
5744
+ const readbackVerdict = normalized && contract ? readbackSettlesContract(contract, normalized.readback, reservationRecord ? normalizeReservation(reservationRecord.payload)?.observedArtifactSri : void 0) : void 0;
5745
+ 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") {
5746
+ projection.releaseStateDamaged = true;
5747
+ continue;
5748
+ }
5749
+ const pinned = {
5750
+ ...normalized,
5751
+ settledAtSeq: 0,
5752
+ ledgerPosition: record$2.position
5753
+ };
5754
+ const index = projection.releaseSettlements.findIndex((entry) => entry.contractId === pinned.contractId && entry.operation === pinned.operation && entry.callId === pinned.callId);
5755
+ if (index < 0) projection.releaseSettlements.push(pinned);
5756
+ else if (OUTCOME_STRENGTH[pinned.outcome] >= OUTCOME_STRENGTH[projection.releaseSettlements[index].outcome]) projection.releaseSettlements[index] = pinned;
5757
+ }
5758
+ }
5759
+ function hasPrivateRestartIntent(snapshot, resolutionCallId, serviceId, preGeneration) {
5760
+ 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);
5761
+ }
5762
+
4631
5763
  //#endregion
4632
5764
  //#region src/runtime.ts
4633
5765
  const name = "context-guard";
4634
- const inject = ["sessions", "commands"];
5766
+ const inject = [
5767
+ "sessions",
5768
+ "commands",
5769
+ "fs"
5770
+ ];
4635
5771
  /**
4636
5772
  * Bind an explicit mutation to one live root-owned contract item. Resolution
4637
5773
  * evidence is intentionally not authority: every effect rechecks the current
@@ -4884,13 +6020,13 @@ async function handleGuardTurnStopping(agent, runtime, access$1) {
4884
6020
  }
4885
6021
  return "root_pause_routed";
4886
6022
  }
4887
- const decision = decideTurnBoundary(runtime.projection);
6023
+ const decision = decideTurnBoundary(runtime.projection, rootInstruction?.text);
4888
6024
  if (decision.noProgressClaim) {
4889
- const record$1 = `${NO_PROGRESS_RECORD_PREFIX}${JSON.stringify(decision.noProgressClaim)}`;
6025
+ const record$2 = `${NO_PROGRESS_RECORD_PREFIX}${JSON.stringify(decision.noProgressClaim)}`;
4890
6026
  agent.session.append("user/message", createUserMessage({
4891
6027
  content: [{
4892
6028
  type: "text",
4893
- text: record$1
6029
+ text: record$2
4894
6030
  }],
4895
6031
  source: {
4896
6032
  kind: "plugin",
@@ -5013,10 +6149,11 @@ function sessionHeaderForDigest(session) {
5013
6149
  delegationDepth: typeof raw.delegationDepth === "number" ? raw.delegationDepth : 0
5014
6150
  };
5015
6151
  }
5016
- function createRuntime(agent, config, hostLock = DEFAULT_HOST_LOCK, readGoalState, refreshHostLock) {
6152
+ function createRuntime(agent, config, hostLock = DEFAULT_HOST_LOCK, readGoalState, refreshHostLock, readPrivateRecords, initializePrivateRecords) {
5017
6153
  const projection = createProjection();
5018
6154
  const session = agent.session;
5019
6155
  let pendingRecovery = false;
6156
+ let pendingRecoveryCauses = /* @__PURE__ */ new Set();
5020
6157
  let durabilityConfirmed = false;
5021
6158
  let durabilityWatermark = "unknown";
5022
6159
  let observedEpoch = -1;
@@ -5024,11 +6161,14 @@ function createRuntime(agent, config, hostLock = DEFAULT_HOST_LOCK, readGoalStat
5024
6161
  let observedContractRevision = -1;
5025
6162
  let protocolV4Present = false;
5026
6163
  let protocolV5Present = false;
6164
+ let protocolV6Present = false;
5027
6165
  let realRootInputSeen = false;
5028
6166
  let lifecycle = "armed";
6167
+ let synchronizedOnce = false;
5029
6168
  const continuationAttempts = projection.continuationAttempts;
5030
6169
  const persistenceCorrectionAttempts = projection.persistenceCorrectionAttempts;
5031
6170
  const rebuild = () => {
6171
+ const previousReleaseContracts = projection.releaseContracts.length;
5032
6172
  if (refreshHostLock) hostLock = refreshHostLock();
5033
6173
  const header = session.header;
5034
6174
  const priorRecoveryDigest = projection.lastRecoveryDigest;
@@ -5050,6 +6190,18 @@ function createRuntime(agent, config, hostLock = DEFAULT_HOST_LOCK, readGoalStat
5050
6190
  sessionHeader
5051
6191
  }, durabilityConfirmed, hostLock);
5052
6192
  Object.assign(projection, derived.projection);
6193
+ if (readPrivateRecords) {
6194
+ let privateSnapshot = readPrivateRecords();
6195
+ if (!synchronizedOnce && events.length === 0 && !privateSnapshot.damaged && !privateSnapshot.anchored && initializePrivateRecords?.()) privateSnapshot = readPrivateRecords();
6196
+ if (projection.releaseContracts.length > 0 && !privateSnapshot.damaged && !privateSnapshot.anchored) if (synchronizedOnce && previousReleaseContracts === 0 && initializePrivateRecords?.()) privateSnapshot = readPrivateRecords();
6197
+ else privateSnapshot = {
6198
+ records: [],
6199
+ damaged: true,
6200
+ anchored: false
6201
+ };
6202
+ applyPrivateLedger(projection, privateSnapshot);
6203
+ }
6204
+ synchronizedOnce = true;
5053
6205
  if (!sessionHeader) {
5054
6206
  projection.integrity = "unknown";
5055
6207
  if (!projection.integrityViolations.includes("session_ref_unavailable")) projection.integrityViolations.push("session_ref_unavailable");
@@ -5068,8 +6220,19 @@ function createRuntime(agent, config, hostLock = DEFAULT_HOST_LOCK, readGoalStat
5068
6220
  projection.persistenceCorrectionAttempts = persistenceCorrectionAttempts;
5069
6221
  projection.lastRecoveryDigest = priorRecoveryDigest;
5070
6222
  projection.durabilityWatermark = durabilityWatermark;
6223
+ if (projection.boundaryProtocol === 6 && durabilityWatermark === "confirmed") try {
6224
+ const displayOrigins = /* @__PURE__ */ new Map();
6225
+ projection.coreV2 = projectSessionCoreV2(session.snapshotEvents(), projection, displayOrigins);
6226
+ projection.coreV2RequirementOrigins = projection.coreV2 ? displayOrigins : void 0;
6227
+ projection.coreV2Reason = projection.coreV2 ? void 0 : "source_not_projectable";
6228
+ } catch {
6229
+ projection.coreV2 = void 0;
6230
+ projection.coreV2RequirementOrigins = void 0;
6231
+ projection.coreV2Reason = "projection_failed";
6232
+ }
5071
6233
  protocolV4Present = derived.protocolV4Present;
5072
6234
  protocolV5Present = derived.boundaryV5;
6235
+ protocolV6Present = derived.boundaryV6;
5073
6236
  realRootInputSeen = derived.realRootInputSeen;
5074
6237
  lifecycle = lifecyclePhase({
5075
6238
  enabled: projection.enabled,
@@ -5077,13 +6240,18 @@ function createRuntime(agent, config, hostLock = DEFAULT_HOST_LOCK, readGoalStat
5077
6240
  });
5078
6241
  if (observedEpoch >= 0 && derived.projection.epoch > observedEpoch) {
5079
6242
  pendingRecovery = true;
6243
+ pendingRecoveryCauses.add("guard_reenabled");
5080
6244
  projection.lastRecoveryDigest = void 0;
5081
6245
  }
5082
6246
  observedEpoch = derived.projection.epoch;
5083
- if (observedContractRevision >= 0 && projection.contractRevision !== observedContractRevision) pendingRecovery = true;
6247
+ if (observedContractRevision >= 0 && projection.contractRevision !== observedContractRevision) {
6248
+ pendingRecovery = true;
6249
+ pendingRecoveryCauses.add("contract_updated");
6250
+ }
5084
6251
  observedContractRevision = projection.contractRevision;
5085
6252
  if (derived.lastCompactionSeq > observedCompactionSeq) {
5086
6253
  pendingRecovery = true;
6254
+ pendingRecoveryCauses.add("compaction");
5087
6255
  projection.lastRecoveryDigest = void 0;
5088
6256
  observedCompactionSeq = derived.lastCompactionSeq;
5089
6257
  }
@@ -5099,12 +6267,14 @@ function createRuntime(agent, config, hostLock = DEFAULT_HOST_LOCK, readGoalStat
5099
6267
  durabilityWatermark = confirmed ? "confirmed" : "failed";
5100
6268
  projection.durabilityWatermark = durabilityWatermark;
5101
6269
  };
5102
- const markRecoveryNeeded = () => {
6270
+ const markRecoveryNeeded = (cause) => {
5103
6271
  pendingRecovery = true;
6272
+ pendingRecoveryCauses.add(cause ?? "explicit");
5104
6273
  };
5105
6274
  const consumeRecovery = () => {
5106
6275
  const was = pendingRecovery;
5107
6276
  pendingRecovery = false;
6277
+ pendingRecoveryCauses = /* @__PURE__ */ new Set();
5108
6278
  return was;
5109
6279
  };
5110
6280
  rebuild();
@@ -5120,6 +6290,12 @@ function createRuntime(agent, config, hostLock = DEFAULT_HOST_LOCK, readGoalStat
5120
6290
  get protocolV5Present() {
5121
6291
  return protocolV5Present;
5122
6292
  },
6293
+ get protocolV6Present() {
6294
+ return protocolV6Present;
6295
+ },
6296
+ get recoveryCauses() {
6297
+ return [...pendingRecoveryCauses];
6298
+ },
5123
6299
  sync,
5124
6300
  setEnabled,
5125
6301
  setDurability,
@@ -5161,7 +6337,12 @@ function revalidateCoreLock(config, expected) {
5161
6337
  goalAvailable: false,
5162
6338
  reasonCode: "host_lock_installed_graph_drift"
5163
6339
  };
5164
- return actual;
6340
+ const audited = auditedForegroundRenderers(config.hostLockRuntimeRoot, config.hostLockProfileRoot);
6341
+ return audited.length ? {
6342
+ ...actual,
6343
+ auditedForegroundRenderers: audited,
6344
+ digest: createHash("sha256").update(`dsh.core-host-renderer/v1\0${actual.digest}\0${audited.join(",")}`).digest("hex")
6345
+ } : actual;
5165
6346
  } catch {
5166
6347
  return {
5167
6348
  ...expected,
@@ -5171,6 +6352,41 @@ function revalidateCoreLock(config, expected) {
5171
6352
  };
5172
6353
  }
5173
6354
  }
6355
+ /** Observe one actual Host dispatch through Cordis without joining its gate. */
6356
+ function registerPassiveHostWorkdirObserver(agent, hostLockAtCall, attestedRouteAtCall, sourcedRootAtCall) {
6357
+ if (typeof agent.ctx.on !== "function") return;
6358
+ const pending = /* @__PURE__ */ new WeakMap();
6359
+ agent.ctx.on("tools/pre-execute", async (exec, next) => {
6360
+ if (exec.agent === agent && (exec.name === "bash" || exec.name === "pwsh")) try {
6361
+ const policy = agent.ctx.get("sandboxPolicy");
6362
+ const receipt = captureHostWorkdir(agent.session, exec, hostLockAtCall(), policy, await attestedRouteAtCall(exec.name, agent.ctx.get("shell"), policy), sourcedRootAtCall?.(exec) ?? null);
6363
+ if (receipt) pending.set(exec, receipt);
6364
+ } catch {}
6365
+ return next();
6366
+ });
6367
+ agent.ctx.on("tools/post-execute", async (exec, _result, next) => {
6368
+ const decision = await next();
6369
+ const receipt = pending.get(exec);
6370
+ pending.delete(exec);
6371
+ if (!receipt || exec.agent !== agent) return decision;
6372
+ const context = createUserMessage({
6373
+ content: [{
6374
+ type: "text",
6375
+ text: `${HOST_WORKDIR_PREFIX}${JSON.stringify(receipt)}`
6376
+ }],
6377
+ source: {
6378
+ kind: "plugin",
6379
+ plugin: "context-guard",
6380
+ form: "notice",
6381
+ summary: "read-only Host workdir observation"
6382
+ }
6383
+ });
6384
+ return {
6385
+ ...decision,
6386
+ additionalContexts: [...decision.additionalContexts ?? [], context]
6387
+ };
6388
+ });
6389
+ }
5174
6390
  function apply(ctx, rawConfig = {}, seams = {}) {
5175
6391
  const config = resolveConfig(rawConfig);
5176
6392
  const installedHostLock = seams.hostLock ?? evaluateHostLock(config.hostLockPackages ?? [], {
@@ -5178,7 +6394,14 @@ function apply(ctx, rawConfig = {}, seams = {}) {
5178
6394
  profileKind: config.hostLockProfile
5179
6395
  });
5180
6396
  const runtimes = /* @__PURE__ */ new Map();
6397
+ const privateLedgerRoot = seams.privateLedgerRoot ?? resolvePrivateLedgerRoot(void 0, process.env.DSH_HOME, homedir());
5181
6398
  const hostLocks = /* @__PURE__ */ new Map();
6399
+ const ledgerContext = (agent, fallback = installedHostLock) => ({
6400
+ sessionId: String(agent.session.id),
6401
+ sessionHeader: structuredClone(agent.session.header),
6402
+ cwd: sessionCwd(agent.session) ?? "",
6403
+ hostLockDigest: (hostLocks.get(agent) ?? fallback).digest
6404
+ });
5182
6405
  const registeredAgents = /* @__PURE__ */ new WeakSet();
5183
6406
  const ensure = (agent) => {
5184
6407
  let runtime = runtimes.get(agent);
@@ -5190,7 +6413,7 @@ function apply(ctx, rawConfig = {}, seams = {}) {
5190
6413
  return current;
5191
6414
  };
5192
6415
  const agentHostLock = refreshHostLock();
5193
- runtime = createRuntime(agent, config, agentHostLock, goals ? () => goals.get(agent) : void 0, refreshHostLock);
6416
+ 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
6417
  runtimes.set(agent, runtime);
5195
6418
  hostLocks.set(agent, agentHostLock);
5196
6419
  }
@@ -5202,17 +6425,21 @@ function apply(ctx, rawConfig = {}, seams = {}) {
5202
6425
  runtime.sync();
5203
6426
  if (source === "resume" || source === "compact") {
5204
6427
  runtime.projection.lastRecoveryDigest = void 0;
5205
- runtime.markRecoveryNeeded();
6428
+ runtime.markRecoveryNeeded(source === "resume" ? "resume" : "compaction");
5206
6429
  }
5207
6430
  if (registeredAgents.has(agent)) return;
5208
6431
  registeredAgents.add(agent);
6432
+ registerPassiveHostWorkdirObserver(agent, () => seams.hostLock ?? revalidateCoreLock(config, installedHostLock), (tool, provider, policy) => config.hostLockRuntimeRoot && config.hostLockProfileRoot ? auditedDefaultWorkdirProvider(config.hostLockRuntimeRoot, config.hostLockProfileRoot, tool, provider, policy) : false, (exec) => {
6433
+ runtime.sync();
6434
+ return sourcedNamedTestRoot(runtime.projection, agent.session, exec.arguments);
6435
+ });
5209
6436
  agent.ctx.tools.register(createRebindTool(() => runtime.projection, async () => {
5210
6437
  const durable = await ctx.sessions.flush(agent.session);
5211
6438
  runtime.setDurability(durable);
5212
6439
  runtime.sync();
5213
6440
  return durable;
5214
6441
  }));
5215
- agent.ctx.tools.register(createCheckpointTool(() => runtime.projection, () => runtime.markRecoveryNeeded(), async () => {
6442
+ agent.ctx.tools.register(createCheckpointTool(() => runtime.projection, () => runtime.markRecoveryNeeded("checkpoint_followup"), async () => {
5216
6443
  const durable = await ctx.sessions.flush(agent.session);
5217
6444
  runtime.setDurability(durable);
5218
6445
  runtime.sync();
@@ -5223,34 +6450,12 @@ function apply(ctx, rawConfig = {}, seams = {}) {
5223
6450
  runtime.setDurability(durable);
5224
6451
  runtime.sync();
5225
6452
  return durable;
5226
- }, () => 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);
6453
+ }, () => runtime.markRecoveryNeeded("boundary_update")));
6454
+ /** Persist release state outside provider-visible Session history. */
6455
+ const persistReleaseRecord = async (toolAgent, kind, payload) => {
6456
+ if (toolAgent.session !== agent.session) return false;
6457
+ if (!sessionCwd(agent.session)) return false;
6458
+ const durable = appendPrivateLedger(privateLedgerRoot, ledgerContext(agent), kind, payload);
5254
6459
  runtime.sync();
5255
6460
  return durable;
5256
6461
  };
@@ -5271,12 +6476,13 @@ function apply(ctx, rawConfig = {}, seams = {}) {
5271
6476
  return authorizeMutationFromProjection(runtime.projection, request);
5272
6477
  },
5273
6478
  marketOrigin: optionalMarketOrigin(ctx, agent),
6479
+ hasRestartIntent: (resolutionCallId, serviceId, preGeneration) => hasPrivateRestartIntent(readPrivateLedger(privateLedgerRoot, ledgerContext(agent)), resolutionCallId, serviceId, preGeneration),
5274
6480
  releaseGate: async (request) => {
5275
6481
  runtime.sync();
5276
6482
  const projection = runtime.projection;
5277
6483
  if (!(projection.policy === "release" || projection.releaseContracts.length > 0)) return {
5278
- status: "granted",
5279
- reasonCode: "release_profile_not_adopted"
6484
+ status: "denied",
6485
+ reasonCode: "release_contract_not_adopted"
5280
6486
  };
5281
6487
  const observed = { ...request.observed };
5282
6488
  const declaredRef = releaseContractFor(projection, request.operation)?.candidate.ref;
@@ -5297,12 +6503,19 @@ function apply(ctx, rawConfig = {}, seams = {}) {
5297
6503
  status: "denied",
5298
6504
  reasonCode: decision.reasonCode
5299
6505
  };
5300
- return await persistReleaseRecord(agent, RELEASE_RESERVATION_PREFIX, {
6506
+ const grantedContract = projection.releaseContracts.find((entry) => entry.contractId === decision.contractId);
6507
+ if (!grantedContract) return {
6508
+ status: "denied",
6509
+ reasonCode: "release_state_damaged"
6510
+ };
6511
+ return await persistReleaseRecord(agent, "release_reservation", {
5301
6512
  contractId: decision.contractId,
5302
6513
  operation: request.operation,
5303
6514
  callId: request.callId,
5304
6515
  startedAtSeq: 0,
5305
6516
  status: "in_flight",
6517
+ contract_sha256: privateLedgerContractDigest(grantedContract),
6518
+ target_sha256: privateLedgerTargetDigest(request.resolvedTarget),
5306
6519
  ...observed.artifactSri !== void 0 ? { observedArtifactSri: observed.artifactSri } : {}
5307
6520
  }) ? {
5308
6521
  status: "granted",
@@ -5319,40 +6532,41 @@ function apply(ctx, rawConfig = {}, seams = {}) {
5319
6532
  const reservation = reservationFor(runtime.projection, contractId, request.callId);
5320
6533
  let outcome = request.effect === "not_effected" ? "not_effected" : "unknown";
5321
6534
  if (request.effect === "completed" && contract) outcome = readbackSettlesContract(contract, request.readback, reservation?.observedArtifactSri) === "settled" ? "settled" : "unknown";
5322
- await persistReleaseRecord(agent, RELEASE_SETTLEMENT_PREFIX, {
6535
+ await persistReleaseRecord(agent, "release_settlement", {
5323
6536
  contractId,
5324
6537
  operation: request.operation,
5325
6538
  callId: request.callId,
5326
6539
  settledAtSeq: 0,
5327
6540
  readback: request.readback,
5328
- outcome
6541
+ outcome,
6542
+ settlement_source: "effect"
5329
6543
  });
5330
6544
  },
5331
6545
  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);
6546
+ if (toolAgent.session !== agent.session) return false;
6547
+ if (!sessionCwd(agent.session)) return false;
6548
+ const snapshot = readPrivateLedger(privateLedgerRoot, ledgerContext(agent));
6549
+ if (snapshot.damaged || !snapshot.anchored) return false;
6550
+ const durable = appendPrivateLedger(privateLedgerRoot, ledgerContext(agent), "restart_intent", {
6551
+ resolution_call_id: intent.resolutionCallId,
6552
+ service_id: intent.serviceId,
6553
+ pre_generation: intent.preGeneration
6554
+ });
5351
6555
  runtime.sync();
5352
6556
  return durable;
5353
6557
  }
5354
6558
  };
5355
6559
  agent.ctx.tools.register(createEvidenceTool(evidenceOptions));
6560
+ agent.ctx.tools.register(createNativeFileObserver({
6561
+ fs: ctx.fs,
6562
+ flush: (session) => ctx.sessions.flush(session)
6563
+ }));
6564
+ agent.ctx.tools.register(createNativeGitObserver({ flush: (session) => ctx.sessions.flush(session) }));
6565
+ agent.ctx.tools.register(createTestReadinessObserver({
6566
+ getProjection: () => runtime.projection,
6567
+ fs: ctx.fs,
6568
+ flush: (session) => ctx.sessions.flush(session)
6569
+ }));
5356
6570
  agent.ctx.tools.register(createActionTool(evidenceOptions));
5357
6571
  agent.ctx.tools.register(createPrepareTool({
5358
6572
  getProjection: () => runtime.projection,
@@ -5384,13 +6598,14 @@ function apply(ctx, rawConfig = {}, seams = {}) {
5384
6598
  getProjection: () => runtime.projection,
5385
6599
  fetcher: evidenceOptions.fetcher,
5386
6600
  ...evidenceOptions.allowLoopbackHttpRegistry ? { allowLoopbackHttpRegistry: true } : {},
5387
- persistSettlement: async (request) => persistReleaseRecord(request.agent, RELEASE_SETTLEMENT_PREFIX, {
6601
+ persistSettlement: async (request) => persistReleaseRecord(request.agent, "release_settlement", {
5388
6602
  contractId: request.contractId,
5389
6603
  operation: request.operation,
5390
6604
  callId: request.callId,
5391
6605
  settledAtSeq: 0,
5392
6606
  readback: request.readback,
5393
- outcome: request.outcome
6607
+ outcome: request.outcome,
6608
+ settlement_source: "reconcile"
5394
6609
  })
5395
6610
  }));
5396
6611
  agent.ctx.tools.register(createExternalOperationTool((id, toolAgent) => readExternalOperation(ctx, toolAgent, id), () => evaluateExternalWaitCapability(hostLocks.get(agent) ?? installedHostLock)));
@@ -5405,11 +6620,13 @@ function apply(ctx, rawConfig = {}, seams = {}) {
5405
6620
  if (decision.kind !== "enter") return decision;
5406
6621
  const injected = [];
5407
6622
  const delegated = isDelegatedSession(agent.session);
5408
- let boundaryPending = !runtime.protocolV5Present;
6623
+ let boundaryPending = !runtime.protocolV6Present;
5409
6624
  const firstStep = previewFirstStepInjection({
5410
6625
  activation: config.activation,
5411
6626
  enabled: runtime.projection.enabled,
5412
6627
  boundaryV5Present: runtime.protocolV5Present,
6628
+ boundaryV6Present: runtime.protocolV6Present,
6629
+ targetProtocol: 6,
5413
6630
  boundaryPresent: runtime.protocolV4Present,
5414
6631
  delegated,
5415
6632
  policy: runtime.projection.policy
@@ -5419,21 +6636,25 @@ function apply(ctx, rawConfig = {}, seams = {}) {
5419
6636
  if (runtime.lifecycle === "armed") injected.push(pluginNoticeMessage(firstStep.guidance, "Context Guard first-step protection guidance"));
5420
6637
  boundaryPending = false;
5421
6638
  }
6639
+ const armedRecoveryCauses = runtime.recoveryCauses ?? [];
5422
6640
  if (runtime.projection.enabled && runtime.consumeRecovery()) {
5423
- const hasOpenWork = [...runtime.projection.items.values()].some((item) => item.status === "pending");
5424
- const hasRejections = (runtime.projection.lastCheckpointRejections?.length ?? 0) > 0;
6641
+ const current = currentV6Feedback(runtime.projection);
6642
+ const standingConstraints = current ? Object.values(current.predicates).filter((state) => state === "constraint_active").length : 0;
6643
+ const hasOpenWork = current ? current.status !== "observed" || standingConstraints > 0 : [...runtime.projection.items.values()].some((item) => item.status === "pending");
6644
+ const hasRejections = current === void 0 && (runtime.projection.lastCheckpointRejections?.length ?? 0) > 0;
5425
6645
  const recovery = hasOpenWork || hasRejections ? renderRecoveryPacket(runtime.projection, { charBudget: 4e3 }) : void 0;
5426
6646
  const digest$2 = recovery ? recoveryDigest(recovery, runtime.projection) : void 0;
5427
6647
  if (recovery && digest$2 !== runtime.projection.lastRecoveryDigest) {
5428
6648
  runtime.projection.lastRecoveryDigest = digest$2;
5429
6649
  if (boundaryPending && !delegated) {
5430
- injected.push(pluginNoticeMessage(PROTOCOL_V5_NOTICE, "Context Guard recorded a replay version boundary"));
6650
+ injected.push(pluginNoticeMessage(PROTOCOL_V6_NOTICE, "Context Guard recorded a replay version boundary"));
5431
6651
  boundaryPending = false;
5432
6652
  }
6653
+ const title = recoveryTitle(armedRecoveryCauses);
5433
6654
  injected.push(createUserMessage({
5434
6655
  content: [{
5435
6656
  type: "text",
5436
- text: `Open task requirements (recovered after compaction or resume):\n${recovery}`
6657
+ text: `${title}\n${recovery}`
5437
6658
  }],
5438
6659
  source: {
5439
6660
  kind: "plugin",
@@ -5548,12 +6769,12 @@ function optionalGoalService(ctx, agent) {
5548
6769
  }
5549
6770
  function normalizeGoalState(value) {
5550
6771
  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;
6772
+ const record$2 = value;
6773
+ const goal = record$2.goal && typeof record$2.goal === "object" ? record$2.goal : record$2;
5553
6774
  const id = goal.id;
5554
6775
  const revision = goal.revision;
5555
6776
  const phase = goal.phase;
5556
- const activation = record$1.activation ?? goal.activation;
6777
+ const activation = record$2.activation ?? goal.activation;
5557
6778
  if (typeof id !== "string" || typeof revision !== "number") return void 0;
5558
6779
  if (![
5559
6780
  "active",
@@ -5571,4 +6792,112 @@ function normalizeGoalState(value) {
5571
6792
  }
5572
6793
 
5573
6794
  //#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 };
6795
+ //#region src/raw-replay.ts
6796
+ /** Local synthetic replay using the actual Session, derivation and registered
6797
+ * Stop handler. It neither executes tools nor asserts a real model outcome. */
6798
+ async function replayRawV2(input) {
6799
+ const cwd = input.cwd ?? "/work";
6800
+ const id = SessionId("raw-v2-replay");
6801
+ const session = Session.create(id, void 0, {
6802
+ version: SESSION_FORMAT_VERSION,
6803
+ isSeeded: false,
6804
+ id,
6805
+ createdAt: 1,
6806
+ cwd
6807
+ });
6808
+ session.append("user/message", createUserMessage({
6809
+ content: [{
6810
+ type: "text",
6811
+ text: PROTOCOL_V6_NOTICE
6812
+ }],
6813
+ source: {
6814
+ kind: "plugin",
6815
+ plugin: "context-guard",
6816
+ form: "notice",
6817
+ summary: "v6 replay boundary"
6818
+ }
6819
+ }), { surfaceOp: "append" });
6820
+ session.append("turn/start", { turn: 1 });
6821
+ session.append("user/message", createUserMessage({
6822
+ content: [{
6823
+ type: "text",
6824
+ text: input.root
6825
+ }],
6826
+ source: { kind: "user" }
6827
+ }), { surfaceOp: "append" });
6828
+ const appendEvent = session.append.bind(session);
6829
+ for (const event of input.events ?? []) {
6830
+ if (event.type === "turn/end") throw new Error("turn/end is emitted only after the Stop callback in this replay");
6831
+ appendEvent(event.type, event.data, event.type === "tool/call" ? void 0 : { surfaceOp: "append" });
6832
+ }
6833
+ session.append("assistant/message", {
6834
+ turn: 1,
6835
+ step: 1,
6836
+ message: {
6837
+ role: "assistant",
6838
+ content: [{
6839
+ type: "text",
6840
+ text: input.final
6841
+ }]
6842
+ }
6843
+ }, { surfaceOp: "append" });
6844
+ const lock = evaluateHostLock(EXPECTED_HOST_PACKAGES, {
6845
+ platform: "posix",
6846
+ profileKind: "web"
6847
+ });
6848
+ const steers = [];
6849
+ const agent = {
6850
+ session,
6851
+ steer: (message) => {
6852
+ steers.push(message);
6853
+ }
6854
+ };
6855
+ const runtime = createRuntime(agent, { activation: "always" }, lock, () => void 0);
6856
+ runtime.setDurability(true);
6857
+ runtime.sync();
6858
+ const snapshot = sessionCoreSnapshot(session.snapshotEvents(), runtime.projection);
6859
+ const stopCore = runtime.projection.coreV2 ?? null;
6860
+ const stop = await handleGuardTurnStopping(agent, runtime, {
6861
+ flush: async () => true,
6862
+ hostSupported: true,
6863
+ readExternalOperation: () => void 0
6864
+ });
6865
+ session.append("turn/end", {
6866
+ turn: 1,
6867
+ reason: { kind: "completed" }
6868
+ });
6869
+ runtime.sync();
6870
+ const projection = runtime.projection;
6871
+ const postSnapshot = sessionCoreSnapshot(session.snapshotEvents(), projection);
6872
+ return {
6873
+ stop_core_snapshot: snapshot ?? null,
6874
+ stop_core_projection: stopCore,
6875
+ stop,
6876
+ post_turn_core_snapshot: postSnapshot ?? null,
6877
+ post_turn_core_projection: projection.coreV2 ?? null,
6878
+ goal_complete_denial: goalCompletionDenial(projection, "update_goal", {
6879
+ action: "complete",
6880
+ goal_id: projection.currentGoalRef?.id,
6881
+ revision: projection.currentGoalRef?.revision
6882
+ }) ?? null,
6883
+ assistant_observation: observeAssistantOutcome(input.final),
6884
+ steers: steers.length,
6885
+ items: [...projection.items.values()].map((item) => ({
6886
+ id: item.id,
6887
+ status: item.status,
6888
+ action: item.semanticAction,
6889
+ authority: item.authority,
6890
+ disposition: item.authorityDisposition,
6891
+ review: item.needsReview?.reason ?? null
6892
+ })),
6893
+ durable_seq: session.seq,
6894
+ event_types: session.snapshotEvents().map((event) => ({
6895
+ seq: event.seq,
6896
+ type: event.type
6897
+ })),
6898
+ boundary_protocol: projection.boundaryProtocol
6899
+ };
6900
+ }
6901
+
6902
+ //#endregion
6903
+ 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, V6_ORDINARY_COMPLETION_RULE, V6_ORDINARY_COMPLETION_RULE_COMPACT, V6_ORDINARY_COMPLETION_RULE_SHORT, 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, recoveryTitle, 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, v6CurrentRootBoundaries, v6TestPredicate, validateActionManifest, validateActionTarget, validateManifest, validateProofManifest, validateProofManifestV2, verbIsNegated, verifiedLinearCommitReadback, verifyComposedHostLockDump, withDurability };