dsh-completion-guard 0.4.0 → 0.4.2
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 +17 -2
- package/CHANGELOG.zh-CN.md +17 -2
- package/README.md +51 -11
- package/README.zh-CN.md +51 -11
- package/dist/domain/index.d.ts +2 -2
- package/dist/domain/index.js +2 -2
- package/dist/{domain-CHTQFIT8.js → domain-BXB_BPQg.js} +548 -120
- package/dist/{index-AtjJOrK8.d.ts → index-DNF0OTi-.d.ts} +65 -4
- package/dist/index.d.ts +2 -2
- package/dist/index.js +371 -96
- package/docs/ARCHITECTURE.md +19 -1
- package/docs/COMPATIBILITY.md +22 -5
- package/docs/LOCAL_ACCEPTANCE.md +63 -1
- package/docs/SEMANTIC_COMPATIBILITY.md +25 -2
- package/docs/distribution.md +23 -8
- package/docs/upstream-deltas.json +81 -180
- package/manifests/supported-host.v1.json +209 -0
- package/package.json +9 -9
|
@@ -4,30 +4,6 @@ import { dirname, join, resolve, sep } from "node:path";
|
|
|
4
4
|
import { existsSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
|
|
7
|
-
//#region src/domain/types.ts
|
|
8
|
-
function createProjection() {
|
|
9
|
-
return {
|
|
10
|
-
enabled: false,
|
|
11
|
-
epoch: 0,
|
|
12
|
-
contractRevision: 0,
|
|
13
|
-
items: /* @__PURE__ */ new Map(),
|
|
14
|
-
evidence: /* @__PURE__ */ new Map(),
|
|
15
|
-
checkpoints: [],
|
|
16
|
-
boundaries: [],
|
|
17
|
-
externalOperations: /* @__PURE__ */ new Map(),
|
|
18
|
-
sessionRefDigest: "11".repeat(32),
|
|
19
|
-
hostLockDigest: "22".repeat(32),
|
|
20
|
-
hostStatus: "supported",
|
|
21
|
-
integrityViolations: [],
|
|
22
|
-
lastObservedSourceSeq: -1,
|
|
23
|
-
lastGuardEventSeq: -1,
|
|
24
|
-
continuationAttempts: /* @__PURE__ */ new Map(),
|
|
25
|
-
persistenceCorrectionAttempts: /* @__PURE__ */ new Map(),
|
|
26
|
-
integrity: "valid"
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
//#endregion
|
|
31
7
|
//#region src/domain/canonicalize.ts
|
|
32
8
|
function normalizeClause(text) {
|
|
33
9
|
return text.trim().replace(/\s+/g, " ");
|
|
@@ -862,10 +838,10 @@ function extractArtifactPaths(text) {
|
|
|
862
838
|
}
|
|
863
839
|
return [...found];
|
|
864
840
|
}
|
|
865
|
-
function segmentClauses(text) {
|
|
841
|
+
function segmentClauses(text, captureVersion = "v042") {
|
|
866
842
|
const normalized = normalizeClause(text);
|
|
867
843
|
if (!normalized) return [];
|
|
868
|
-
const parts = normalized.split(/(?<=[。!?;])|(?<=[.!?])(?=\s|$)|(?<=(?:^|[\s。!?;.!?,,;:]))(?=(?:(?:do not|don't|never)(?![A-Za-z0-9_./@\\-])|禁止|不要|不得))/i).map((part) => part.trim()).filter(Boolean);
|
|
844
|
+
const parts = normalized.split(/(?<=[。!?;])|(?<=[.!?])(?=\s|$)|(?<=(?:^|[\s。!?;.!?,,;:]))(?=(?:(?:do not|don't|never)(?![A-Za-z0-9_./@\\-])|禁止|不要|不得))/i).flatMap((part) => captureVersion === "v041" || classifyClause(part.trim()).kind === "prohibition" ? [part] : part.split(/(?<!一)(?:并且?|以及|同时)(?=(?:验证(?!结果|全部通过|通过|成功)|确认(?!结果|全部通过|通过|成功|完成)|确保(?!结果|全部通过|通过|成功)|检查(?!结果)|更新|记录|安装|应用|重启|提交|推送|发布|在.{0,40}记录))|\s+and\s+(?=(?:verify|confirm|install|apply|restart|commit|push|publish|record)\b)/i)).map((part) => part.trim()).filter(Boolean);
|
|
869
845
|
const segments = [];
|
|
870
846
|
for (const part of parts) {
|
|
871
847
|
const { kind, body } = classifyClause(part);
|
|
@@ -881,9 +857,10 @@ function segmentClauses(text) {
|
|
|
881
857
|
* Build a GuardItem from an already-classified clause body and a resolved
|
|
882
858
|
* verification subject/surface.
|
|
883
859
|
*/
|
|
884
|
-
function captureItem(kind, body, sourceMessageId, id, revision, subject, surface, method, operation) {
|
|
860
|
+
function captureItem(kind, body, sourceMessageId, id, revision, subject, surface, method, operation, captureVersion = "v042") {
|
|
885
861
|
const sanitized = sanitizeClauseText(body);
|
|
886
|
-
const
|
|
862
|
+
const unsupportedVisual = captureVersion === "v042" && /\bGUI\b|界面|视觉|截图|颜色|布局|视觉效果/i.test(sanitized);
|
|
863
|
+
const semanticAction = unsupportedVisual ? "generic_run" : semanticActionFromText(sanitized);
|
|
887
864
|
const capturedTarget = captureRequestedTarget(semanticAction, sanitized, subject, surface);
|
|
888
865
|
const effectiveOperation = semanticAction === "verify" ? "verify" : operation;
|
|
889
866
|
const item = {
|
|
@@ -900,7 +877,7 @@ function captureItem(kind, body, sourceMessageId, id, revision, subject, surface
|
|
|
900
877
|
subject
|
|
901
878
|
} : {
|
|
902
879
|
enforced: true,
|
|
903
|
-
surface,
|
|
880
|
+
surface: unsupportedVisual ? "ui" : surface,
|
|
904
881
|
subject,
|
|
905
882
|
method,
|
|
906
883
|
operation: effectiveOperation
|
|
@@ -941,6 +918,214 @@ function captureClause(text, sourceMessageId, id, revision, scope = {}) {
|
|
|
941
918
|
return captureItem(kind, body, sourceMessageId, id, revision, path$1 || scope.cwd || "scope", surface, extractMethod(body), extractOperation(body));
|
|
942
919
|
}
|
|
943
920
|
|
|
921
|
+
//#endregion
|
|
922
|
+
//#region src/domain/rebind.ts
|
|
923
|
+
function preservesIdentity(old, clarified) {
|
|
924
|
+
const keys = Object.entries(old.requestedTarget ?? {}).filter(([key]) => key !== "scope");
|
|
925
|
+
const unwrap = (value) => JSON.stringify(value && typeof value === "object" && "v" in value ? value.v : value);
|
|
926
|
+
return keys.every(([key, value]) => unwrap(value) === unwrap(clarified.requestedTarget?.[key])) && (!old.verification.method || old.verification.method === clarified.verification.method) && (old.verification.surface !== "artifact" || old.verification.subject === clarified.verification.subject);
|
|
927
|
+
}
|
|
928
|
+
/** Exact source partition is deliberately conservative: a proposal cannot
|
|
929
|
+
* invent authority or silently discard a difficult acceptance clause. */
|
|
930
|
+
function proposeRebind(p, args) {
|
|
931
|
+
const item = p.items.get(args.item_id ?? "");
|
|
932
|
+
const clauses = args.clauses;
|
|
933
|
+
const clarificationItemIds = args.clarification_item_ids ?? [];
|
|
934
|
+
if (!item || item.status !== "pending" || item.kind === "prohibition" || !item.authority || item.authority === "legacy_authority_unclassified" || !Array.isArray(clauses) || clauses.length < 1 || clauses.length > 8 || clauses.some((s) => typeof s !== "string" || !s.trim() || s.length > 2048) || clauses.join("") !== item.normalizedText || clarificationItemIds.length !== 0 && clarificationItemIds.length !== clauses.length || new Set(clarificationItemIds.filter(Boolean)).size !== clarificationItemIds.filter(Boolean).length) return void 0;
|
|
935
|
+
for (const [index, id] of clarificationItemIds.entries()) {
|
|
936
|
+
if (!id) continue;
|
|
937
|
+
const clarified = p.items.get(id);
|
|
938
|
+
if (!clarified || clarified.id === item.id || clarified.status !== "pending" || clarified.reboundFrom || clarified.revision <= item.revision || clarified.sourceMessageId === item.sourceMessageId || clarified.authority !== "root_instruction" || clarified.legacyFlags?.length || clarified.kind !== item.kind || !clarified.normalizedText.includes(clauses[index].trim()) || !preservesIdentity(item, clarified) || /GUI|界面|视觉|截图|颜色|效果|布局/i.test(clauses[index]) && clarified.semanticAction !== "generic_run") return void 0;
|
|
939
|
+
}
|
|
940
|
+
const candidates = clauses.map((clause, index) => {
|
|
941
|
+
const root = p.items.get(clarificationItemIds[index] ?? "");
|
|
942
|
+
const captured = root ?? captureItem(item.kind, clause, item.sourceMessageId, "candidate", item.revision, item.verification.subject ?? "scope", item.verification.surface === "artifact" ? "artifact" : "scope", item.verification.method, item.verification.operation);
|
|
943
|
+
return {
|
|
944
|
+
sourceText: clause,
|
|
945
|
+
action: root || captured.semanticAction === item.semanticAction ? captured.semanticAction : "generic_run",
|
|
946
|
+
requestedTarget: captured.requestedTarget,
|
|
947
|
+
acceptance: root ? root.verification : item.verification,
|
|
948
|
+
sourceMessageId: captured.sourceMessageId,
|
|
949
|
+
rootItemId: root?.id ?? null,
|
|
950
|
+
rootRevision: root?.revision ?? null
|
|
951
|
+
};
|
|
952
|
+
});
|
|
953
|
+
const body = {
|
|
954
|
+
session: p.sessionRefDigest,
|
|
955
|
+
epoch: p.epoch,
|
|
956
|
+
contractRevision: p.contractRevision,
|
|
957
|
+
itemId: item.id,
|
|
958
|
+
itemRevision: item.revision,
|
|
959
|
+
sourceMessageId: item.sourceMessageId,
|
|
960
|
+
originalText: item.normalizedText,
|
|
961
|
+
clauses,
|
|
962
|
+
clarificationItemIds,
|
|
963
|
+
candidates
|
|
964
|
+
};
|
|
965
|
+
if (Buffer.byteLength(JSON.stringify(body), "utf8") > 8192) return void 0;
|
|
966
|
+
const digest$1 = sha256(JSON.stringify(body));
|
|
967
|
+
const normalized = JSON.parse(JSON.stringify(body));
|
|
968
|
+
return {
|
|
969
|
+
id: `RB-${digest$1.slice(0, 24)}`,
|
|
970
|
+
digest: digest$1,
|
|
971
|
+
...normalized,
|
|
972
|
+
status: "pending"
|
|
973
|
+
};
|
|
974
|
+
}
|
|
975
|
+
function rebindResponse(p, args) {
|
|
976
|
+
if (!p.enabled || p.integrity !== "valid") return {
|
|
977
|
+
status: "unknown",
|
|
978
|
+
reason_code: "guard_unavailable"
|
|
979
|
+
};
|
|
980
|
+
if (Object.keys(args).some((key) => ![
|
|
981
|
+
"operation",
|
|
982
|
+
"item_id",
|
|
983
|
+
"proposal_id",
|
|
984
|
+
"clauses",
|
|
985
|
+
"clarification_item_ids"
|
|
986
|
+
].includes(key))) return {
|
|
987
|
+
status: "rejected",
|
|
988
|
+
reason_code: "invalid_rebind_parameters"
|
|
989
|
+
};
|
|
990
|
+
if (args.operation === "propose") {
|
|
991
|
+
const candidate = proposeRebind(p, args);
|
|
992
|
+
if (!candidate) return {
|
|
993
|
+
status: "rejected",
|
|
994
|
+
reason_code: "source_partition_required",
|
|
995
|
+
next_step: "Supply 1-8 exact consecutive clauses covering the original text, including unsupported work; the proposal must fit 8 KiB. Clarification that changes meaning requires a new root-user instruction."
|
|
996
|
+
};
|
|
997
|
+
return {
|
|
998
|
+
status: "proposed",
|
|
999
|
+
proposal: p.rebindProposals.get(candidate.id) ?? candidate,
|
|
1000
|
+
next_step: `Root user must reply exactly: 确认重绑定 ${candidate.id}. This changes the contract only and grants no execution permission.`
|
|
1001
|
+
};
|
|
1002
|
+
}
|
|
1003
|
+
const proposal = p.rebindProposals.get(args.proposal_id ?? "");
|
|
1004
|
+
if (!proposal) return {
|
|
1005
|
+
status: "rejected",
|
|
1006
|
+
reason_code: "proposal_not_found"
|
|
1007
|
+
};
|
|
1008
|
+
if (args.operation === "withdraw") return proposal.status === "confirmed" ? {
|
|
1009
|
+
status: "rejected",
|
|
1010
|
+
reason_code: "proposal_already_applied"
|
|
1011
|
+
} : {
|
|
1012
|
+
status: "withdrawn",
|
|
1013
|
+
proposal_id: proposal.id,
|
|
1014
|
+
digest: proposal.digest
|
|
1015
|
+
};
|
|
1016
|
+
if (args.operation !== "query") return {
|
|
1017
|
+
status: "rejected",
|
|
1018
|
+
reason_code: "invalid_rebind_operation"
|
|
1019
|
+
};
|
|
1020
|
+
return proposal.status === "pending" && (proposal.contractRevision !== p.contractRevision || proposal.epoch !== p.epoch || proposal.session !== p.sessionRefDigest) ? {
|
|
1021
|
+
status: "stale",
|
|
1022
|
+
reason_code: "proposal_contract_changed",
|
|
1023
|
+
proposal: {
|
|
1024
|
+
...proposal,
|
|
1025
|
+
status: "stale"
|
|
1026
|
+
},
|
|
1027
|
+
next_step: "Propose again against the current contract."
|
|
1028
|
+
} : {
|
|
1029
|
+
status: proposal.status,
|
|
1030
|
+
proposal
|
|
1031
|
+
};
|
|
1032
|
+
}
|
|
1033
|
+
function replayRebindResult(p, args, recorded) {
|
|
1034
|
+
const expected = rebindResponse(p, args);
|
|
1035
|
+
if (JSON.stringify(expected) !== JSON.stringify(recorded)) return;
|
|
1036
|
+
if (args.operation === "propose") {
|
|
1037
|
+
const candidate = proposeRebind(p, args);
|
|
1038
|
+
if (candidate && !p.rebindProposals.has(candidate.id)) p.rebindProposals.set(candidate.id, candidate);
|
|
1039
|
+
} else if (args.operation === "withdraw") {
|
|
1040
|
+
const proposal = p.rebindProposals.get(args.proposal_id ?? "");
|
|
1041
|
+
if (proposal?.status === "pending") proposal.status = "withdrawn";
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
/** Invoked only for a canonical root user message, never tool or plugin text.
|
|
1045
|
+
* The single durable confirmation event is the atomic transaction commit. */
|
|
1046
|
+
function confirmRebind(p, text, eventId, durable) {
|
|
1047
|
+
const match = /^确认重绑定 (RB-[a-f0-9]{24})$/.exec(text.trim());
|
|
1048
|
+
if (!match) return false;
|
|
1049
|
+
const proposal = p.rebindProposals.get(match[1]);
|
|
1050
|
+
if (!proposal || !durable) return true;
|
|
1051
|
+
if (proposal.status !== "pending") return true;
|
|
1052
|
+
const old = p.items.get(proposal.itemId);
|
|
1053
|
+
if (!old || proposal.session !== p.sessionRefDigest || proposal.epoch !== p.epoch || old.status !== "pending" || old.revision !== proposal.itemRevision || p.contractRevision !== proposal.contractRevision || proposeRebind(p, {
|
|
1054
|
+
operation: "propose",
|
|
1055
|
+
item_id: old.id,
|
|
1056
|
+
clauses: proposal.clauses,
|
|
1057
|
+
clarification_item_ids: proposal.clarificationItemIds
|
|
1058
|
+
})?.digest !== proposal.digest) {
|
|
1059
|
+
proposal.status = "stale";
|
|
1060
|
+
return true;
|
|
1061
|
+
}
|
|
1062
|
+
const revision = p.contractRevision + 1;
|
|
1063
|
+
const replacements = proposal.clauses.map((clause, index) => {
|
|
1064
|
+
const clarified = p.items.get(proposal.clarificationItemIds[index] ?? "");
|
|
1065
|
+
if (clarified) return {
|
|
1066
|
+
...clarified,
|
|
1067
|
+
reboundFrom: {
|
|
1068
|
+
itemId: old.id,
|
|
1069
|
+
proposalId: proposal.id,
|
|
1070
|
+
confirmationEvent: eventId
|
|
1071
|
+
}
|
|
1072
|
+
};
|
|
1073
|
+
const captured = captureItem(old.kind, clause, old.sourceMessageId, `${old.kind[0].toUpperCase()}:${proposal.id}:${index + 1}`, revision, old.verification.subject ?? "scope", old.verification.surface === "artifact" ? "artifact" : "scope", old.verification.method ?? extractMethod(clause), old.verification.operation ?? extractOperation(clause));
|
|
1074
|
+
if (captured.semanticAction !== old.semanticAction) captured.semanticAction = "generic_run";
|
|
1075
|
+
return {
|
|
1076
|
+
...captured,
|
|
1077
|
+
authority: old.authority,
|
|
1078
|
+
reboundFrom: {
|
|
1079
|
+
itemId: old.id,
|
|
1080
|
+
proposalId: proposal.id,
|
|
1081
|
+
confirmationEvent: eventId
|
|
1082
|
+
},
|
|
1083
|
+
verification: {
|
|
1084
|
+
...captured.verification,
|
|
1085
|
+
...old.verification
|
|
1086
|
+
}
|
|
1087
|
+
};
|
|
1088
|
+
});
|
|
1089
|
+
if (replacements.some((item) => p.items.has(item.id) && !proposal.clarificationItemIds.includes(item.id))) {
|
|
1090
|
+
proposal.status = "stale";
|
|
1091
|
+
return true;
|
|
1092
|
+
}
|
|
1093
|
+
for (const item of replacements) p.items.set(item.id, item);
|
|
1094
|
+
old.status = "superseded";
|
|
1095
|
+
old.supersededByItems = replacements.map((item) => item.id);
|
|
1096
|
+
old.supersededBy = replacements[0].id;
|
|
1097
|
+
p.contractRevision = revision;
|
|
1098
|
+
proposal.status = "confirmed";
|
|
1099
|
+
proposal.confirmationEvent = eventId;
|
|
1100
|
+
proposal.replacementIds = old.supersededByItems;
|
|
1101
|
+
return true;
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
//#endregion
|
|
1105
|
+
//#region src/domain/types.ts
|
|
1106
|
+
function createProjection() {
|
|
1107
|
+
return {
|
|
1108
|
+
enabled: false,
|
|
1109
|
+
epoch: 0,
|
|
1110
|
+
contractRevision: 0,
|
|
1111
|
+
rebindProposals: /* @__PURE__ */ new Map(),
|
|
1112
|
+
items: /* @__PURE__ */ new Map(),
|
|
1113
|
+
evidence: /* @__PURE__ */ new Map(),
|
|
1114
|
+
checkpoints: [],
|
|
1115
|
+
boundaries: [],
|
|
1116
|
+
externalOperations: /* @__PURE__ */ new Map(),
|
|
1117
|
+
sessionRefDigest: "11".repeat(32),
|
|
1118
|
+
hostLockDigest: "22".repeat(32),
|
|
1119
|
+
hostStatus: "supported",
|
|
1120
|
+
integrityViolations: [],
|
|
1121
|
+
lastObservedSourceSeq: -1,
|
|
1122
|
+
lastGuardEventSeq: -1,
|
|
1123
|
+
continuationAttempts: /* @__PURE__ */ new Map(),
|
|
1124
|
+
persistenceCorrectionAttempts: /* @__PURE__ */ new Map(),
|
|
1125
|
+
integrity: "valid"
|
|
1126
|
+
};
|
|
1127
|
+
}
|
|
1128
|
+
|
|
944
1129
|
//#endregion
|
|
945
1130
|
//#region src/domain/contract-digest.ts
|
|
946
1131
|
function stable$3(value) {
|
|
@@ -1825,14 +2010,55 @@ function bindingSatisfies(projection, item, evidenceIds) {
|
|
|
1825
2010
|
}
|
|
1826
2011
|
}
|
|
1827
2012
|
|
|
2013
|
+
//#endregion
|
|
2014
|
+
//#region src/domain/diagnostics.ts
|
|
2015
|
+
function itemDiagnosis(p, item) {
|
|
2016
|
+
if (item.kind === "prohibition") return {
|
|
2017
|
+
certifiable: false,
|
|
2018
|
+
reason_code: "prohibition_active",
|
|
2019
|
+
next_step: "Keep this constraint enforced; it is not a completion evidence obligation."
|
|
2020
|
+
};
|
|
2021
|
+
const action = item.semanticAction ?? "generic_run";
|
|
2022
|
+
const reason = item.status === "passed" ? "certified" : action === "generic_run" ? "generic_run_non_certifiable" : item.legacyFlags?.length || item.targetCaptureStatus === "clarification_required" ? "target_clarification_required" : p.hostStatus !== "supported" ? "host_unavailable" : ACTION_MANIFEST.actions[action].evidenceProducer !== "supported" ? "adapter_unavailable" : "missing_evidence";
|
|
2023
|
+
return {
|
|
2024
|
+
certifiable: reason === "missing_evidence" || reason === "certified",
|
|
2025
|
+
reason_code: reason,
|
|
2026
|
+
next_step: reason === "certified" ? "No further binding needed." : reason === "generic_run_non_certifiable" || reason === "target_clarification_required" ? "Use context_guard_rebind to propose explicit clauses for root-user confirmation; preserve unsupported work pending. Rebinding grants no execution permission." : reason === "missing_evidence" ? "Collect matching durable evidence, then call context_guard_checkpoint with bindings." : "Restore the audited host/adapter capability before certification; keep pending work visible at a qualified safe boundary."
|
|
2027
|
+
};
|
|
2028
|
+
}
|
|
2029
|
+
const NATIVE_ADAPTERS = new Set([
|
|
2030
|
+
"dsh.bash.v1",
|
|
2031
|
+
"dsh.pwsh.v1",
|
|
2032
|
+
"dsh.shell.v1",
|
|
2033
|
+
"dsh.read.v1",
|
|
2034
|
+
"dsh.write.v1",
|
|
2035
|
+
"dsh.edit.v1",
|
|
2036
|
+
"dsh.web.v1"
|
|
2037
|
+
]);
|
|
2038
|
+
function evidenceAvailabilityReason(evidence) {
|
|
2039
|
+
if (evidence.parseStatus !== "supported") return evidence.reasonCode ?? evidence.parseStatus ?? "adapter_unavailable";
|
|
2040
|
+
if (!evidence.adapterId || !evidence.adapterVersion || (SUPPORTED_EVIDENCE_ADAPTERS[evidence.adapterId] ?? (NATIVE_ADAPTERS.has(evidence.adapterId) ? "1.0.0" : void 0)) !== evidence.adapterVersion) return "adapter_unavailable";
|
|
2041
|
+
if (evidence.outcome !== "success") return "evidence_outcome_not_success";
|
|
2042
|
+
if (!evidence.semanticAction || evidence.semanticAction === "generic_run") return "generic_run_non_certifiable";
|
|
2043
|
+
}
|
|
2044
|
+
/** Shared display filter; certification remains the full domain check. */
|
|
2045
|
+
function relevantEvidence(p, item, evidence) {
|
|
2046
|
+
const action = item.semanticAction;
|
|
2047
|
+
if (!action || action === "generic_run" || !actionCompatible(action, evidence.semanticAction ?? "generic_run") || evidence.epoch !== p.epoch || evidenceAvailabilityReason(evidence) !== void 0) return false;
|
|
2048
|
+
if (item.reboundFrom) {
|
|
2049
|
+
const source = /^m(\d+)(?::|$)/.exec(item.sourceMessageId);
|
|
2050
|
+
if (!source || evidence.toolResultSeq < Number(source[1])) return false;
|
|
2051
|
+
}
|
|
2052
|
+
if (isStatefulAction(action)) return requestedTargetMatchesResolved(action, item.requestedTarget, evidence.resolvedTarget);
|
|
2053
|
+
const value = (entry) => JSON.stringify(entry && typeof entry === "object" && "v" in entry ? entry.v : entry);
|
|
2054
|
+
return !!item.requestedTarget && Object.entries(item.requestedTarget).every(([key, entry]) => evidence.resolvedTarget && value(entry) === value(evidence.resolvedTarget[key]));
|
|
2055
|
+
}
|
|
2056
|
+
|
|
1828
2057
|
//#endregion
|
|
1829
2058
|
//#region src/domain/recovery.ts
|
|
1830
2059
|
const DEFAULT_RECOVERY_CHAR_BUDGET = 4e3;
|
|
1831
|
-
const
|
|
1832
|
-
const
|
|
1833
|
-
const MORE_ITEMS_RULE = (remaining) => `…(${remaining} more open items; the full list is in the checkpoint tool response)`;
|
|
1834
|
-
const MORE_EVIDENCE_RULE = (remaining) => `…(${remaining} more evidence rows)`;
|
|
1835
|
-
const COMPLETION_RULE = "Obtain a Context Guard checkpoint from matching durable evidence before claiming completion.";
|
|
2060
|
+
const MIN_RECOVERY_CHAR_BUDGET = 512;
|
|
2061
|
+
const COMPLETION_RULE = "Obtain a Context Guard checkpoint from matching durable evidence before claiming completion. A qualified safe end preserves pending work; it is not completion.";
|
|
1836
2062
|
/**
|
|
1837
2063
|
* An actionable one-line hint for how an open item's verification contract can
|
|
1838
2064
|
* be closed. It never weakens the contract; it only names the missing facet so
|
|
@@ -1841,6 +2067,7 @@ const COMPLETION_RULE = "Obtain a Context Guard checkpoint from matching durable
|
|
|
1841
2067
|
* evidence already cover.
|
|
1842
2068
|
*/
|
|
1843
2069
|
function closingHint(projection, item, evidenceIds) {
|
|
2070
|
+
if (item.semanticAction === "generic_run") return itemDiagnosis(projection, item).next_step;
|
|
1844
2071
|
const verification = item.verification;
|
|
1845
2072
|
const parts = [];
|
|
1846
2073
|
if (evidenceIds?.length) {
|
|
@@ -1868,84 +2095,57 @@ function openItems$1(projection) {
|
|
|
1868
2095
|
* injected once instead of looping (v0.2.1).
|
|
1869
2096
|
*/
|
|
1870
2097
|
function recoveryDigest(packet, projection) {
|
|
2098
|
+
const items = openItems$1(projection);
|
|
2099
|
+
const evidence = [...projection.evidence.values()].filter((row) => items.some((item) => relevantEvidence(projection, item, row)));
|
|
1871
2100
|
return sha256(JSON.stringify({
|
|
1872
2101
|
packet,
|
|
1873
2102
|
revision: projection.contractRevision,
|
|
1874
|
-
epoch: projection.epoch
|
|
2103
|
+
epoch: projection.epoch,
|
|
2104
|
+
host: projection.hostLockDigest,
|
|
2105
|
+
evidence
|
|
1875
2106
|
}));
|
|
1876
2107
|
}
|
|
1877
2108
|
function renderRecoveryPacket(projection, options = {}) {
|
|
1878
2109
|
const budget = options.charBudget ?? DEFAULT_RECOVERY_CHAR_BUDGET;
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
const
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
2110
|
+
if (!Number.isSafeInteger(budget) || budget < MIN_RECOVERY_CHAR_BUDGET) throw new RangeError("recovery charBudget must be an integer >= 512");
|
|
2111
|
+
const clip = (text, size) => text.length <= size ? text : text.slice(0, size - 1) + "…";
|
|
2112
|
+
const items = openItems$1(projection).sort((a, b) => Number(b.kind === "prohibition") - Number(a.kind === "prohibition") || b.revision - a.revision || a.id.localeCompare(b.id));
|
|
2113
|
+
const rejected$1 = options.rejectedBindings ?? (projection.lastCheckpointRejectionRevision === projection.contractRevision ? projection.lastCheckpointRejections : []) ?? [];
|
|
2114
|
+
const compact = budget < 1e3;
|
|
2115
|
+
const lines = [`Context Guard: ${items.length} pending; revision ${projection.contractRevision}.`, compact ? "Checkpoint required before completion. Qualified safe end preserves pending work; it is not completion." : COMPLETION_RULE];
|
|
2116
|
+
const pointer = "Details/omissions: context_guard_checkpoint (item_ids, evidence_scope=history, cursor).";
|
|
2117
|
+
const evidence = [...projection.evidence.values()].filter((e) => items.some((item) => relevantEvidence(projection, item, e))).sort((a, b) => b.toolResultSeq - a.toolResultSeq || a.id.localeCompare(b.id));
|
|
2118
|
+
const footer = (count$1, refusals$1, shown$1) => `${items.length - count$1} items folded; ${rejected$1.length - refusals$1} rejections folded; ${evidence.length - shown$1} relevant evidence rows folded. Full ledger remains enforced.`;
|
|
2119
|
+
let remaining = budget - lines.join("\n").length - 87 - footer(0, 0, 0).length - 3;
|
|
2120
|
+
const add = (line, cap) => {
|
|
2121
|
+
if (remaining < 30) return false;
|
|
2122
|
+
const text = clip(line, Math.min(cap, remaining));
|
|
2123
|
+
lines.push(text);
|
|
2124
|
+
remaining -= text.length + 1;
|
|
1885
2125
|
return true;
|
|
1886
2126
|
};
|
|
1887
|
-
const
|
|
1888
|
-
const
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
if (count >= MAX_RECOVERY_ITEMS) {
|
|
1893
|
-
push(MORE_ITEMS_RULE(list.length - count));
|
|
1894
|
-
return true;
|
|
1895
|
-
}
|
|
1896
|
-
if (!push(render(item))) return false;
|
|
1897
|
-
listedIds.add(item.id);
|
|
1898
|
-
count += 1;
|
|
1899
|
-
}
|
|
1900
|
-
return true;
|
|
2127
|
+
const constraints = items.filter((item) => item.kind === "prohibition");
|
|
2128
|
+
const work = items.filter((item) => item.kind !== "prohibition");
|
|
2129
|
+
let count = 0, refusals = 0, shown = 0;
|
|
2130
|
+
const constraint = (item) => {
|
|
2131
|
+
if (add(`DO NOT [${clip(item.id, 20)}] ${clip(item.normalizedText, compact ? 18 : 100)}`, compact ? 45 : 140)) count++;
|
|
1901
2132
|
};
|
|
1902
|
-
const
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
if (
|
|
1906
|
-
const action = item.semanticAction ?? "generic_run";
|
|
1907
|
-
const spec = ACTION_MANIFEST.actions[action];
|
|
1908
|
-
return `[${item.id}] ${item.normalizedText} action=${action} requested=${JSON.stringify(item.requestedTarget ?? {})} predicate=${spec.predicateId}@1 params=inline(resolved:${spec.resolvedTargetKeys.join(",") || "-"};observed:${spec.observedStateKeys.join(",") || "-"})`;
|
|
2133
|
+
const requirement = (item) => {
|
|
2134
|
+
const diagnosis = itemDiagnosis(projection, item);
|
|
2135
|
+
const remedy = diagnosis.reason_code === "generic_run_non_certifiable" || diagnosis.reason_code === "target_clarification_required" ? "context_guard_rebind; root confirmation required" : diagnosis.reason_code === "host_unavailable" || diagnosis.reason_code === "adapter_unavailable" ? "Restore audited host/adapter capability" : "Collect matching evidence; checkpoint";
|
|
2136
|
+
if (add(`[${clip(item.id, 20)}] ${diagnosis.reason_code}; ${compact ? remedy : diagnosis.next_step}; ${clip(item.normalizedText, 70)}`, compact ? 110 : 310)) count++;
|
|
1909
2137
|
};
|
|
1910
|
-
if (
|
|
1911
|
-
if (
|
|
1912
|
-
if (!
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
if (
|
|
1917
|
-
|
|
1918
|
-
break;
|
|
1919
|
-
}
|
|
1920
|
-
if (!push([
|
|
1921
|
-
`evidence ${evidence.id}`,
|
|
1922
|
-
`tool=${evidence.toolName}`,
|
|
1923
|
-
`action=${evidence.semanticAction ?? "generic_run"}`,
|
|
1924
|
-
`role=${evidence.evidenceRole ?? "effect"}`,
|
|
1925
|
-
`resolved=${JSON.stringify(evidence.resolvedTarget ?? {})}`,
|
|
1926
|
-
`observed=${JSON.stringify(evidence.observedState ?? {})}`,
|
|
1927
|
-
`adapter=${evidence.adapterId ?? "-"}@${evidence.adapterVersion ?? "-"}`,
|
|
1928
|
-
`ops=${(evidence.operations ?? []).map((entry) => entry.op).join(",") || "-"}`,
|
|
1929
|
-
`executables=${(evidence.executables ?? []).join(",") || "-"}`,
|
|
1930
|
-
`parse=${evidence.parseStatus ?? "adapter_unavailable"}`
|
|
1931
|
-
].join(" "))) return finalize();
|
|
1932
|
-
evidenceCount += 1;
|
|
1933
|
-
}
|
|
1934
|
-
for (const item of [...projection.items.values()].filter((item$1) => item$1.status === "superseded")) if (item.supersededBy && !push(`[${item.id} -> ${item.supersededBy}]`)) return finalize();
|
|
1935
|
-
for (const binding of options.rejectedBindings ?? []) {
|
|
1936
|
-
const offending = binding.offendingEvidenceIds?.length ? ` offending=${binding.offendingEvidenceIds.join(",")}` : "";
|
|
1937
|
-
const reason = binding.reasonCode ? binding.reasonCode : binding.reason;
|
|
1938
|
-
if (!push(`rejected ${binding.itemId}: ${reason}${offending}`)) return finalize();
|
|
1939
|
-
}
|
|
1940
|
-
for (const item of items) {
|
|
1941
|
-
if (item.kind === "prohibition" || !listedIds.has(item.id)) continue;
|
|
1942
|
-
push(`closing hint [${item.id}]: ${closingHint(projection, item)}`);
|
|
1943
|
-
}
|
|
1944
|
-
push(COMPLETION_RULE);
|
|
1945
|
-
return finalize();
|
|
1946
|
-
function finalize() {
|
|
1947
|
-
return lines.join("\n");
|
|
2138
|
+
if (constraints[0]) constraint(constraints[0]);
|
|
2139
|
+
if (work[0]) requirement(work[0]);
|
|
2140
|
+
if (!compact) {
|
|
2141
|
+
for (const item of work.slice(1, 4)) requirement(item);
|
|
2142
|
+
for (const item of constraints.slice(1, 4)) constraint(item);
|
|
2143
|
+
for (const binding of rejected$1.slice(0, 4)) if (add(`rejected ${clip(binding.itemId, 30)}: ${clip(binding.reasonCode ?? binding.reason, 120)}`, 170)) refusals++;
|
|
2144
|
+
for (const item of work.slice(0, 4)) if (itemDiagnosis(projection, item).certifiable) add(`closing hint [${clip(item.id, 20)}]: ${closingHint(projection, item)}`, 240);
|
|
2145
|
+
for (const row of evidence.slice(0, 4)) if (add(`evidence ${clip(row.id, 40)} action=${row.semanticAction} role=${row.evidenceRole ?? "effect"}`, 140)) shown++;
|
|
1948
2146
|
}
|
|
2147
|
+
lines.push(footer(count, refusals, shown), pointer);
|
|
2148
|
+
return lines.join("\n");
|
|
1949
2149
|
}
|
|
1950
2150
|
|
|
1951
2151
|
//#endregion
|
|
@@ -1996,6 +2196,16 @@ function evidenceProblem(projection, item, binding) {
|
|
|
1996
2196
|
reasonCode: "evidence_missing",
|
|
1997
2197
|
offendingEvidenceIds: missing
|
|
1998
2198
|
};
|
|
2199
|
+
if (item.reboundFrom) {
|
|
2200
|
+
const sourceSeq = /^m(\d+)(?::|$)/.exec(item.sourceMessageId);
|
|
2201
|
+
const tooEarly = binding.evidenceIds.filter((id) => !sourceSeq || projection.evidence.get(id).toolResultSeq < Number(sourceSeq[1]));
|
|
2202
|
+
if (tooEarly.length) return {
|
|
2203
|
+
itemId: item.id,
|
|
2204
|
+
reason: "evidence predates the authoritative root clause used by this replacement",
|
|
2205
|
+
reasonCode: "rebind_evidence_predates_source",
|
|
2206
|
+
offendingEvidenceIds: tooEarly
|
|
2207
|
+
};
|
|
2208
|
+
}
|
|
1999
2209
|
const wrongEpoch = binding.evidenceIds.filter((id) => projection.evidence.get(id)?.epoch !== projection.epoch);
|
|
2000
2210
|
if (wrongEpoch.length) return {
|
|
2001
2211
|
itemId: item.id,
|
|
@@ -3109,14 +3319,194 @@ const ALPHA3_HOST_PACKAGES = [
|
|
|
3109
3319
|
integrity
|
|
3110
3320
|
}));
|
|
3111
3321
|
|
|
3322
|
+
//#endregion
|
|
3323
|
+
//#region src/domain/rc1-host.ts
|
|
3324
|
+
/** Exact 34-row rc.1 runtime/web graph from the 2026-09-03 native macOS audit. */
|
|
3325
|
+
const RC1_HOST_PACKAGES = [
|
|
3326
|
+
[
|
|
3327
|
+
"@deepseek-ai/cordis",
|
|
3328
|
+
"4.0.2",
|
|
3329
|
+
"sha512-asOnXP1TzFSFQlHb1iegDZp0z/8WD1c7YNrwJR/Tx2bzNuMXfcekE/I67Iv6SQXeLB4csxqCngzQKANP7gdw0g=="
|
|
3330
|
+
],
|
|
3331
|
+
[
|
|
3332
|
+
"@deepseek-ai/dsh-agent",
|
|
3333
|
+
"0.1.2-rc.1",
|
|
3334
|
+
"sha512-lfaqN34vUCWvbn1kJVHrhfJ6Dvt1HDHCm33ZCpmKkl07/5q6FxWqVv6rOdVX5QnM/9xz/uYiN0nQwUtBg4+Skg=="
|
|
3335
|
+
],
|
|
3336
|
+
[
|
|
3337
|
+
"@deepseek-ai/dsh-commands",
|
|
3338
|
+
"0.1.2-rc.1",
|
|
3339
|
+
"sha512-uBh4JTX7pOkFhmbWjXjVLnOQOawyccC7+DazbHrLRN6/wy4OgTRH+DaW0+ibLq+XRAO19OvBTtuoh3x/KkJx1Q=="
|
|
3340
|
+
],
|
|
3341
|
+
[
|
|
3342
|
+
"@deepseek-ai/dsh-goal",
|
|
3343
|
+
"0.1.2-rc.1",
|
|
3344
|
+
"sha512-djzY1oNZV5RwnOFXmDeWFbyswInV9RVWAD0qryxMznQtEDF31PUJ8BQfqs9tVrTV36V3a0neYrZP0DDvRP8ZCA=="
|
|
3345
|
+
],
|
|
3346
|
+
[
|
|
3347
|
+
"@deepseek-ai/dsh-llm",
|
|
3348
|
+
"0.1.2-rc.1",
|
|
3349
|
+
"sha512-7VYsha5AXsVLnsAwYJffWXz9bwUbElw8i5N8tlTSdai9Bupk3sMbsotzPf8ZbsuGAxQYErahMwQwgGEu4qZO6g=="
|
|
3350
|
+
],
|
|
3351
|
+
[
|
|
3352
|
+
"@deepseek-ai/dsh-session",
|
|
3353
|
+
"0.1.2-rc.1",
|
|
3354
|
+
"sha512-jRGNPTbQcvIx1F2MVmmkoiHLgpC3Btqo1wkl/3JDLlOWRVWKOuaC+5fQiMrFPOYfno6YiX/c2UvmA0td8qB92w=="
|
|
3355
|
+
],
|
|
3356
|
+
[
|
|
3357
|
+
"@deepseek-ai/dsh-tools",
|
|
3358
|
+
"0.1.2-rc.1",
|
|
3359
|
+
"sha512-W9kUio00s7WbM8kEwniyd4hfb3CeUxVczsjXbOcKtakfiTywNLeyRWkpx2fvwRAH2rBfg3qCgczVfS0DOw1csg=="
|
|
3360
|
+
],
|
|
3361
|
+
[
|
|
3362
|
+
"@deepseek-ai/dsh-tool-goal",
|
|
3363
|
+
"0.1.2-rc.1",
|
|
3364
|
+
"sha512-ooHKN6Eqy3owNS/oCDO7mR+UalEE4AxJMXou29waahIdSQsFAlk4pPApvhrwg1lpchF5CKwBPOtsVmjq2HfBKQ=="
|
|
3365
|
+
],
|
|
3366
|
+
[
|
|
3367
|
+
"@deepseek-ai/dsh-agent-loop",
|
|
3368
|
+
"0.1.2-rc.1",
|
|
3369
|
+
"sha512-4h16Gn/5oXLTFeorehdlKe5xmDKscR/eRsUu3cs6clKgaTrn6YvnWNB0XkYEg+AXiXbsyfl5MW5Bs4576t7vZw=="
|
|
3370
|
+
],
|
|
3371
|
+
[
|
|
3372
|
+
"@deepseek-ai/dsh-tool-bash",
|
|
3373
|
+
"0.1.2-rc.1",
|
|
3374
|
+
"sha512-xKc4oXVDBwM/PaicpjGdWEaJ1N14B7KPmOzdpQ7ynE4gKUnvGU/eTg18EHamdyDOidh5ox0fNUnxk0rQjVo2+Q=="
|
|
3375
|
+
],
|
|
3376
|
+
[
|
|
3377
|
+
"@deepseek-ai/dsh-tool-pwsh",
|
|
3378
|
+
"0.1.2-rc.1",
|
|
3379
|
+
"sha512-LaImOCdizIGkQnxzzkoaqzRWGZLsuDuqqF2adgJ3zeG0nDwan4Sz+1wYz4YSp0Gg6mJ79CYacsbYmGhYYyKY/g=="
|
|
3380
|
+
],
|
|
3381
|
+
[
|
|
3382
|
+
"@deepseek-ai/dsh-shell",
|
|
3383
|
+
"0.1.2-rc.1",
|
|
3384
|
+
"sha512-uFrSY0nNKzh5orGl2B0B4RfK7wTdIlwhPQc7aLA44jyjioLlqhF7PUek/NWtye2scwp3YHOw158XeOQUD8qTFg=="
|
|
3385
|
+
],
|
|
3386
|
+
[
|
|
3387
|
+
"@deepseek-ai/dsh-subprocess-local",
|
|
3388
|
+
"0.1.2-rc.1",
|
|
3389
|
+
"sha512-Spc/IXWvjEteGysifGr6JvCokcH8T88z0mdxIGcu9SFdgDyY8HKR+h5yq73+rbo4RYzT7+TBE43TIZy5LfmzgQ=="
|
|
3390
|
+
],
|
|
3391
|
+
[
|
|
3392
|
+
"@deepseek-ai/dsh-bash-sandbox",
|
|
3393
|
+
"0.1.2-rc.1",
|
|
3394
|
+
"sha512-dF9PfBWus80Juj3VjUmndbGw1/6cT1BY7BLFuXUi7SDMV1fA4iwA2c7HuvezYFGvpE/8QRZ+c5ZiRfxbWGYktw=="
|
|
3395
|
+
],
|
|
3396
|
+
[
|
|
3397
|
+
"@deepseek-ai/dsh-pwsh-sandbox",
|
|
3398
|
+
"0.1.2-rc.1",
|
|
3399
|
+
"sha512-QjJzrM/tJDkgvtVzYz2bmCxBzdSUo/YwI/rPBJeTwLbWBuehyhX6BueCwU6Ja1Bsdm9crz2D7rVc/DU/xrFttw=="
|
|
3400
|
+
],
|
|
3401
|
+
[
|
|
3402
|
+
"@deepseek-ai/dsh-shell-env",
|
|
3403
|
+
"0.1.2-rc.1",
|
|
3404
|
+
"sha512-o1VqxyHp1OrMB8aHnzYAPwuU4giUErCxBg0yr035r6f3Le36viS0sUHsnjcAsMdbaQJf/XvzbaokYDVrdVHE4A=="
|
|
3405
|
+
],
|
|
3406
|
+
[
|
|
3407
|
+
"@deepseek-ai/dsh",
|
|
3408
|
+
"0.1.2-rc.1",
|
|
3409
|
+
"sha512-RPq48TzxvwpdT9/7W1tbhZDBMmeK+bxDrX9cqQC27Wx/LqtgJF8PSa3b3xriU8oxtvhwYmk21w2cej3uMQrnVA=="
|
|
3410
|
+
],
|
|
3411
|
+
[
|
|
3412
|
+
"@deepseek-ai/dsh-host-plugin-inventory",
|
|
3413
|
+
"0.1.2-rc.1",
|
|
3414
|
+
"sha512-MyLA5XncFdfk9btv29FZSg+ojFOOsHEiPkGWAQiRw+EG/2HlVUEm/9KqPxh2jxB5eFge9GahTg2e7x3Veziadw=="
|
|
3415
|
+
],
|
|
3416
|
+
[
|
|
3417
|
+
"@deepseek-ai/dsh-host-webserver",
|
|
3418
|
+
"0.1.2-rc.1",
|
|
3419
|
+
"sha512-QVcaf4qnIa1t215Y8TRiRhqkEz4Lu5/F+KqvWT+4sHOiyWmZr8g1JndqlwP6MBnMQEPmp0I/EKYJ7PWMV32gkA=="
|
|
3420
|
+
],
|
|
3421
|
+
[
|
|
3422
|
+
"@deepseek-ai/dsh-web-app",
|
|
3423
|
+
"0.1.2-rc.1",
|
|
3424
|
+
"sha512-QGh+XWRgrsVktKD3YHw+cY/knwBESq+2TtyOGNc+V7GU3LG9qL6EPB0M8pIDjxF1jLls+M71LIVbevuFx3oZ6Q=="
|
|
3425
|
+
],
|
|
3426
|
+
[
|
|
3427
|
+
"@deepseek-ai/dsh-jobs",
|
|
3428
|
+
"0.1.2-rc.1",
|
|
3429
|
+
"sha512-VuNPXosjgRbEg0tp+GXsdAqkicwSk5Ynl2AezUQheJgpmw5cvWy3rLEg79B686xGc72tIA6pCW6eBbZGnKOmIg=="
|
|
3430
|
+
],
|
|
3431
|
+
[
|
|
3432
|
+
"@deepseek-ai/dsh-jobs-local",
|
|
3433
|
+
"0.1.2-rc.1",
|
|
3434
|
+
"sha512-bfNV6IJRG7vPWg+Rp3siRCA0BVK8rB1aqn0BG2nPKzCIA2coKqeJ8uPbEm+GuyW/naMR4uCOrrCVLyrwBuMwzg=="
|
|
3435
|
+
],
|
|
3436
|
+
[
|
|
3437
|
+
"@deepseek-ai/dsh-tool-jobs",
|
|
3438
|
+
"0.1.2-rc.1",
|
|
3439
|
+
"sha512-ya7E6zToAdJ+GvNeZFPx8jNx0CfI52tlp0NCGzXHeB0S74haGWCV0iFe1nyoDJg7SDiN1xc1d2nV9klOqWtd5g=="
|
|
3440
|
+
],
|
|
3441
|
+
[
|
|
3442
|
+
"@deepseek-ai/dsh-tool-fs",
|
|
3443
|
+
"0.1.2-rc.1",
|
|
3444
|
+
"sha512-9a1lcPGD4Z3p7OLTMkkCdwN0w7Gl96Jlypq6qopUA0WMkKai83VfeLZvramPnTJo6ezpuPXcLFWGm/2UDSlbcA=="
|
|
3445
|
+
],
|
|
3446
|
+
[
|
|
3447
|
+
"@deepseek-ai/dsh-fs",
|
|
3448
|
+
"0.1.2-rc.1",
|
|
3449
|
+
"sha512-BSIB2j8WvATQ1mf7wUIpHPftDwbzz246qp6aUpLGSzBWGmLBdX3O1oDhyNV1YhgPmDQlwovac2odcAb62tuDdw=="
|
|
3450
|
+
],
|
|
3451
|
+
[
|
|
3452
|
+
"@deepseek-ai/dsh-fs-local",
|
|
3453
|
+
"0.1.2-rc.1",
|
|
3454
|
+
"sha512-tFHHKtD11tIk3FpkWF0vBKdX05zKbwqXQW9LhreA5hErCKEsulUsQLamf+kF1D8fuKqa8Yb+yWQIfYS93cy39w=="
|
|
3455
|
+
],
|
|
3456
|
+
[
|
|
3457
|
+
"@deepseek-ai/dsh-fs-sandbox",
|
|
3458
|
+
"0.1.2-rc.1",
|
|
3459
|
+
"sha512-nnZnsOYLWrN2AnoB0qvQBLhh2VdU4A39AqOgWwsxnT3JrScGpvBcBMCt4fpLP9l5VjOY1qhIbLf6xd5p93C/6Q=="
|
|
3460
|
+
],
|
|
3461
|
+
[
|
|
3462
|
+
"@deepseek-ai/dsh-fs-observation-policy",
|
|
3463
|
+
"0.1.2-rc.1",
|
|
3464
|
+
"sha512-Uw3ErcPwQZUvXylLSf+CDjzfAza5ZVNOMkG4hIJjvgG4WBg3tqoCOY2OQk4O1DGTie4EzL4mHpAe5auwoV4JTw=="
|
|
3465
|
+
],
|
|
3466
|
+
[
|
|
3467
|
+
"@deepseek-ai/dsh-sandbox",
|
|
3468
|
+
"0.1.2-rc.1",
|
|
3469
|
+
"sha512-nTO350NlVo9cvKzbeILcPIRIk9ijidrv29snRjTOx7kP5aO/BI2b4KxsRCYoXg8WGAMbIkGbsmZKUD4qz7hyXQ=="
|
|
3470
|
+
],
|
|
3471
|
+
[
|
|
3472
|
+
"@deepseek-ai/dsh-sandbox-policy",
|
|
3473
|
+
"0.1.2-rc.1",
|
|
3474
|
+
"sha512-nLARL84X6K4DCUJsqRWINg3+1EVxsw70hbP+Yl92W/PsquQVs/UJQc55gnhYGmIMf6eJ0vQv39fziNSnAxdx5A=="
|
|
3475
|
+
],
|
|
3476
|
+
[
|
|
3477
|
+
"@deepseek-ai/dsh-user-approval",
|
|
3478
|
+
"0.1.2-rc.1",
|
|
3479
|
+
"sha512-oYkLE4a/TwqVNi299pUf/QP1Yku6KScdUCTUyYbjaRBcN+/pXPpHikl2aoE2thH9D0uT/Kj6T2kz+wDDcFd9Xg=="
|
|
3480
|
+
],
|
|
3481
|
+
[
|
|
3482
|
+
"@deepseek-ai/dsh-attachment",
|
|
3483
|
+
"0.1.2-rc.1",
|
|
3484
|
+
"sha512-QISKUjEITusLvAkqPLRn70xDUt+GjjY41pISjtPKYcZ4EGmayzhgZ3VJNYEcC+rbaF44hs2o/0VhOwHA7lyxjw=="
|
|
3485
|
+
],
|
|
3486
|
+
[
|
|
3487
|
+
"@deepseek-ai/dsh-system-prompt",
|
|
3488
|
+
"0.1.2-rc.1",
|
|
3489
|
+
"sha512-7W93PZKIk4CHvjZGgLIxrrEKpk+6t8nQXje1vKR5vG73dfXH0t1MJ5WWH/fngadYc7c6KzM84ihQ66tJqJqyNQ=="
|
|
3490
|
+
],
|
|
3491
|
+
[
|
|
3492
|
+
"dshmarket",
|
|
3493
|
+
"1.41.0",
|
|
3494
|
+
"sha512-uGhNo85g7i/+kVuFybPMjCOD1nn2ssATDSktm9Zd851qgRv39Gz8l+smpDtpBcfhlobAD3CG6l9caYkLHu4BFw=="
|
|
3495
|
+
]
|
|
3496
|
+
].map(([name, version, integrity]) => ({
|
|
3497
|
+
name,
|
|
3498
|
+
version,
|
|
3499
|
+
integrity
|
|
3500
|
+
}));
|
|
3501
|
+
|
|
3112
3502
|
//#endregion
|
|
3113
3503
|
//#region src/domain/host-lock.ts
|
|
3114
3504
|
/**
|
|
3115
|
-
* Capability expectations shared by every audited host cohort. The rc.
|
|
3116
|
-
*
|
|
3117
|
-
*
|
|
3118
|
-
*
|
|
3119
|
-
*
|
|
3505
|
+
* Capability expectations shared by every audited host cohort. The rc.1 audit
|
|
3506
|
+
* found one host API change: Session event reads moved from `events` to
|
|
3507
|
+
* `snapshotEvents()`. Guard adapts that API locally while the event vocabulary,
|
|
3508
|
+
* flush contract, Goal disarm, `update_goal` gating, tool definition, and
|
|
3509
|
+
* renderer terminal markers remain compatible.
|
|
3120
3510
|
*/
|
|
3121
3511
|
const AUDITED_CAPABILITY_ROWS = [
|
|
3122
3512
|
{
|
|
@@ -3388,7 +3778,12 @@ const ALPHA2_DSHMARKET_139_HOST_PACKAGES = ALPHA2_HOST_PACKAGES.map((row) => row
|
|
|
3388
3778
|
* exact package graph extracted from native macOS and Windows DSH
|
|
3389
3779
|
* `0.1.2-alpha.2` / dshmarket `1.38.1` runtimes. The alpha.2+dshmarket-1.39.0
|
|
3390
3780
|
* cohort carries the exact upgraded-Windows graph. The alpha.3 cohort carries
|
|
3391
|
-
* the graph audited in the 2026-09-01 annex.
|
|
3781
|
+
* the graph audited in the 2026-09-01 annex. The rc.1 cohort carries the exact
|
|
3782
|
+
* runtime plus dshmarket 1.41.0 graph audited natively on macOS, then confirmed
|
|
3783
|
+
* on Windows: the 2026-09-04 native Windows rc.1 runtime graph (dshmarket
|
|
3784
|
+
* 1.41.0) was extracted from the runtime lockfile and verified row-for-row
|
|
3785
|
+
* identical (name, version, registry integrity) to the posix extraction before
|
|
3786
|
+
* this cohort was widened. Graphs that mix cohorts, lack
|
|
3392
3787
|
* rows, duplicate rows, or use identities outside every registered cohort
|
|
3393
3788
|
* fail closed.
|
|
3394
3789
|
*/
|
|
@@ -3567,7 +3962,8 @@ const HOST_COHORTS = [
|
|
|
3567
3962
|
]),
|
|
3568
3963
|
defineCohort("dsh-0.1.2-alpha.2", ["0.1.2-alpha.2"], ["posix", "windows"], ALPHA2_HOST_PACKAGES),
|
|
3569
3964
|
defineCohort("dsh-0.1.2-alpha.2-dshmarket-1.39.0", ["0.1.2-alpha.2"], ["posix", "windows"], ALPHA2_DSHMARKET_139_HOST_PACKAGES),
|
|
3570
|
-
defineCohort("dsh-0.1.2-alpha.3", ["0.1.2-alpha.3"], ["posix", "windows"], ALPHA3_HOST_PACKAGES)
|
|
3965
|
+
defineCohort("dsh-0.1.2-alpha.3", ["0.1.2-alpha.3"], ["posix", "windows"], ALPHA3_HOST_PACKAGES),
|
|
3966
|
+
defineCohort("dsh-0.1.2-rc.1", ["0.1.2-rc.1"], ["posix", "windows"], RC1_HOST_PACKAGES)
|
|
3571
3967
|
];
|
|
3572
3968
|
/**
|
|
3573
3969
|
* rc.2 audited package identities (first registry cohort). The audited
|
|
@@ -5154,13 +5550,14 @@ function supersedeItem(items, oldId, replacement) {
|
|
|
5154
5550
|
|
|
5155
5551
|
//#endregion
|
|
5156
5552
|
//#region src/domain/derive.ts
|
|
5553
|
+
const CAPTURE_V042_NOTICE = "Context Guard capture boundary: v0.4.2";
|
|
5157
5554
|
const PROTOCOL_V3_NOTICE = "Context Guard protocol boundary: v3.0.0";
|
|
5158
|
-
function isProtocolBoundaryNotice(event) {
|
|
5555
|
+
function isProtocolBoundaryNotice(event, notice = PROTOCOL_V3_NOTICE) {
|
|
5159
5556
|
if (event.type !== "user/message") return false;
|
|
5160
5557
|
const data = asRecord(event.data);
|
|
5161
5558
|
const source = asRecord(data?.source);
|
|
5162
5559
|
if (source?.kind !== "plugin" || source.plugin !== "context-guard" || source.form !== "notice") return false;
|
|
5163
|
-
return extractTextContent(data?.content ?? []) ===
|
|
5560
|
+
return extractTextContent(data?.content ?? []) === notice;
|
|
5164
5561
|
}
|
|
5165
5562
|
function parseArguments(raw) {
|
|
5166
5563
|
if (!raw) return {};
|
|
@@ -5268,16 +5665,16 @@ function resolveArtifact(path$1, scope) {
|
|
|
5268
5665
|
* item, so evidence for one file cannot close a message that also covers other
|
|
5269
5666
|
* files or embeds prohibitions.
|
|
5270
5667
|
*/
|
|
5271
|
-
function insertItems(projection, text, sourceMessageId, scope, authority = "root_instruction", legacy = false, legacyAuthorityProven = false) {
|
|
5668
|
+
function insertItems(projection, text, sourceMessageId, scope, authority = "root_instruction", legacy = false, legacyAuthorityProven = false, captureVersion = "v042") {
|
|
5272
5669
|
const before = new Set(projection.items.keys());
|
|
5273
|
-
for (const segment of segmentClauses(text)) {
|
|
5670
|
+
for (const segment of segmentClauses(text, captureVersion)) {
|
|
5274
5671
|
if (classifyUserInteraction(segment.body) === "conversational") continue;
|
|
5275
5672
|
if (segment.kind === "requirement" && segment.paths.length === 0 && isInstructionFraming(segment.body)) continue;
|
|
5276
5673
|
if (segment.kind === "prohibition" || segment.paths.length === 0) {
|
|
5277
|
-
insert(projection, segment.kind, segment.body, sourceMessageId, scope.cwd || "scope", "scope");
|
|
5674
|
+
insert(projection, segment.kind, segment.body, sourceMessageId, scope.cwd || "scope", "scope", captureVersion);
|
|
5278
5675
|
continue;
|
|
5279
5676
|
}
|
|
5280
|
-
for (const path$1 of segment.paths) insert(projection, segment.kind, segment.body, sourceMessageId, resolveArtifact(path$1, scope), "artifact");
|
|
5677
|
+
for (const path$1 of segment.paths) insert(projection, segment.kind, segment.body, sourceMessageId, resolveArtifact(path$1, scope), "artifact", captureVersion);
|
|
5281
5678
|
}
|
|
5282
5679
|
for (const [id, item] of projection.items) {
|
|
5283
5680
|
if (before.has(id)) continue;
|
|
@@ -5292,10 +5689,10 @@ function insertItems(projection, text, sourceMessageId, scope, authority = "root
|
|
|
5292
5689
|
else item.authority = authority;
|
|
5293
5690
|
}
|
|
5294
5691
|
}
|
|
5295
|
-
function insert(projection, kind, body, sourceMessageId, subject, surface) {
|
|
5692
|
+
function insert(projection, kind, body, sourceMessageId, subject, surface, captureVersion) {
|
|
5296
5693
|
const revision = projection.contractRevision + 1;
|
|
5297
5694
|
const id = nextId(projection.items, kind);
|
|
5298
|
-
const item = captureItem(kind, body, sourceMessageId, id, revision, subject, surface, extractMethod(body), extractOperation(body));
|
|
5695
|
+
const item = captureItem(kind, body, sourceMessageId, id, revision, subject, surface, extractMethod(body), extractOperation(body), captureVersion);
|
|
5299
5696
|
const duplicate = [...projection.items.values()].find((existing) => existing.kind === kind && existing.status === "pending" && existing.textSha256 === item.textSha256 && existing.verification.subject === subject);
|
|
5300
5697
|
if (duplicate) supersedeItem(projection.items, duplicate.id, item);
|
|
5301
5698
|
else projection.items.set(id, item);
|
|
@@ -5322,9 +5719,11 @@ function deriveProjection(sourceEvents, config, scope, durableConfirmed, hostLoc
|
|
|
5322
5719
|
let enablementTransitioned = false;
|
|
5323
5720
|
let lastCompactionSeq = -1;
|
|
5324
5721
|
const pendingCalls = /* @__PURE__ */ new Map();
|
|
5325
|
-
const protocolBoundarySeq = sourceEvents.find(isProtocolBoundaryNotice)?.seq;
|
|
5722
|
+
const protocolBoundarySeq = sourceEvents.find((event) => isProtocolBoundaryNotice(event))?.seq;
|
|
5723
|
+
const captureBoundarySeq = sourceEvents.find((event) => isProtocolBoundaryNotice(event, CAPTURE_V042_NOTICE))?.seq;
|
|
5326
5724
|
const priorRootMessages = [];
|
|
5327
5725
|
for (const event of sourceEvents) {
|
|
5726
|
+
projection.enabled = enabled;
|
|
5328
5727
|
projection.lastObservedSourceSeq = Math.max(projection.lastObservedSourceSeq, event.seq);
|
|
5329
5728
|
switch (event.type) {
|
|
5330
5729
|
case "command/run": {
|
|
@@ -5354,18 +5753,19 @@ function deriveProjection(sourceEvents, config, scope, durableConfirmed, hostLoc
|
|
|
5354
5753
|
lastCompactionSeq = event.seq;
|
|
5355
5754
|
break;
|
|
5356
5755
|
case "user/message": {
|
|
5357
|
-
if (isProtocolBoundaryNotice(event)) break;
|
|
5756
|
+
if (isProtocolBoundaryNotice(event) || isProtocolBoundaryNotice(event, CAPTURE_V042_NOTICE)) break;
|
|
5358
5757
|
if (!enabled) break;
|
|
5359
5758
|
const data = asRecord(event.data);
|
|
5360
5759
|
if (asRecord(data?.source)?.kind !== "user") break;
|
|
5361
5760
|
const text = extractTextContent(data?.content ?? []);
|
|
5362
5761
|
if (!text.trim()) break;
|
|
5762
|
+
if (!scope.sessionHeader?.parentSession && !scope.sessionHeader?.delegationDepth && scope.sessionHeader?.origin !== "subagent" && confirmRebind(projection, text, `m${event.seq}`, durableConfirmed)) break;
|
|
5363
5763
|
if (isInformationalMessage(text)) break;
|
|
5364
5764
|
if (classifyUserInteraction(text) === "conversational") break;
|
|
5365
5765
|
const blocks = segmentAuthorityBlocks(text, priorRootMessages);
|
|
5366
5766
|
for (const block$1 of blocks) {
|
|
5367
5767
|
if (!block$1.capture) continue;
|
|
5368
|
-
insertItems(projection, block$1.text, `m${event.seq}:${block$1.blockId}`, scope, block$1.authority === "root_adoption" ? "root_adoption" : "root_instruction", protocolBoundarySeq !== void 0 && event.seq < protocolBoundarySeq, block$1.kind === "instruction" || block$1.authority === "root_adoption");
|
|
5768
|
+
insertItems(projection, block$1.text, `m${event.seq}:${block$1.blockId}`, scope, block$1.authority === "root_adoption" ? "root_adoption" : "root_instruction", protocolBoundarySeq !== void 0 && event.seq < protocolBoundarySeq, block$1.kind === "instruction" || block$1.authority === "root_adoption", captureBoundarySeq !== void 0 && event.seq < captureBoundarySeq || captureBoundarySeq === void 0 && protocolBoundarySeq !== void 0 ? "v041" : "v042");
|
|
5369
5769
|
}
|
|
5370
5770
|
priorRootMessages.push(text);
|
|
5371
5771
|
if (priorRootMessages.length > 16) priorRootMessages.shift();
|
|
@@ -5468,9 +5868,19 @@ function deriveProjection(sourceEvents, config, scope, durableConfirmed, hostLoc
|
|
|
5468
5868
|
if (!call) break;
|
|
5469
5869
|
pendingCalls.delete(callId);
|
|
5470
5870
|
const textContent = extractTextContent((isDispatch ? data?.content : void 0) ?? message?.content ?? []);
|
|
5871
|
+
if (call.name === "context_guard_rebind") {
|
|
5872
|
+
if (!call.rootCallId && !data?.error && durableConfirmed) replayRebindResult(projection, parseArguments(call.arguments), parseArguments(textContent));
|
|
5873
|
+
break;
|
|
5874
|
+
}
|
|
5471
5875
|
if (call.name === "context_guard_checkpoint") {
|
|
5472
5876
|
const recorded = parseArguments(textContent);
|
|
5473
|
-
if (recorded.status !== "certified")
|
|
5877
|
+
if (recorded.status !== "certified") {
|
|
5878
|
+
if ((call.bindings?.length ?? 0) > 0) {
|
|
5879
|
+
projection.lastCheckpointRejections = certifyCheckpoint(projection, call.bindings ?? [], "diagnostic", false).rejectedBindings;
|
|
5880
|
+
projection.lastCheckpointRejectionRevision = projection.contractRevision;
|
|
5881
|
+
}
|
|
5882
|
+
break;
|
|
5883
|
+
}
|
|
5474
5884
|
if (!asRecord(recorded.certificate)) {
|
|
5475
5885
|
for (const binding of call.bindings ?? []) {
|
|
5476
5886
|
const item = projection.items.get(binding.itemId);
|
|
@@ -5970,6 +6380,24 @@ async function executeRevalidatedGitEffect(resolved, manifest, target, currentSt
|
|
|
5970
6380
|
return { status: "executed" };
|
|
5971
6381
|
}
|
|
5972
6382
|
|
|
6383
|
+
//#endregion
|
|
6384
|
+
//#region src/domain/session-events.ts
|
|
6385
|
+
/**
|
|
6386
|
+
* Read a stable snapshot from both legacy DSH Sessions and the rc.1 Session
|
|
6387
|
+
* API. rc.1 replaced the public `events` getter with `snapshotEvents()`; the
|
|
6388
|
+
* structural adapter keeps older audited cohorts working without widening the
|
|
6389
|
+
* accepted event contract.
|
|
6390
|
+
*/
|
|
6391
|
+
function snapshotSessionEvents(session) {
|
|
6392
|
+
if (!session || typeof session !== "object") return [];
|
|
6393
|
+
const source = session;
|
|
6394
|
+
if (typeof source.snapshotEvents === "function") {
|
|
6395
|
+
const events = source.snapshotEvents.call(session);
|
|
6396
|
+
return Array.isArray(events) ? events : [];
|
|
6397
|
+
}
|
|
6398
|
+
return Array.isArray(source.events) ? source.events : [];
|
|
6399
|
+
}
|
|
6400
|
+
|
|
5973
6401
|
//#endregion
|
|
5974
6402
|
//#region src/domain/host-resolver.ts
|
|
5975
6403
|
/** Names audited in any registered cohort; rows outside the union are unknown. */
|
|
@@ -6549,4 +6977,4 @@ function proofEvidenceConstraints(evidence, obligation) {
|
|
|
6549
6977
|
}
|
|
6550
6978
|
|
|
6551
6979
|
//#endregion
|
|
6552
|
-
export {
|
|
6980
|
+
export { DEFAULT_HOST_LOCK as $, SUPPORTED_EVIDENCE_ADAPTERS as $t, decideTurnBoundary as A, bindingSatisfies as At, extractTextContent as B, extractArtifactPaths as Bt, createGitPrestateEnvelope as C, closingHint as Ct, revalidateGitPrestate as D, evidenceAvailabilityReason as Dt, parseGitCommandManifest as E, renderRecoveryPacket as Et, CAPTURE_V042_NOTICE as F, createProjection as Ft, isRunExecutable as G, canonicalRegistryBase as Gt, isDeterministicCheck as H, extractOperation as Ht, PROTOCOL_V3_NOTICE as I, rebindResponse as It, goalCompletionDenial as J, ACTION_MANIFEST_VERSION as Jt, parsePwshCommand as K, npmEscapedPackageName as Kt, deriveProjection as L, captureClause as Lt, isWholeTaskCompletionClaim as M, evidenceMatchesItem as Mt, latestAssistantText as N, isVerifyingCapability as Nt, verifiedLinearCommitReadback as O, itemDiagnosis as Ot, observeAssistantOutcome as P, currentContractDigest as Pt, BASE_HOST_PACKAGES as Q, STOP_PROTOCOL_VERSION as Qt, supersedeItem as R, captureItem as Rt, commitTreeSnapshotDigest as S, MIN_RECOVERY_CHAR_BUDGET as St, gitCommandMatchesTarget as T, recoveryDigest as Tt, withDurability as U, isInformationalMessage as Ut, extractToolSubject as V, extractMethod as Vt, canonicalArgvFromCommand as W, segmentClauses as Wt, ALPHA2_DSHMARKET_139_HOST_PACKAGES as X, SEMANTIC_ACTIONS as Xt, hasCurrentCertificate as Y, CERTIFICATE_VERSION as Yt, ALPHA2_HOST_PACKAGES as Z, STATEFUL_ACTIONS as Zt, resolveInstalledHostLock as _, effectuateBoundary as _t, createProofManifest as a, semanticActionFromText as an, bindLiveGoalCapability as at, GIT_COMMAND_MANIFEST_IDS as b, certifyCheckpoint as bt, sessionQuery as c, COMMAND_SURFACE_MANIFEST as cn, evaluateHostLock as ct, hostLockContextFromComposedDump as d, digestStrings as dn, RC1_HOST_PACKAGES as dt, actionCompatible as en, EXPECTED_HOST_PACKAGES as et, hostLockRowsFromComposedDump as f, normalizeClause as fn, ALPHA3_HOST_PACKAGES as ft, resolveActiveProfileHostLock as g, availableBoundaryQualifications as gt, packageRowsFromPnpmLock as h, sha256 as hn, classifyUserInteraction as ht, canonicalProjection as i, semanticActionFromCommand as in, bindExecutableIdentity as it, decideTurnStopping as j, evidenceCoverage as jt, classifyCompletionClaim as k, relevantEvidence as kt, validateProofManifest as l, validateManifest as ln, evaluateToolSurfaceCapability as lt, packageRowsFromActiveGraph as m, sanitizeUrl as mn, segmentAuthorityBlocks as mt, PROOF_PROTOCOL_VERSION as n, requestedTargetAuthorizesMutation as nn, HOST_CAPABILITY_PACKAGE_GROUPS as nt, proofDigest as o, validateActionManifest as on, evaluateExternalWaitCapability as ot, injectActiveProfileHostLock as p, sanitizeClauseText as pn, authorityCaptureCounts as pt, parseShellCommand as q, ACTION_MANIFEST as qt, bindProofToProjection as r, requestedTargetMatchesResolved as rn, HOST_COHORTS as rt, proofEvidenceConstraints as s, validateActionTarget as sn, evaluateHostCapability as st, PROOF_KINDS as t, isStatefulAction as tn, GOAL_HOST_PACKAGES as tt, HostProfileError as u, canonicalizePath as un, selectHostCohort as ut, verifyComposedHostLockDump as v, isCurrentAcceptedBoundary as vt, executeRevalidatedGitEffect as w, openItems$1 as wt, commitIndexSnapshotDigest as x, DEFAULT_RECOVERY_CHAR_BUDGET as xt, snapshotSessionEvents as y, qualifyBoundary as yt, evidenceFromPersistedToolResult as z, classifyClause as zt };
|