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/CHANGELOG.md +38 -1
- package/CHANGELOG.zh-CN.md +38 -1
- package/README.md +30 -157
- package/README.zh-CN.md +24 -52
- package/dist/domain/index.d.ts +2 -2
- package/dist/domain/index.js +2 -2
- package/dist/{domain-BUA1lLjs.js → domain-DbPbaoXp.js} +10103 -5654
- package/dist/{index-CfEiC4bb.d.ts → index-hiUtfKJa.d.ts} +208 -8
- package/dist/index.d.ts +22 -4
- package/dist/index.js +1509 -180
- package/docs/ARCHITECTURE.md +43 -9
- package/docs/COMPATIBILITY.md +6 -0
- package/docs/CONTRACT_REVISION_0_6_3.md +2 -2
- package/docs/CORE_ALIGNMENT_CONTRACT_V2.md +155 -0
- package/docs/CORE_ALIGNMENT_PLAN_REVIEW.json +144 -0
- package/docs/DEVELOPMENT_PLAN_0_7_0.md +93 -0
- package/docs/LOCAL_ACCEPTANCE.md +21 -1
- package/docs/PRIVACY.md +11 -0
- package/docs/README.md +20 -0
- package/docs/RELEASE_NOTES_0_7_1.md +21 -0
- package/docs/SEMANTIC_COMPATIBILITY.md +11 -0
- package/package.json +2 -2
- package/docs/DEVELOPMENT_HANDOFF_0_6_3.json +0 -65
- package/docs/DEVELOPMENT_PLAN_0_6_2.md +0 -86
- package/docs/DEVELOPMENT_PLAN_0_6_3.md +0 -103
- package/docs/EXECUTE_0_6_3_PROMPT.md +0 -62
- package/docs/RELEASE_PLAN_0_6_2.md +0 -41
- package/docs/REVIEW_0_6_2_CORE_ALIGNMENT.md +0 -87
package/dist/index.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { $ as
|
|
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: "
|
|
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
|
|
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
|
|
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) =>
|
|
1321
|
-
|
|
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
|
|
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
|
|
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$
|
|
1502
|
-
const start = record$
|
|
1503
|
-
const end = record$
|
|
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
|
|
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: "
|
|
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: "
|
|
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
|
|
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 = [
|
|
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$
|
|
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$
|
|
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)
|
|
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
|
-
|
|
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
|
-
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
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: "
|
|
5279
|
-
reasonCode: "
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
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,
|
|
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.
|
|
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
|
|
5424
|
-
const
|
|
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(
|
|
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:
|
|
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$
|
|
5552
|
-
const goal = record$
|
|
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$
|
|
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
|
-
|
|
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 };
|