project-tiny-context-harness 0.8.12 → 0.8.13

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.
Files changed (158) hide show
  1. package/README.md +43 -19
  2. package/assets/README.md +81 -40
  3. package/assets/README.zh-CN.md +44 -22
  4. package/assets/agents/AGENTS_CORE.md +8 -4
  5. package/assets/skills/context_development_engineer/SKILL.md +9 -1
  6. package/assets/skills/design-resource-authoring/SKILL.md +7 -5
  7. package/assets/skills/design-resource-authoring/references/downstream-handoff.md +2 -2
  8. package/assets/skills/design-resource-authoring/references/open-design-provider.md +22 -2
  9. package/assets/skills/design-resource-authoring/references/recovery-and-writeback.md +199 -0
  10. package/assets/skills/design-resource-authoring/references/resource-selection.md +2 -2
  11. package/assets/skills/long-task-workflow/SKILL.md +6 -6
  12. package/assets/skills/long-task-workflow/references/contract-authoring.md +27 -22
  13. package/assets/skills/long-task-workflow/references/evidence-design.md +49 -32
  14. package/assets/skills/long-task-workflow/references/source-authoring.md +2 -2
  15. package/dist/commands/design-resource-recovery.d.ts +1 -0
  16. package/dist/commands/design-resource-recovery.js +152 -0
  17. package/dist/commands/design-resource.js +20 -1
  18. package/dist/commands/index.js +1 -1
  19. package/dist/lib/design-resource-reconciliation-codec.d.ts +2 -0
  20. package/dist/lib/design-resource-reconciliation-codec.js +174 -0
  21. package/dist/lib/design-resource-reconciliation-types.d.ts +62 -0
  22. package/dist/lib/design-resource-reconciliation-types.js +1 -0
  23. package/dist/lib/design-resource-reconciliation.d.ts +3 -0
  24. package/dist/lib/design-resource-reconciliation.js +224 -0
  25. package/dist/lib/design-resource-recovery-authority-policy.d.ts +8 -0
  26. package/dist/lib/design-resource-recovery-authority-policy.js +123 -0
  27. package/dist/lib/design-resource-recovery-catalog-resources.d.ts +6 -0
  28. package/dist/lib/design-resource-recovery-catalog-resources.js +121 -0
  29. package/dist/lib/design-resource-recovery-catalog-shape.d.ts +3 -0
  30. package/dist/lib/design-resource-recovery-catalog-shape.js +104 -0
  31. package/dist/lib/design-resource-recovery-catalog.d.ts +9 -0
  32. package/dist/lib/design-resource-recovery-catalog.js +103 -0
  33. package/dist/lib/design-resource-recovery-cleanup.d.ts +2 -0
  34. package/dist/lib/design-resource-recovery-cleanup.js +11 -0
  35. package/dist/lib/design-resource-recovery-codec-primitives.d.ts +19 -0
  36. package/dist/lib/design-resource-recovery-codec-primitives.js +92 -0
  37. package/dist/lib/design-resource-recovery-codec.d.ts +4 -0
  38. package/dist/lib/design-resource-recovery-codec.js +93 -0
  39. package/dist/lib/design-resource-recovery-current.d.ts +9 -0
  40. package/dist/lib/design-resource-recovery-current.js +41 -0
  41. package/dist/lib/design-resource-recovery-delta-policy.d.ts +5 -0
  42. package/dist/lib/design-resource-recovery-delta-policy.js +108 -0
  43. package/dist/lib/design-resource-recovery-files.d.ts +37 -0
  44. package/dist/lib/design-resource-recovery-files.js +204 -0
  45. package/dist/lib/design-resource-recovery-final-disposition-shape.d.ts +2 -0
  46. package/dist/lib/design-resource-recovery-final-disposition-shape.js +47 -0
  47. package/dist/lib/design-resource-recovery-patch-types.d.ts +54 -0
  48. package/dist/lib/design-resource-recovery-patch-types.js +1 -0
  49. package/dist/lib/design-resource-recovery-replay.d.ts +7 -0
  50. package/dist/lib/design-resource-recovery-replay.js +112 -0
  51. package/dist/lib/design-resource-recovery-repository-bindings.d.ts +9 -0
  52. package/dist/lib/design-resource-recovery-repository-bindings.js +49 -0
  53. package/dist/lib/design-resource-recovery-schema.d.ts +5 -0
  54. package/dist/lib/design-resource-recovery-schema.js +5 -0
  55. package/dist/lib/design-resource-recovery-shape.d.ts +10 -0
  56. package/dist/lib/design-resource-recovery-shape.js +184 -0
  57. package/dist/lib/design-resource-recovery-source-authority.d.ts +5 -0
  58. package/dist/lib/design-resource-recovery-source-authority.js +219 -0
  59. package/dist/lib/design-resource-recovery-text.d.ts +17 -0
  60. package/dist/lib/design-resource-recovery-text.js +186 -0
  61. package/dist/lib/design-resource-recovery-types.d.ts +197 -0
  62. package/dist/lib/design-resource-recovery-types.js +1 -0
  63. package/dist/lib/design-resource-recovery-writeback-policy.d.ts +5 -0
  64. package/dist/lib/design-resource-recovery-writeback-policy.js +326 -0
  65. package/dist/lib/design-resource-recovery-writeback-shape.d.ts +6 -0
  66. package/dist/lib/design-resource-recovery-writeback-shape.js +155 -0
  67. package/dist/lib/design-resource-recovery.d.ts +44 -0
  68. package/dist/lib/design-resource-recovery.js +216 -0
  69. package/dist/lib/long-task-acceptance-shape.js +8 -2
  70. package/dist/lib/long-task-activation-validation.js +13 -3
  71. package/dist/lib/long-task-admitted-observation-records.d.ts +25 -0
  72. package/dist/lib/long-task-admitted-observation-records.js +40 -0
  73. package/dist/lib/long-task-admitted-observation.d.ts +93 -0
  74. package/dist/lib/long-task-admitted-observation.js +201 -0
  75. package/dist/lib/long-task-artifacts.d.ts +1 -0
  76. package/dist/lib/long-task-artifacts.js +1 -0
  77. package/dist/lib/long-task-authority-material-diff.js +1 -0
  78. package/dist/lib/long-task-authority-policy.d.ts +2 -0
  79. package/dist/lib/long-task-authority-policy.js +2 -0
  80. package/dist/lib/long-task-authority-revision-details.js +3 -1
  81. package/dist/lib/long-task-authority.js +2 -1
  82. package/dist/lib/long-task-check-execution-policy.js +5 -0
  83. package/dist/lib/long-task-check-runner.d.ts +2 -2
  84. package/dist/lib/long-task-check-runner.js +440 -23
  85. package/dist/lib/long-task-claims.d.ts +18 -0
  86. package/dist/lib/long-task-claims.js +35 -0
  87. package/dist/lib/long-task-compact-structure-targets.js +1 -0
  88. package/dist/lib/long-task-conformance-policy.js +3 -1
  89. package/dist/lib/long-task-counterfactual-claim-policy.d.ts +3 -4
  90. package/dist/lib/long-task-counterfactual-claim-policy.js +11 -3
  91. package/dist/lib/long-task-counterfactual-sandbox.js +1 -0
  92. package/dist/lib/long-task-counterfactual-types.d.ts +2 -0
  93. package/dist/lib/long-task-delivery-compiler.js +2 -0
  94. package/dist/lib/long-task-evidence-capability-policy.d.ts +3 -2
  95. package/dist/lib/long-task-evidence-capability-policy.js +114 -8
  96. package/dist/lib/long-task-evidence-capability-runtime.d.ts +5 -2
  97. package/dist/lib/long-task-evidence-capability-runtime.js +149 -5
  98. package/dist/lib/long-task-evidence-sensitivity-policy.d.ts +9 -0
  99. package/dist/lib/long-task-evidence-sensitivity-policy.js +31 -1
  100. package/dist/lib/long-task-evidence-v2.d.ts +4 -4
  101. package/dist/lib/long-task-evidence-v2.js +321 -43
  102. package/dist/lib/long-task-exact-comparison.d.ts +16 -0
  103. package/dist/lib/long-task-exact-comparison.js +28 -0
  104. package/dist/lib/long-task-execution-observation.d.ts +24 -0
  105. package/dist/lib/long-task-execution-observation.js +332 -0
  106. package/dist/lib/long-task-explain-acceptance-link.d.ts +4 -0
  107. package/dist/lib/long-task-explain-acceptance-link.js +4 -0
  108. package/dist/lib/long-task-explain-claim-links.d.ts +2 -0
  109. package/dist/lib/long-task-explain-claim-links.js +2 -0
  110. package/dist/lib/long-task-explain-source-links.d.ts +6 -0
  111. package/dist/lib/long-task-final-v2.js +7 -4
  112. package/dist/lib/long-task-json-pointer-observation.d.ts +59 -0
  113. package/dist/lib/long-task-json-pointer-observation.js +184 -0
  114. package/dist/lib/long-task-observation-artifact.d.ts +8 -0
  115. package/dist/lib/long-task-observation-artifact.js +58 -0
  116. package/dist/lib/long-task-observation-authority.d.ts +17 -0
  117. package/dist/lib/long-task-observation-authority.js +348 -0
  118. package/dist/lib/long-task-paths.js +1 -1
  119. package/dist/lib/long-task-process-observation.d.ts +6 -0
  120. package/dist/lib/long-task-process-observation.js +117 -0
  121. package/dist/lib/long-task-process-runtime-closure.d.ts +13 -0
  122. package/dist/lib/long-task-process-runtime-closure.js +175 -0
  123. package/dist/lib/long-task-progress.js +2 -0
  124. package/dist/lib/long-task-protected-files.d.ts +1 -1
  125. package/dist/lib/long-task-protected-files.js +1 -30
  126. package/dist/lib/long-task-risk.js +8 -3
  127. package/dist/lib/long-task-root-shape.js +10 -1
  128. package/dist/lib/long-task-runner-environment.d.ts +1 -1
  129. package/dist/lib/long-task-runner-environment.js +4 -4
  130. package/dist/lib/long-task-runner-freeze.d.ts +4 -2
  131. package/dist/lib/long-task-runner-freeze.js +128 -28
  132. package/dist/lib/long-task-runtime-types.d.ts +111 -0
  133. package/dist/lib/long-task-scoped-binding.d.ts +13 -0
  134. package/dist/lib/long-task-scoped-binding.js +11 -0
  135. package/dist/lib/long-task-semantic-contract-types.d.ts +1 -0
  136. package/dist/lib/long-task-semantic-fact-contract-closure.js +3 -3
  137. package/dist/lib/long-task-semantic-fact-evidence.d.ts +3 -3
  138. package/dist/lib/long-task-semantic-fact-evidence.js +75 -58
  139. package/dist/lib/long-task-source-claim-validation.js +4 -1
  140. package/dist/lib/long-task-source-target-continuity.d.ts +2 -2
  141. package/dist/lib/long-task-source-target-continuity.js +35 -2
  142. package/dist/lib/long-task-source-target-index.d.ts +3 -0
  143. package/dist/lib/long-task-source-target-index.js +19 -0
  144. package/dist/lib/long-task-stage-policy.js +10 -4
  145. package/dist/lib/long-task-static-observation-freeze.d.ts +83 -0
  146. package/dist/lib/long-task-static-observation-freeze.js +428 -0
  147. package/dist/lib/long-task-status-projection.js +5 -1
  148. package/dist/lib/long-task-target-policy.d.ts +1 -1
  149. package/dist/lib/long-task-target-policy.js +3 -0
  150. package/dist/lib/long-task-verifier-dependency-closure.js +7 -3
  151. package/dist/lib/long-task-verifier-v2.js +70 -9
  152. package/dist/lib/long-task-workspace.d.ts +1 -1
  153. package/dist/lib/long-task-workspace.js +1 -12
  154. package/dist/lib/repository-path-safety.d.ts +14 -0
  155. package/dist/lib/repository-path-safety.js +126 -0
  156. package/dist/schemas/long-task-delivery-v2/long-task-delivery-v2.schema.json +53 -8
  157. package/migrations/README.md +77 -0
  158. package/package.json +1 -1
@@ -0,0 +1,121 @@
1
+ export function indexDesignResourceSelectedResources(state) {
2
+ uniqueRows(state.selected_resource_bindings.map((row) => row.key), "selected_resource_key");
3
+ uniqueRows(state.selected_resource_bindings.map((row) => row.locator), "selected_resource_locator");
4
+ const provider = new Map(state.provider.resources.map((row) => [row.key, row]));
5
+ const result = new Map();
6
+ for (const row of state.selected_resource_bindings) {
7
+ requireNonEmpty(row.condition_refs, `selected_resource_conditions:${row.key}`);
8
+ uniqueRows(row.condition_refs, `selected_resource_condition:${row.key}`);
9
+ const declared = provider.get(row.key);
10
+ if (!declared)
11
+ invalid(`selected_resource_not_declared:${row.key}`);
12
+ if (declared.raw_byte_digest !== row.raw_byte_digest)
13
+ invalid(`selected_resource_digest_mismatch:${row.key}`);
14
+ result.set(row.key, row);
15
+ }
16
+ return result;
17
+ }
18
+ export function validateDesignResourceDecisionCatalog(rows, deltasById, activeChangedByTarget, superseded, selectedResources) {
19
+ const bindingIds = [];
20
+ const bindingTuples = [];
21
+ const activeOwnerTuples = [];
22
+ for (const row of rows) {
23
+ validateDesignResourceConditions([row.resource_ref], row.condition_refs, selectedResources, `resource_decision_expectation:${row.key}`);
24
+ uniqueRows(row.bindings.map((binding) => binding.binding_id), `resource_decision_binding_id:${row.key}`);
25
+ for (const binding of row.bindings) {
26
+ bindingIds.push(binding.binding_id);
27
+ bindingTuples.push(resourceBindingIdentity(row.resource_ref, binding.target_key, binding.delta_id));
28
+ const delta = deltasById.get(binding.delta_id);
29
+ if (!delta)
30
+ invalid(`resource_decision_delta_unknown:${row.key}:${binding.delta_id}`);
31
+ if (!delta.target_keys.includes(binding.target_key))
32
+ invalid(`resource_decision_target_mismatch:${row.key}:${binding.target_key}:${binding.delta_id}`);
33
+ if (delta.semantic_kind !== row.semantic_kind)
34
+ invalid(`resource_decision_semantic_kind_mismatch:${row.key}:${binding.delta_id}`);
35
+ const isActiveChanged = delta.status === "accepted" &&
36
+ !superseded.has(delta.delta_id) &&
37
+ delta.operation !== "preserve";
38
+ validateFrozenDisposition(row, binding, delta, isActiveChanged, selectedResources);
39
+ if (isActiveChanged)
40
+ activeOwnerTuples.push(deltaTarget(binding));
41
+ }
42
+ }
43
+ uniqueRows(bindingIds, "resource_decision_binding_id_global");
44
+ uniqueRows(bindingTuples, "resource_decision_binding_tuple_global");
45
+ const expectedActive = [...activeChangedByTarget].flatMap(([target, deltaIds]) => deltaIds.map((deltaId) => `${deltaId}\u0000${target}`));
46
+ assertExactSet(activeOwnerTuples, expectedActive, "resource_decision_active_owner_universe");
47
+ }
48
+ export function validateDesignResourceConditions(resourceRefs, conditionRefs, selected, label) {
49
+ requireNonEmpty(resourceRefs, `${label}:resource_refs_empty`);
50
+ requireNonEmpty(conditionRefs, `${label}:condition_refs_empty`);
51
+ uniqueRows(resourceRefs, `${label}:resource_ref`);
52
+ uniqueRows(conditionRefs, `${label}:condition_ref`);
53
+ for (const resourceRef of resourceRefs) {
54
+ const resource = selected.get(resourceRef);
55
+ if (!resource)
56
+ invalid(`${label}:resource_unselected:${resourceRef}`);
57
+ for (const condition of conditionRefs)
58
+ if (!resource.condition_refs.includes(condition))
59
+ invalid(`${label}:condition_undeclared:${resourceRef}:${condition}`);
60
+ }
61
+ }
62
+ function validateFrozenDisposition(row, binding, delta, isActiveChanged, selectedResources) {
63
+ const disposition = binding.final_disposition;
64
+ if (!isActiveChanged) {
65
+ const required = delta.status === "unresolved" ? "unresolved" : "not-adopted";
66
+ if (disposition.kind !== required)
67
+ invalid(`resource_decision_inactive_disposition:${row.key}:${binding.binding_id}:${required}`);
68
+ return;
69
+ }
70
+ if (disposition.kind === "proposal-written")
71
+ return;
72
+ if (disposition.kind !== "resource-owned-exact-visual")
73
+ invalid(`resource_decision_active_disposition:${row.key}:${binding.binding_id}`);
74
+ if (delta.semantic_kind !== "exact-visual")
75
+ invalid(`resource_decision_nonvisual_resource_owner:${row.key}`);
76
+ if (disposition.resource_ref !== row.resource_ref)
77
+ invalid(`resource_decision_owner_resource:${binding.binding_id}`);
78
+ assertExactSet(disposition.condition_refs, row.condition_refs, `resource_decision_owner_conditions:${binding.binding_id}`);
79
+ const selected = selectedResources.get(disposition.resource_ref);
80
+ if (!selected)
81
+ invalid(`resource_decision_owner_unselected:${binding.binding_id}`);
82
+ const owner = disposition.downstream_owner;
83
+ if (owner.resource_key !== disposition.resource_ref ||
84
+ owner.locator !== selected.locator ||
85
+ owner.raw_byte_digest !== selected.raw_byte_digest)
86
+ invalid(`resource_decision_owner_identity:${binding.binding_id}`);
87
+ const requiredOwnerKind = selected.identity_kind === "repository-snapshot"
88
+ ? "selected-source-record"
89
+ : "external-immutable";
90
+ if (owner.kind !== requiredOwnerKind)
91
+ invalid(`resource_decision_owner_kind:${binding.binding_id}`);
92
+ }
93
+ function deltaTarget(binding) {
94
+ return `${binding.delta_id}\u0000${binding.target_key}`;
95
+ }
96
+ function resourceBindingIdentity(resourceRef, targetKey, deltaId) {
97
+ return `${resourceRef}\u0000${targetKey}\u0000${deltaId}`;
98
+ }
99
+ function requireNonEmpty(values, code) {
100
+ if (!values.length)
101
+ invalid(code);
102
+ }
103
+ function uniqueRows(values, code) {
104
+ if (new Set(values).size !== values.length)
105
+ invalid(`duplicate:${code}`);
106
+ }
107
+ function assertExactSet(actual, expected, code) {
108
+ uniqueRows(actual, `${code}:actual`);
109
+ uniqueRows(expected, `${code}:expected`);
110
+ const left = [...actual].sort(compareText);
111
+ const right = [...expected].sort(compareText);
112
+ if (left.length !== right.length ||
113
+ left.some((value, index) => value !== right[index]))
114
+ invalid(code);
115
+ }
116
+ function compareText(left, right) {
117
+ return left < right ? -1 : left > right ? 1 : 0;
118
+ }
119
+ function invalid(code) {
120
+ throw new Error(`design_resource_recovery_invalid:${code}`);
121
+ }
@@ -0,0 +1,3 @@
1
+ import type { DesignResourceAuditExpectations, DesignResourceSelectedResourceBinding } from "./design-resource-recovery-types.js";
2
+ export declare function parseAuditExpectations(value: unknown, label: string): DesignResourceAuditExpectations;
3
+ export declare function parseSelectedResourceBinding(value: unknown, label: string): DesignResourceSelectedResourceBinding;
@@ -0,0 +1,104 @@
1
+ import { arrayOf, digest, object, oneOf, optionalArrayOf, stringSet, text, } from "./design-resource-recovery-codec-primitives.js";
2
+ import { DESIGN_RESOURCE_SEMANTIC_KINDS } from "./design-resource-recovery-shape.js";
3
+ import { parseDesignResourceFinalDisposition } from "./design-resource-recovery-final-disposition-shape.js";
4
+ export function parseAuditExpectations(value, label) {
5
+ const row = object(value, label, [
6
+ "changed",
7
+ "unchanged",
8
+ "resource_decisions",
9
+ "blast_radius",
10
+ "inactive_delta_leakage",
11
+ ]);
12
+ return {
13
+ changed: optionalArrayOf(row.changed, `${label}.changed`, parseChanged),
14
+ unchanged: optionalArrayOf(row.unchanged, `${label}.unchanged`, parseUnchanged),
15
+ resource_decisions: optionalArrayOf(row.resource_decisions, `${label}.resource_decisions`, parseResourceDecision),
16
+ blast_radius: optionalArrayOf(row.blast_radius, `${label}.blast_radius`, parseKeyRow),
17
+ inactive_delta_leakage: optionalArrayOf(row.inactive_delta_leakage, `${label}.inactive_delta_leakage`, parseInactiveDelta),
18
+ };
19
+ }
20
+ export function parseSelectedResourceBinding(value, label) {
21
+ const row = object(value, label, [
22
+ "key",
23
+ "identity_kind",
24
+ "locator",
25
+ "raw_byte_digest",
26
+ "condition_refs",
27
+ ]);
28
+ return {
29
+ key: text(row.key, `${label}.key`),
30
+ identity_kind: oneOf(row.identity_kind, ["repository-snapshot", "external-immutable"], `${label}.identity_kind`),
31
+ locator: text(row.locator, `${label}.locator`),
32
+ raw_byte_digest: digest(row.raw_byte_digest, `${label}.raw_byte_digest`),
33
+ condition_refs: stringSet(row.condition_refs, `${label}.condition_refs`),
34
+ };
35
+ }
36
+ function parseChanged(value, label) {
37
+ const row = object(value, label, [
38
+ "key",
39
+ "delta_ids",
40
+ "resource_refs",
41
+ "condition_refs",
42
+ ]);
43
+ return {
44
+ key: text(row.key, `${label}.key`),
45
+ delta_ids: stringSet(row.delta_ids, `${label}.delta_ids`),
46
+ resource_refs: stringSet(row.resource_refs, `${label}.resource_refs`),
47
+ condition_refs: stringSet(row.condition_refs, `${label}.condition_refs`),
48
+ };
49
+ }
50
+ function parseUnchanged(value, label) {
51
+ const row = object(value, label, [
52
+ "key",
53
+ "resource_refs",
54
+ "condition_refs",
55
+ "basis_source_refs",
56
+ ]);
57
+ return {
58
+ key: text(row.key, `${label}.key`),
59
+ resource_refs: stringSet(row.resource_refs, `${label}.resource_refs`),
60
+ condition_refs: stringSet(row.condition_refs, `${label}.condition_refs`),
61
+ basis_source_refs: stringSet(row.basis_source_refs, `${label}.basis_source_refs`),
62
+ };
63
+ }
64
+ function parseResourceDecision(value, label) {
65
+ const row = object(value, label, [
66
+ "key",
67
+ "resource_ref",
68
+ "semantic_kind",
69
+ "bindings",
70
+ "condition_refs",
71
+ ]);
72
+ return {
73
+ key: text(row.key, `${label}.key`),
74
+ resource_ref: text(row.resource_ref, `${label}.resource_ref`),
75
+ semantic_kind: oneOf(row.semantic_kind, DESIGN_RESOURCE_SEMANTIC_KINDS, `${label}.semantic_kind`),
76
+ bindings: arrayOf(row.bindings, `${label}.bindings`, parseBinding),
77
+ condition_refs: stringSet(row.condition_refs, `${label}.condition_refs`),
78
+ };
79
+ }
80
+ function parseBinding(value, label) {
81
+ const row = object(value, label, [
82
+ "binding_id",
83
+ "delta_id",
84
+ "target_key",
85
+ "final_disposition",
86
+ ]);
87
+ return {
88
+ binding_id: text(row.binding_id, `${label}.binding_id`),
89
+ delta_id: text(row.delta_id, `${label}.delta_id`),
90
+ target_key: text(row.target_key, `${label}.target_key`),
91
+ final_disposition: parseDesignResourceFinalDisposition(row.final_disposition, `${label}.final_disposition`),
92
+ };
93
+ }
94
+ function parseKeyRow(value, label) {
95
+ const row = object(value, label, ["key"]);
96
+ return { key: text(row.key, `${label}.key`) };
97
+ }
98
+ function parseInactiveDelta(value, label) {
99
+ const row = object(value, label, ["delta_id", "reason"]);
100
+ return {
101
+ delta_id: text(row.delta_id, `${label}.delta_id`),
102
+ reason: oneOf(row.reason, ["rejected", "unresolved", "superseded"], `${label}.reason`),
103
+ };
104
+ }
@@ -0,0 +1,9 @@
1
+ import type { DesignResourceAuthoritySourceItem, DesignResourceDelta, DesignResourceRecoveryCheckpoint, DesignResourceRecoveryCreateInput, DesignResourceSelectedResourceBinding } from "./design-resource-recovery-types.js";
2
+ type RecoveryState = DesignResourceRecoveryCreateInput | DesignResourceRecoveryCheckpoint;
3
+ export interface ValidatedRecoveryCatalog {
4
+ changed: Set<string>;
5
+ unchanged: Set<string>;
6
+ selectedResources: Map<string, DesignResourceSelectedResourceBinding>;
7
+ }
8
+ export declare function validateDesignResourceRecoveryCatalog(state: RecoveryState, deltasById: Map<string, DesignResourceDelta>, activeAccepted: DesignResourceDelta[], superseded: Set<string>, authoritySources: Map<string, DesignResourceAuthoritySourceItem>): ValidatedRecoveryCatalog;
9
+ export {};
@@ -0,0 +1,103 @@
1
+ import { indexDesignResourceSelectedResources, validateDesignResourceConditions, validateDesignResourceDecisionCatalog, } from "./design-resource-recovery-catalog-resources.js";
2
+ export function validateDesignResourceRecoveryCatalog(state, deltasById, activeAccepted, superseded, authoritySources) {
3
+ const catalog = state.audit_expectations;
4
+ uniqueRows(catalog.changed.map((row) => row.key), "changed_key");
5
+ uniqueRows(catalog.unchanged.map((row) => row.key), "unchanged_key");
6
+ uniqueRows(catalog.resource_decisions.map((row) => row.key), "resource_decision_key");
7
+ uniqueRows(catalog.blast_radius.map((row) => row.key), "blast_radius_key");
8
+ uniqueRows(catalog.inactive_delta_leakage.map((row) => row.delta_id), "inactive_delta_id");
9
+ const selectedResources = indexDesignResourceSelectedResources(state);
10
+ const activeChangedByTarget = activeChangedTargetIndex(activeAccepted);
11
+ const changed = new Set(activeChangedByTarget.keys());
12
+ const unchanged = new Set(catalog.unchanged.map((row) => row.key));
13
+ assertExactSet(catalog.changed.map((row) => row.key), [...changed], "audit_expectation_changed_keys");
14
+ assertDisjoint(changed, unchanged, "changed_and_unchanged_overlap");
15
+ const scope = new Set(state.base.in_scope_keys);
16
+ assertSubset(unchanged, scope, "explicit_unchanged_outside_scope");
17
+ for (const delta of activeAccepted) {
18
+ if (delta.operation === "preserve")
19
+ assertSubset(new Set(delta.target_keys), unchanged, `preserve_delta_not_explicitly_unchanged:${delta.delta_id}`);
20
+ }
21
+ for (const delta of state.deltas)
22
+ assertSubset(new Set(delta.explicitly_unchanged_keys), unchanged, `delta_unchanged_not_declared:${delta.delta_id}`);
23
+ for (const row of catalog.changed) {
24
+ assertExactSet(row.delta_ids, activeChangedByTarget.get(row.key) ?? [], `audit_expectation_changed_delta_ids:${row.key}`);
25
+ validateDesignResourceConditions(row.resource_refs, row.condition_refs, selectedResources, `audit_expectation_changed:${row.key}`);
26
+ }
27
+ for (const row of catalog.unchanged) {
28
+ validateDesignResourceConditions(row.resource_refs, row.condition_refs, selectedResources, `audit_expectation_unchanged:${row.key}`);
29
+ requireNonEmpty(row.basis_source_refs, `unchanged_basis_empty:${row.key}`);
30
+ for (const sourceRef of row.basis_source_refs)
31
+ if (!authoritySources.has(sourceRef))
32
+ invalid(`unchanged_basis_source_unresolved:${row.key}:${sourceRef}`);
33
+ }
34
+ const blast = new Set(catalog.blast_radius.map((row) => row.key));
35
+ assertSubset(new Set(state.base.explicitly_excluded_keys), blast, "explicit_exclusions_missing_from_blast_universe");
36
+ validateInactiveCatalog(state, catalog.inactive_delta_leakage, superseded);
37
+ validateDesignResourceDecisionCatalog(catalog.resource_decisions, deltasById, activeChangedByTarget, superseded, selectedResources);
38
+ return { changed, unchanged, selectedResources };
39
+ }
40
+ function activeChangedTargetIndex(activeAccepted) {
41
+ const result = new Map();
42
+ for (const delta of activeAccepted) {
43
+ if (delta.operation === "preserve")
44
+ continue;
45
+ for (const target of delta.target_keys) {
46
+ const owners = result.get(target) ?? [];
47
+ owners.push(delta.delta_id);
48
+ result.set(target, owners);
49
+ }
50
+ }
51
+ for (const [target, owners] of result)
52
+ if (owners.length !== 1)
53
+ invalid(`active_accepted_target_collision:${target}:${owners.join(",")}`);
54
+ return result;
55
+ }
56
+ function validateInactiveCatalog(state, rows, superseded) {
57
+ const expected = new Map();
58
+ for (const delta of state.deltas) {
59
+ if (delta.status === "rejected")
60
+ expected.set(delta.delta_id, "rejected");
61
+ else if (delta.status === "unresolved")
62
+ expected.set(delta.delta_id, "unresolved");
63
+ }
64
+ for (const deltaId of superseded)
65
+ expected.set(deltaId, "superseded");
66
+ assertExactSet(rows.map((row) => row.delta_id), [...expected.keys()], "inactive_delta_expectation_ids");
67
+ for (const row of rows)
68
+ if (expected.get(row.delta_id) !== row.reason)
69
+ invalid(`inactive_delta_reason_mismatch:${row.delta_id}`);
70
+ }
71
+ function requireNonEmpty(values, code) {
72
+ if (!values.length)
73
+ invalid(code);
74
+ }
75
+ function uniqueRows(values, code) {
76
+ if (new Set(values).size !== values.length)
77
+ invalid(`duplicate:${code}`);
78
+ }
79
+ function assertSubset(candidate, owner, code) {
80
+ const outside = [...candidate].filter((value) => !owner.has(value));
81
+ if (outside.length)
82
+ invalid(`${code}:${outside.sort(compareText).join(",")}`);
83
+ }
84
+ function assertDisjoint(left, right, code) {
85
+ const overlap = [...left].filter((value) => right.has(value));
86
+ if (overlap.length)
87
+ invalid(`${code}:${overlap.sort(compareText).join(",")}`);
88
+ }
89
+ function assertExactSet(actual, expected, code) {
90
+ uniqueRows(actual, `${code}:actual`);
91
+ uniqueRows(expected, `${code}:expected`);
92
+ const left = [...actual].sort(compareText);
93
+ const right = [...expected].sort(compareText);
94
+ if (left.length !== right.length ||
95
+ left.some((value, index) => value !== right[index]))
96
+ invalid(code);
97
+ }
98
+ function compareText(left, right) {
99
+ return left < right ? -1 : left > right ? 1 : 0;
100
+ }
101
+ function invalid(code) {
102
+ throw new Error(`design_resource_recovery_invalid:${code}`);
103
+ }
@@ -0,0 +1,2 @@
1
+ import { removeRecoveryCheckpointFile } from "./design-resource-recovery-files.js";
2
+ export declare function removeDesignResourceRecoveryCheckpoint(repository: string, sessionId: string, expectedDigest: string): Promise<Awaited<ReturnType<typeof removeRecoveryCheckpointFile>>>;
@@ -0,0 +1,11 @@
1
+ import { parseDesignResourceRecoveryCheckpoint } from "./design-resource-recovery-codec.js";
2
+ import { readRecoveryCheckpointFile, removeRecoveryCheckpointFile, } from "./design-resource-recovery-files.js";
3
+ import { validateDesignResourceRecoverySemantics } from "./design-resource-recovery-replay.js";
4
+ export async function removeDesignResourceRecoveryCheckpoint(repository, sessionId, expectedDigest) {
5
+ const snapshot = await readRecoveryCheckpointFile(repository, sessionId);
6
+ const checkpoint = parseDesignResourceRecoveryCheckpoint(snapshot.bytes.toString("utf8"));
7
+ if (checkpoint.session_id !== sessionId)
8
+ throw new Error("design_resource_recovery_invalid:session_identity_mismatch");
9
+ validateDesignResourceRecoverySemantics(checkpoint);
10
+ return removeRecoveryCheckpointFile(repository, sessionId, expectedDigest);
11
+ }
@@ -0,0 +1,19 @@
1
+ export declare function parseStrictJsonObject(content: string, label: string): Record<string, unknown>;
2
+ export declare function object(value: unknown, label: string, required?: string[], optional?: string[]): Record<string, unknown>;
3
+ export declare function text(value: unknown, label: string): string;
4
+ export declare function multilineText(value: unknown, label: string, options?: {
5
+ allowEmpty?: boolean;
6
+ }): string;
7
+ export declare function digest(value: unknown, label: string): string;
8
+ export declare function integer(value: unknown, label: string, minimum?: number): number;
9
+ export declare function literal<T extends string | number | boolean>(value: unknown, expected: T, label: string): T;
10
+ export declare function oneOf<const T extends readonly string[]>(value: unknown, allowed: T, label: string): T[number];
11
+ export declare function stringSet(value: unknown, label: string, options?: {
12
+ allowEmpty?: boolean;
13
+ }): string[];
14
+ export declare function arrayOf<T>(value: unknown, label: string, parse: (item: unknown, label: string) => T, options?: {
15
+ allowEmpty?: boolean;
16
+ }): T[];
17
+ export declare function optionalArrayOf<T>(value: unknown, label: string, parse: (item: unknown, label: string) => T): T[];
18
+ export declare function unknownSemantics(record: Record<string, unknown>, key: string, label: string): unknown;
19
+ export declare function invalid(label: string, reason: string): Error;
@@ -0,0 +1,92 @@
1
+ import { parseStrictYaml } from "./strict-codec.js";
2
+ export function parseStrictJsonObject(content, label) {
3
+ try {
4
+ JSON.parse(content);
5
+ }
6
+ catch (error) {
7
+ throw invalid(label, `json:${message(error)}`);
8
+ }
9
+ return object(parseStrictYaml(content), label);
10
+ }
11
+ export function object(value, label, required = [], optional = []) {
12
+ if (!value || typeof value !== "object" || Array.isArray(value))
13
+ throw invalid(label, "object_required");
14
+ const record = value;
15
+ const allowed = new Set([...required, ...optional]);
16
+ if (allowed.size)
17
+ for (const key of Object.keys(record))
18
+ if (!allowed.has(key))
19
+ throw invalid(label, `unknown_field:${key}`);
20
+ for (const key of required)
21
+ if (!Object.hasOwn(record, key))
22
+ throw invalid(label, `missing_field:${key}`);
23
+ return record;
24
+ }
25
+ export function text(value, label) {
26
+ if (typeof value !== "string" || !value.trim() || /[\0\r\n\t]/u.test(value))
27
+ throw invalid(label, "non_empty_single_line_string_required");
28
+ return value;
29
+ }
30
+ export function multilineText(value, label, options = {}) {
31
+ if (typeof value !== "string" ||
32
+ (!options.allowEmpty && !value.length) ||
33
+ value.includes("\0"))
34
+ throw invalid(label, options.allowEmpty ? "text_required" : "non_empty_text_required");
35
+ return value;
36
+ }
37
+ export function digest(value, label) {
38
+ const result = text(value, label);
39
+ if (!/^[0-9a-f]{64}$/u.test(result))
40
+ throw invalid(label, "sha256_required");
41
+ return result;
42
+ }
43
+ export function integer(value, label, minimum = 0) {
44
+ if (!Number.isSafeInteger(value) || value < minimum)
45
+ throw invalid(label, `integer_at_least_${minimum}_required`);
46
+ return value;
47
+ }
48
+ export function literal(value, expected, label) {
49
+ if (value !== expected)
50
+ throw invalid(label, `expected:${String(expected)}`);
51
+ return expected;
52
+ }
53
+ export function oneOf(value, allowed, label) {
54
+ const result = text(value, label);
55
+ if (!allowed.includes(result))
56
+ throw invalid(label, `unsupported:${result}`);
57
+ return result;
58
+ }
59
+ export function stringSet(value, label, options = {}) {
60
+ if (!Array.isArray(value))
61
+ throw invalid(label, "array_required");
62
+ const result = value.map((item, index) => text(item, `${label}[${index}]`));
63
+ if (!options.allowEmpty && !result.length)
64
+ throw invalid(label, "non_empty_array_required");
65
+ if (new Set(result).size !== result.length)
66
+ throw invalid(label, "duplicate_value");
67
+ return result.sort(compareText);
68
+ }
69
+ export function arrayOf(value, label, parse, options = {}) {
70
+ if (!Array.isArray(value))
71
+ throw invalid(label, "array_required");
72
+ if (!options.allowEmpty && !value.length)
73
+ throw invalid(label, "non_empty_array_required");
74
+ return value.map((item, index) => parse(item, `${label}[${index}]`));
75
+ }
76
+ export function optionalArrayOf(value, label, parse) {
77
+ return arrayOf(value, label, parse, { allowEmpty: true });
78
+ }
79
+ export function unknownSemantics(record, key, label) {
80
+ if (!Object.hasOwn(record, key))
81
+ throw invalid(label, `missing_field:${key}`);
82
+ return record[key];
83
+ }
84
+ export function invalid(label, reason) {
85
+ return new Error(`design_resource_recovery_invalid:${label}:${reason}`);
86
+ }
87
+ function message(error) {
88
+ return error instanceof Error ? error.message : String(error);
89
+ }
90
+ function compareText(left, right) {
91
+ return left < right ? -1 : left > right ? 1 : 0;
92
+ }
@@ -0,0 +1,4 @@
1
+ import { type DesignResourceRecoveryCheckpoint, type DesignResourceRecoveryCreateInput } from "./design-resource-recovery-types.js";
2
+ export declare function parseDesignResourceRecoveryCreateInput(content: string): DesignResourceRecoveryCreateInput;
3
+ export declare function parseDesignResourceRecoveryCheckpoint(content: string): DesignResourceRecoveryCheckpoint;
4
+ export declare function encodeDesignResourceRecoveryCheckpoint(checkpoint: DesignResourceRecoveryCheckpoint): string;
@@ -0,0 +1,93 @@
1
+ import { parseAuditExpectations, parseSelectedResourceBinding, } from "./design-resource-recovery-catalog-shape.js";
2
+ import { DESIGN_RESOURCE_RECOVERY_INPUT_SCHEMA, DESIGN_RESOURCE_RECOVERY_SCHEMA, } from "./design-resource-recovery-schema.js";
3
+ import { literal, object, optionalArrayOf, parseStrictJsonObject, stringSet, text, } from "./design-resource-recovery-codec-primitives.js";
4
+ import { parseAuthorityIdentity, parseAuthoritySourceItem, parseDelegation, parseDelta, parseRecoveryBase, parseRecoveryBaseInput, } from "./design-resource-recovery-shape.js";
5
+ import { parseProviderReferences, parseWritebackInput, } from "./design-resource-recovery-writeback-shape.js";
6
+ import { canonicalJson } from "./strict-codec.js";
7
+ const COMMON_FIELDS = [
8
+ "session_id",
9
+ "disclosure_review",
10
+ "base",
11
+ "authority_sources",
12
+ "delegations",
13
+ "deltas",
14
+ "decision_sets",
15
+ "audit_expectations",
16
+ "design_authority",
17
+ "provider",
18
+ "selected_resource_bindings",
19
+ ];
20
+ export function parseDesignResourceRecoveryCreateInput(content) {
21
+ const row = parseStrictJsonObject(content, "create_input");
22
+ const root = object(row, "create_input", ["schema_version", ...COMMON_FIELDS], ["writeback"]);
23
+ literal(root.schema_version, DESIGN_RESOURCE_RECOVERY_INPUT_SCHEMA, "create_input.schema_version");
24
+ return {
25
+ schema_version: DESIGN_RESOURCE_RECOVERY_INPUT_SCHEMA,
26
+ ...parseCommon(root, false),
27
+ ...(root.writeback === undefined
28
+ ? {}
29
+ : {
30
+ writeback: parseWritebackInput(root.writeback, "create_input.writeback", false),
31
+ }),
32
+ };
33
+ }
34
+ export function parseDesignResourceRecoveryCheckpoint(content) {
35
+ const row = parseStrictJsonObject(content, "checkpoint");
36
+ const root = object(row, "checkpoint", ["schema_version", "owner", ...COMMON_FIELDS], ["writeback"]);
37
+ literal(root.schema_version, DESIGN_RESOURCE_RECOVERY_SCHEMA, "checkpoint.schema_version");
38
+ literal(root.owner, "ty-context-design-resource-recovery", "checkpoint.owner");
39
+ return {
40
+ schema_version: DESIGN_RESOURCE_RECOVERY_SCHEMA,
41
+ owner: "ty-context-design-resource-recovery",
42
+ ...parseCommon(root, true),
43
+ ...(root.writeback === undefined
44
+ ? {}
45
+ : {
46
+ writeback: parseWritebackInput(root.writeback, "checkpoint.writeback", true),
47
+ }),
48
+ };
49
+ }
50
+ export function encodeDesignResourceRecoveryCheckpoint(checkpoint) {
51
+ return canonicalJson(checkpoint);
52
+ }
53
+ function parseCommon(root, complete) {
54
+ const disclosure = object(root.disclosure_review, "disclosure_review", [
55
+ "reviewed",
56
+ "contains_sensitive_raw_values",
57
+ ]);
58
+ literal(disclosure.reviewed, true, "disclosure_review.reviewed");
59
+ literal(disclosure.contains_sensitive_raw_values, false, "disclosure_review.contains_sensitive_raw_values");
60
+ const decisionSets = object(root.decision_sets, "decision_sets", [
61
+ "accepted_delta_ids",
62
+ "rejected_delta_ids",
63
+ "unresolved_delta_ids",
64
+ ]);
65
+ return {
66
+ session_id: parseSessionId(root.session_id),
67
+ disclosure_review: {
68
+ reviewed: true,
69
+ contains_sensitive_raw_values: false,
70
+ },
71
+ base: complete
72
+ ? parseRecoveryBase(root.base, "base")
73
+ : parseRecoveryBaseInput(root.base, "base"),
74
+ authority_sources: optionalArrayOf(root.authority_sources, "authority_sources", parseAuthoritySourceItem),
75
+ delegations: optionalArrayOf(root.delegations, "delegations", parseDelegation),
76
+ deltas: optionalArrayOf(root.deltas, "deltas", parseDelta),
77
+ decision_sets: {
78
+ accepted_delta_ids: stringSet(decisionSets.accepted_delta_ids, "decision_sets.accepted_delta_ids", { allowEmpty: true }),
79
+ rejected_delta_ids: stringSet(decisionSets.rejected_delta_ids, "decision_sets.rejected_delta_ids", { allowEmpty: true }),
80
+ unresolved_delta_ids: stringSet(decisionSets.unresolved_delta_ids, "decision_sets.unresolved_delta_ids", { allowEmpty: true }),
81
+ },
82
+ audit_expectations: parseAuditExpectations(root.audit_expectations, "audit_expectations"),
83
+ design_authority: parseAuthorityIdentity(root.design_authority, "design_authority"),
84
+ provider: parseProviderReferences(root.provider, "provider"),
85
+ selected_resource_bindings: optionalArrayOf(root.selected_resource_bindings, "selected_resource_bindings", parseSelectedResourceBinding),
86
+ };
87
+ }
88
+ function parseSessionId(value) {
89
+ const result = text(value, "session_id");
90
+ if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/u.test(result))
91
+ throw new Error("design_resource_recovery_invalid:session_id:unsafe");
92
+ return result;
93
+ }
@@ -0,0 +1,9 @@
1
+ import type { DesignResourceAuthorityIdentity, DesignResourceRecoveryCheckpoint } from "./design-resource-recovery-types.js";
2
+ export declare function loadCurrentDesignResourceRecoveryCheckpoint(repository: string, sessionId: string, options?: {
3
+ validateSelectedResources?: boolean;
4
+ }): Promise<{
5
+ checkpoint: DesignResourceRecoveryCheckpoint;
6
+ path: string;
7
+ digest: string;
8
+ }>;
9
+ export declare function validateDesignResourceRepositoryAuthority(repository: string, authority: DesignResourceAuthorityIdentity): Promise<void>;
@@ -0,0 +1,41 @@
1
+ import { readRecoveryCheckpointFile, readRecoveryRepositoryFile, } from "./design-resource-recovery-files.js";
2
+ import { parseDesignResourceRecoveryCheckpoint } from "./design-resource-recovery-codec.js";
3
+ import { validateDesignResourceRecoverySemantics } from "./design-resource-recovery-replay.js";
4
+ import { decodeDesignResourceText } from "./design-resource-recovery-text.js";
5
+ import { validateDesignResourceAuthoritySourceItems } from "./design-resource-recovery-source-authority.js";
6
+ import { validateSelectedResourceRepositoryBindings } from "./design-resource-recovery-repository-bindings.js";
7
+ export async function loadCurrentDesignResourceRecoveryCheckpoint(repository, sessionId, options = {}) {
8
+ const snapshot = await readRecoveryCheckpointFile(repository, sessionId);
9
+ const checkpoint = parseDesignResourceRecoveryCheckpoint(snapshot.bytes.toString("utf8"));
10
+ if (checkpoint.session_id !== sessionId)
11
+ invalid("session_identity_mismatch");
12
+ validateDesignResourceRecoverySemantics(checkpoint);
13
+ const base = await readRecoveryRepositoryFile(repository, checkpoint.base.locator, "design_resource_recovery_base");
14
+ assertDigest("base", base.raw_byte_digest, checkpoint.base.raw_byte_digest);
15
+ const decoded = decodeDesignResourceText(base.bytes);
16
+ if (decoded.encoding !== checkpoint.base.encoding ||
17
+ decoded.eol_policy !== checkpoint.base.eol_policy)
18
+ invalid("base_text_identity_changed");
19
+ await validateDesignResourceRepositoryAuthority(repository, checkpoint.design_authority);
20
+ await validateDesignResourceAuthoritySourceItems(repository, checkpoint);
21
+ if (options.validateSelectedResources !== false)
22
+ await validateSelectedResourceRepositoryBindings(repository, checkpoint);
23
+ return {
24
+ checkpoint,
25
+ path: snapshot.relative,
26
+ digest: snapshot.raw_byte_digest,
27
+ };
28
+ }
29
+ export async function validateDesignResourceRepositoryAuthority(repository, authority) {
30
+ if (authority.kind !== "repository-file")
31
+ return;
32
+ const snapshot = await readRecoveryRepositoryFile(repository, authority.locator, "design_resource_recovery_design_authority");
33
+ assertDigest("design_authority", snapshot.raw_byte_digest, authority.raw_byte_digest);
34
+ }
35
+ function assertDigest(label, actual, expected) {
36
+ if (actual !== expected)
37
+ invalid(`${label}_digest_mismatch:${expected}:${actual}`);
38
+ }
39
+ function invalid(reason) {
40
+ throw new Error(`design_resource_recovery_invalid:${reason}`);
41
+ }
@@ -0,0 +1,5 @@
1
+ import type { DesignResourceAuthoritySourceItem, DesignResourceDelegation, DesignResourceDelta } from "./design-resource-recovery-types.js";
2
+ export declare function validateDesignResourceDeltas(deltas: DesignResourceDelta[], scope: Set<string>, excluded: Set<string>, delegations: Map<string, DesignResourceDelegation>, authoritySources: Map<string, DesignResourceAuthoritySourceItem>): {
3
+ byId: Map<string, DesignResourceDelta>;
4
+ superseded: Set<string>;
5
+ };