codex-workflow-v2 2.0.0-beta.2 → 2.0.0-beta.5

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 (135) hide show
  1. package/README.md +35 -2
  2. package/dist/src/alpha6/adoption.js +13 -3
  3. package/dist/src/alpha6/adoption.js.map +1 -1
  4. package/dist/src/alpha6/handoff.d.ts +23 -0
  5. package/dist/src/alpha6/handoff.js +221 -28
  6. package/dist/src/alpha6/handoff.js.map +1 -1
  7. package/dist/src/alpha6/milestone.d.ts +2 -0
  8. package/dist/src/alpha6/milestone.js +15 -0
  9. package/dist/src/alpha6/milestone.js.map +1 -1
  10. package/dist/src/alpha6/plan-risk.d.ts +1 -0
  11. package/dist/src/alpha6/plan-risk.js +15 -7
  12. package/dist/src/alpha6/plan-risk.js.map +1 -1
  13. package/dist/src/alpha6/review.d.ts +1 -0
  14. package/dist/src/alpha6/review.js +9 -0
  15. package/dist/src/alpha6/review.js.map +1 -1
  16. package/dist/src/cli.js +253 -67
  17. package/dist/src/cli.js.map +1 -1
  18. package/dist/src/contracts.d.ts +111 -5
  19. package/dist/src/contracts.js +1 -1
  20. package/dist/src/credential-output.d.ts +10 -0
  21. package/dist/src/credential-output.js +73 -0
  22. package/dist/src/credential-output.js.map +1 -0
  23. package/dist/src/errors.d.ts +1 -1
  24. package/dist/src/errors.js.map +1 -1
  25. package/dist/src/index.d.ts +1 -1
  26. package/dist/src/index.js +1 -1
  27. package/dist/src/index.js.map +1 -1
  28. package/dist/src/lifecycle/canonical-hash.d.ts +6 -0
  29. package/dist/src/lifecycle/canonical-hash.js +24 -0
  30. package/dist/src/lifecycle/canonical-hash.js.map +1 -0
  31. package/dist/src/lifecycle/catalog.d.ts +26 -0
  32. package/dist/src/lifecycle/catalog.js +208 -0
  33. package/dist/src/lifecycle/catalog.js.map +1 -0
  34. package/dist/src/lifecycle/compiler-inspection.d.ts +48 -0
  35. package/dist/src/lifecycle/compiler-inspection.js +29 -0
  36. package/dist/src/lifecycle/compiler-inspection.js.map +1 -0
  37. package/dist/src/lifecycle/core-static-readiness.d.ts +6 -0
  38. package/dist/src/lifecycle/core-static-readiness.js +130 -0
  39. package/dist/src/lifecycle/core-static-readiness.js.map +1 -0
  40. package/dist/src/lifecycle/corrective-replan-authority.d.ts +53 -0
  41. package/dist/src/lifecycle/corrective-replan-authority.js +139 -0
  42. package/dist/src/lifecycle/corrective-replan-authority.js.map +1 -0
  43. package/dist/src/lifecycle/corrective-replan-binding-manifest.d.ts +21 -0
  44. package/dist/src/lifecycle/corrective-replan-binding-manifest.js +35 -0
  45. package/dist/src/lifecycle/corrective-replan-binding-manifest.js.map +1 -0
  46. package/dist/src/lifecycle/corrective-replan-credential-core.d.ts +86 -0
  47. package/dist/src/lifecycle/corrective-replan-credential-core.js +563 -0
  48. package/dist/src/lifecycle/corrective-replan-credential-core.js.map +1 -0
  49. package/dist/src/lifecycle/corrective-replan-credential-schema.d.ts +17 -0
  50. package/dist/src/lifecycle/corrective-replan-credential-schema.js +44 -0
  51. package/dist/src/lifecycle/corrective-replan-credential-schema.js.map +1 -0
  52. package/dist/src/lifecycle/corrective-replan-credentials.d.ts +47 -0
  53. package/dist/src/lifecycle/corrective-replan-credentials.js +103 -0
  54. package/dist/src/lifecycle/corrective-replan-credentials.js.map +1 -0
  55. package/dist/src/lifecycle/corrective-replan.d.ts +64 -0
  56. package/dist/src/lifecycle/corrective-replan.js +548 -0
  57. package/dist/src/lifecycle/corrective-replan.js.map +1 -0
  58. package/dist/src/lifecycle/evaluator.d.ts +2 -0
  59. package/dist/src/lifecycle/evaluator.js +35 -0
  60. package/dist/src/lifecycle/evaluator.js.map +1 -0
  61. package/dist/src/lifecycle/fingerprint.d.ts +31 -0
  62. package/dist/src/lifecycle/fingerprint.js +388 -0
  63. package/dist/src/lifecycle/fingerprint.js.map +1 -0
  64. package/dist/src/lifecycle/immutable.d.ts +1 -0
  65. package/dist/src/lifecycle/immutable.js +10 -0
  66. package/dist/src/lifecycle/immutable.js.map +1 -0
  67. package/dist/src/lifecycle/implementation-table.d.ts +29 -0
  68. package/dist/src/lifecycle/implementation-table.js +87 -0
  69. package/dist/src/lifecycle/implementation-table.js.map +1 -0
  70. package/dist/src/lifecycle/index.d.ts +4 -0
  71. package/dist/src/lifecycle/index.js +5 -0
  72. package/dist/src/lifecycle/index.js.map +1 -0
  73. package/dist/src/lifecycle/schema-artifact.d.ts +12 -0
  74. package/dist/src/lifecycle/schema-artifact.js +214 -0
  75. package/dist/src/lifecycle/schema-artifact.js.map +1 -0
  76. package/dist/src/lifecycle/semantic-registry.d.ts +6 -0
  77. package/dist/src/lifecycle/semantic-registry.js +489 -0
  78. package/dist/src/lifecycle/semantic-registry.js.map +1 -0
  79. package/dist/src/lifecycle/types.d.ts +718 -0
  80. package/dist/src/lifecycle/types.js +4 -0
  81. package/dist/src/lifecycle/types.js.map +1 -0
  82. package/dist/src/observation.d.ts +20 -0
  83. package/dist/src/observation.js +171 -0
  84. package/dist/src/observation.js.map +1 -0
  85. package/dist/src/reviewer.d.ts +39 -1
  86. package/dist/src/reviewer.js +179 -43
  87. package/dist/src/reviewer.js.map +1 -1
  88. package/dist/src/state/corrective-replan-executor.d.ts +64 -0
  89. package/dist/src/state/corrective-replan-executor.js +608 -0
  90. package/dist/src/state/corrective-replan-executor.js.map +1 -0
  91. package/dist/src/state/corrective-replan-public-schema.d.ts +3 -0
  92. package/dist/src/state/corrective-replan-public-schema.js +43 -0
  93. package/dist/src/state/corrective-replan-public-schema.js.map +1 -0
  94. package/dist/src/state/corrective-replan-public.d.ts +95 -0
  95. package/dist/src/state/corrective-replan-public.js +665 -0
  96. package/dist/src/state/corrective-replan-public.js.map +1 -0
  97. package/dist/src/state/corrective-replan-transaction.d.ts +160 -0
  98. package/dist/src/state/corrective-replan-transaction.js +730 -0
  99. package/dist/src/state/corrective-replan-transaction.js.map +1 -0
  100. package/dist/src/state/corrective-yield-executor.d.ts +31 -0
  101. package/dist/src/state/corrective-yield-executor.js +236 -0
  102. package/dist/src/state/corrective-yield-executor.js.map +1 -0
  103. package/dist/src/state/corrective-yield-transaction.d.ts +97 -0
  104. package/dist/src/state/corrective-yield-transaction.js +591 -0
  105. package/dist/src/state/corrective-yield-transaction.js.map +1 -0
  106. package/dist/src/state/lock.d.ts +76 -3
  107. package/dist/src/state/lock.js +611 -30
  108. package/dist/src/state/lock.js.map +1 -1
  109. package/dist/src/state/store.d.ts +3 -0
  110. package/dist/src/state/store.js +65 -12
  111. package/dist/src/state/store.js.map +1 -1
  112. package/dist/src/transition-core.d.ts +67 -0
  113. package/dist/src/transition-core.js +318 -0
  114. package/dist/src/transition-core.js.map +1 -0
  115. package/dist/src/version.d.ts +1 -1
  116. package/dist/src/version.js +1 -1
  117. package/dist/src/workflow.d.ts +62 -25
  118. package/dist/src/workflow.js +892 -183
  119. package/dist/src/workflow.js.map +1 -1
  120. package/docs/lifecycle/state-machine-stabilization.md +641 -0
  121. package/docs/release.md +6 -2
  122. package/docs/updating-existing-project.md +9 -0
  123. package/package.json +4 -1
  124. package/plugins/codex-workflow-gateway/skills/codex-workflow-gateway/SKILL.md +36 -0
  125. package/schemas/adoption-posture-event.schema.json +1 -1
  126. package/schemas/context-envelope.schema.json +1 -1
  127. package/schemas/corrective-replan-credentials.private.schema.json +98 -0
  128. package/schemas/corrective-replan-execution-event.private.schema.json +53 -0
  129. package/schemas/corrective-replan-public.schema.json +142 -0
  130. package/schemas/corrective-replan-task-transaction.private.schema.json +151 -0
  131. package/schemas/corrective-yield-task-transaction.private.schema.json +98 -0
  132. package/schemas/remediation-event.schema.json +11 -1
  133. package/schemas/task-handoff-event.schema.json +1 -1
  134. package/schemas/transition-definition.schema.json +2609 -0
  135. package/schemas/transition-payloads.schema.json +140 -0
@@ -0,0 +1,563 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { types as utilTypes } from 'node:util';
3
+ import { correctiveReplanBindingManifest } from './corrective-replan-binding-manifest.js';
4
+ import { installedAuthoritySemanticBindings } from './corrective-replan-authority.js';
5
+ import { correctiveReplanCredentialSchemaValidators } from './corrective-replan-credential-schema.js';
6
+ import { hashCanonical } from './fingerprint.js';
7
+ import { deepFreeze } from './immutable.js';
8
+ import { LIFECYCLE_EPOCH } from './types.js';
9
+ const kernels = new WeakMap();
10
+ const TTL = 900_000;
11
+ const MAX_SAFE = Number.MAX_SAFE_INTEGER;
12
+ const MALFORMED = Symbol('malformed');
13
+ const LIMIT = Symbol('limit');
14
+ export function createCorrectiveReplanCredentialKernel(ports) {
15
+ if (!exactKeys(ports, ['snapshotSource', 'coreClock', 'idSource', 'challengeCodeSource', 'validationEventTailSource']))
16
+ throw new TypeError('Invalid corrective replan Core ports.');
17
+ const captured = deepFreeze({
18
+ readSnapshot: ports.snapshotSource.readCorrectiveReplanSnapshot.bind(ports.snapshotSource),
19
+ now: ports.coreClock.nowMs.bind(ports.coreClock), nextId: ports.idSource.nextId.bind(ports.idSource),
20
+ issueCode: ports.challengeCodeSource.issueConfirmationCode.bind(ports.challengeCodeSource),
21
+ readTail: ports.validationEventTailSource.readPlanValidationTail.bind(ports.validationEventTailSource),
22
+ });
23
+ const issuer = Object.freeze(Object.create(null));
24
+ kernels.set(issuer, { ports: captured, plans: new WeakMap(), challenges: new WeakMap(), confirmations: new WeakMap(),
25
+ receipts: new WeakMap(), events: new WeakMap(), preparations: new Map(), preparationGeneration: { value: 0 },
26
+ challenged: new WeakSet(), confirmed: new WeakSet(), receipted: new WeakSet(), evented: new WeakSet() });
27
+ return deepFreeze({
28
+ issuePlanValidation: (input) => totalResult(() => issuePlanValidation(issuer, input)),
29
+ issueHumanChallenge: (input) => totalResult(() => issueHumanChallenge(issuer, input)),
30
+ confirmHuman: (input) => totalResult(() => confirmHuman(issuer, input)),
31
+ issueReceipt: (input) => totalResult(() => issueReceipt(issuer, input)),
32
+ verifyReceipt: (input) => totalVerification(() => verifyReceipt(issuer, input)),
33
+ materializeStoredEvent: (input) => totalResult(() => materializeStoredEvent(issuer, input)),
34
+ verifyStoredEvent: (input) => totalVerification(() => verifyStoredEvent(issuer, input)),
35
+ });
36
+ }
37
+ const issuePlanValidation = (issuer, input) => {
38
+ const kernel = kernels.get(object(issuer));
39
+ if (!kernel)
40
+ return rejected('credential.provenance.invalid', '/', 'provenance');
41
+ const owned = copyOwnedJson(input);
42
+ if (owned === LIMIT)
43
+ return rejected('credential.operation.limit-exceeded', '/', 'schema');
44
+ if (owned === MALFORMED || !exactKeys(owned, ['taskId', 'draft']))
45
+ return rejected('credential.operation.malformed', '/', 'schema');
46
+ const envelope = owned;
47
+ if (!canonicalId(envelope.taskId) || !exactDraft(envelope.draft))
48
+ return rejected('credential.plan-validation.input-invalid', '/draft', 'schema');
49
+ const now = safeTime(kernel.ports.now());
50
+ if (now === null)
51
+ return rejected('credential.time.invalid', '/coreClock', 'time');
52
+ const loaded = loadCanonicalSnapshot(kernel, envelope.taskId);
53
+ if ('issueId' in loaded)
54
+ return rejected(loaded.issueId, loaded.path, loaded.reasonClass);
55
+ const { snapshot, snapshotBindingHash } = loaded;
56
+ const base = record(snapshot.baseValues);
57
+ const expected = record(snapshot.validationExpectation);
58
+ const draft = record(envelope.draft);
59
+ for (const key of ['requirements', 'acceptance', 'architecture'])
60
+ if (!same(draft[key], expected[key]))
61
+ return rejected('credential.plan-validation.snapshot-mismatch', `/draft/${key}`, 'binding');
62
+ const validatorContext = record(draft.validatorContext);
63
+ const plannerContextHash = get(expected, '/plannerContext/contextHash');
64
+ if (validatorContext.contextHash === plannerContextHash)
65
+ return rejected('credential.plan-validation.context-invalid', '/draft/validatorContext', 'binding');
66
+ if (base.planAuthorIdentityHash === base.planValidatorIdentityHash)
67
+ return rejected('credential.plan-validation.sod-invalid', '/snapshot/baseValues/planValidatorIdentityHash', 'sod');
68
+ const findings = array(draft.findings);
69
+ const dispositions = array(draft.dispositions);
70
+ if (!keyedBijection(findings, dispositions))
71
+ return rejected('credential.plan-validation.findings-invalid', '/draft/findings', 'binding');
72
+ const plannerCaptured = safeTime(get(expected, '/plannerContext/capturedAtMs'));
73
+ if (plannerCaptured === null || plannerCaptured > now)
74
+ return rejected('credential.plan-validation.context-time-invalid', '/snapshot/validationExpectation/plannerContext/capturedAtMs', 'time');
75
+ const preparationKey = hashCanonical({ family: 'corrective-replan', snapshotBindingHash, transitionId: base.transitionId,
76
+ taskId: base.taskId, revision: base.revision, candidatePlanHash: base.candidatePlanHash, candidateStepSetHash: base.candidateStepSetHash });
77
+ const previous = kernel.preparations.get(preparationKey);
78
+ if (previous && now < previous.expiresAtMs)
79
+ return rejected('credential.preparation.duplicate', '/taskId', 'provenance');
80
+ if (previous)
81
+ kernel.preparations.delete(preparationKey);
82
+ const generation = ++kernel.preparationGeneration.value;
83
+ kernel.preparations.set(preparationKey, { generation, status: 'reserved', expiresAtMs: now + TTL });
84
+ let committed = false;
85
+ try {
86
+ const sortedFindings = sortRows(findings);
87
+ const sortedDispositions = sortRows(dispositions);
88
+ const freshContext = { sourceSnapshotHash: snapshotBindingHash, plannerContextHash, validatorContextHash: validatorContext.contextHash, passed: true };
89
+ const validation = { domain: 'codex-workflow/plan-validation/v1', source: expected.source, candidate: expected.candidate,
90
+ requirements: draft.requirements, acceptance: draft.acceptance, architecture: draft.architecture,
91
+ planAuthor: expected.planAuthor, plannerContext: expected.plannerContext, validator: expected.validator,
92
+ validatorContext: { contextHash: validatorContext.contextHash, capturedAtMs: now }, freshContext,
93
+ passed: true, findings: sortedFindings, dispositions: sortedDispositions, validatedAtMs: now, expiresAtMs: now + TTL };
94
+ const planValidationHash = hashCanonical(validation);
95
+ const values = { ...clone(base), planValidationHash };
96
+ if (!canonicalManifestValues(values, true))
97
+ return rejected('credential.binding.values-invalid', '/binding/values', 'binding');
98
+ const capability = { id: 'capability.task.corrective-replan', version: 1,
99
+ issuer: { kind: 'human', identityHash: values.humanPrincipalIdentityHash }, source: 'human-confirmation',
100
+ scope: { transitionId: values.transitionId, taskId: values.taskId, candidatePlanHash: values.candidatePlanHash,
101
+ manifestSha256: correctiveReplanBindingManifest.manifestSha256 }, delegation: 'forbidden' };
102
+ const bindingBase = { schemaVersion: 1, manifestRef: { id: correctiveReplanBindingManifest.id, version: 1 },
103
+ manifestSha256: correctiveReplanBindingManifest.manifestSha256, values, capability };
104
+ const binding = { ...bindingBase, bindingSha256: hashCanonical(bindingBase) };
105
+ if (!schema('schema.corrective-replan-binding', binding))
106
+ return rejected('credential.binding.invalid', '/binding', 'schema');
107
+ const attestationBase = { schemaVersion: 1, attestationId: safeId(kernel.ports.nextId('plan-validation-attestation')),
108
+ bindingSha256: binding.bindingSha256, source: validation.source, candidate: validation.candidate,
109
+ requirements: validation.requirements, acceptance: validation.acceptance, architecture: validation.architecture,
110
+ planAuthor: validation.planAuthor, plannerContext: validation.plannerContext, validator: validation.validator,
111
+ validatorContext: validation.validatorContext, freshContext, passed: true,
112
+ findings: sortedFindings, dispositions: sortedDispositions, validatedAtMs: now, expiresAtMs: now + TTL };
113
+ if (!attestationBase.attestationId)
114
+ return rejected('credential.id.invalid', '/idSource', 'integrity');
115
+ const attestation = { ...attestationBase, attestationHash: hashCanonical(attestationBase) };
116
+ if (!schema('schema.corrective-replan-plan-validation-attestation', attestation))
117
+ return rejected('credential.plan-validation.invalid', '/attestation', 'schema');
118
+ const handle = opaque();
119
+ const recordValue = deepFreeze({ preparationKey, generation, snapshot, snapshotBindingHash, binding, attestation });
120
+ kernel.plans.set(handle, recordValue);
121
+ kernel.preparations.set(preparationKey, { generation, status: 'active', expiresAtMs: now + TTL });
122
+ committed = true;
123
+ return accepted({ handle: handle, binding, attestation });
124
+ }
125
+ finally {
126
+ if (!committed && kernel.preparations.get(preparationKey)?.generation === generation)
127
+ kernel.preparations.delete(preparationKey);
128
+ }
129
+ };
130
+ const issueHumanChallenge = (issuer, input) => {
131
+ const kernel = kernels.get(object(issuer));
132
+ if (!kernel)
133
+ return rejected('credential.provenance.invalid', '/', 'provenance');
134
+ if (!exactKeys(input, ['planValidation']))
135
+ return rejected('credential.envelope.invalid', '/', 'schema');
136
+ const handle = object(input.planValidation);
137
+ const plan = kernel.plans.get(handle);
138
+ if (!plan)
139
+ return rejected('credential.provenance.invalid', '/planValidation', 'provenance');
140
+ if (!activePreparation(kernel, plan))
141
+ return rejected('credential.preparation.superseded', '/planValidation', 'provenance');
142
+ if (kernel.challenged.has(handle))
143
+ return rejected('credential.provenance.invalid', '/planValidation', 'provenance');
144
+ const now = safeTime(kernel.ports.now());
145
+ if (now === null)
146
+ return rejected('credential.time.invalid', '/coreClock', 'time');
147
+ if (now < number(plan.attestation.validatedAtMs))
148
+ return rejected('credential.challenge.time-invalid', '/coreClock', 'time');
149
+ const expiresAtMs = Math.min(now + TTL, number(plan.attestation.expiresAtMs));
150
+ if (now >= expiresAtMs)
151
+ return rejected('credential.challenge.expired', '/planValidation', 'time');
152
+ const challengeId = safeId(kernel.ports.nextId('human-challenge'));
153
+ if (!challengeId)
154
+ return rejected('credential.challenge.source-invalid', '/idSource', 'integrity');
155
+ const code = kernel.ports.issueCode();
156
+ if (typeof code !== 'string' || !/^[0-9]{6}$/.test(code))
157
+ return rejected('credential.challenge.source-invalid', '/challengeCodeSource', 'integrity');
158
+ const core = { schemaVersion: 1, challengeId, owner: 'workflow-core', bindingSha256: plan.binding.bindingSha256,
159
+ codeSha256: sha(code), issuedAtMs: now, expiresAtMs };
160
+ const challenge = deepFreeze({ ...core, challengeHash: hashCanonical(core) });
161
+ const challengeHandle = opaque();
162
+ kernel.challenges.set(challengeHandle, deepFreeze({ plan, challenge }));
163
+ kernel.challenged.add(handle);
164
+ return accepted({ handle: challengeHandle,
165
+ delivery: { kind: 'corrective-replan-human-challenge-delivery', version: 1, challengeId, confirmationCode: code, expiresAtMs } });
166
+ };
167
+ const confirmHuman = (issuer, input) => {
168
+ const kernel = kernels.get(object(issuer));
169
+ if (!kernel)
170
+ return rejected('credential.provenance.invalid', '/', 'provenance');
171
+ if (!exactKeys(input, ['challenge', 'confirmation']))
172
+ return rejected('credential.envelope.invalid', '/', 'schema');
173
+ const confirmation = input.confirmation;
174
+ if (!schema('schema.corrective-replan-human-confirmation-input', confirmation))
175
+ return rejected('credential.confirmation.input-invalid', '/confirmation', 'schema');
176
+ const challengeHandle = object(input.challenge);
177
+ const challenge = kernel.challenges.get(challengeHandle);
178
+ if (!challenge)
179
+ return rejected('credential.provenance.invalid', '/challenge', 'provenance');
180
+ if (!activePreparation(kernel, challenge.plan))
181
+ return rejected('credential.preparation.superseded', '/challenge', 'provenance');
182
+ if (kernel.confirmed.has(challengeHandle))
183
+ return rejected('credential.provenance.invalid', '/challenge', 'provenance');
184
+ const candidate = confirmation;
185
+ const now = safeTime(kernel.ports.now());
186
+ if (now === null)
187
+ return rejected('credential.time.invalid', '/coreClock', 'time');
188
+ const validatedAt = number(challenge.plan.attestation.validatedAtMs);
189
+ const issuedAt = number(challenge.challenge.issuedAtMs);
190
+ const expiresAt = number(challenge.challenge.expiresAtMs);
191
+ if (now >= expiresAt)
192
+ return rejected('credential.confirmation.expired', '/coreClock', 'time');
193
+ if (now < validatedAt || now < issuedAt)
194
+ return rejected('credential.confirmation.time-invalid', '/coreClock', 'time');
195
+ if (candidate.challengeId !== challenge.challenge.challengeId || sha(string(candidate.confirmationCode)) !== challenge.challenge.codeSha256)
196
+ return rejected('credential.confirmation.invalid', '/confirmation/confirmationCode', 'integrity');
197
+ const projection = { challengeId: challenge.challenge.challengeId, challengeHash: challenge.challenge.challengeHash,
198
+ bindingSha256: challenge.plan.binding.bindingSha256,
199
+ humanPrincipalIdentityHash: get(challenge.plan.binding, '/values/humanPrincipalIdentityHash'), confirmedAtMs: now };
200
+ const handle = opaque();
201
+ kernel.confirmations.set(handle, deepFreeze({ challenge, projection }));
202
+ kernel.confirmed.add(challengeHandle);
203
+ return accepted({ handle: handle, projection });
204
+ };
205
+ const issueReceipt = (issuer, input) => {
206
+ const kernel = kernels.get(object(issuer));
207
+ if (!kernel)
208
+ return rejected('credential.provenance.invalid', '/', 'provenance');
209
+ if (!exactKeys(input, ['planValidation', 'confirmation']))
210
+ return rejected('credential.envelope.invalid', '/', 'schema');
211
+ const plan = kernel.plans.get(object(input.planValidation));
212
+ const confirmationHandle = object(input.confirmation);
213
+ const confirmation = kernel.confirmations.get(confirmationHandle);
214
+ if (!plan || !confirmation || confirmation.challenge.plan !== plan)
215
+ return rejected('credential.provenance.invalid', '/', 'provenance');
216
+ if (!activePreparation(kernel, plan))
217
+ return rejected('credential.preparation.superseded', '/planValidation', 'provenance');
218
+ if (kernel.receipted.has(confirmationHandle))
219
+ return rejected('credential.provenance.invalid', '/', 'provenance');
220
+ const freshness = receiptFreshnessIssue(kernel, plan);
221
+ if (freshness)
222
+ return rejected(freshness.issueId, freshness.path, freshness.reasonClass);
223
+ const now = safeTime(kernel.ports.now());
224
+ if (now === null)
225
+ return rejected('credential.time.invalid', '/coreClock', 'time');
226
+ const confirmedAt = number(confirmation.projection.confirmedAtMs);
227
+ const validatedAt = number(plan.attestation.validatedAtMs);
228
+ const expiresAtMs = Math.min(number(plan.attestation.expiresAtMs), number(confirmation.challenge.challenge.expiresAtMs));
229
+ if (validatedAt > confirmedAt || confirmedAt > now || now >= expiresAtMs)
230
+ return rejected('credential.receipt.time-invalid', '/coreClock', 'time');
231
+ const values = record(plan.binding.values);
232
+ const author = values.planAuthorIdentityHash;
233
+ if (!authorityPassed('authority-role-evaluator.corrective-replan.eligible-role', {
234
+ actorIdentityHash: values.actorIdentityHash, actorRole: values.actorRole,
235
+ eligibleRoles: ['delivery-coordinator', 'technical-planner'],
236
+ }))
237
+ return rejected('credential.receipt.role-invalid', '/binding/values/actorRole', 'authority');
238
+ if (!authorityPassed('identity-comparator.corrective-replan.author-validator', {
239
+ leftIdentityHash: author, rightIdentityHash: values.planValidatorIdentityHash,
240
+ }) || !authorityPassed('identity-comparator.corrective-replan.author-risk-auditor', {
241
+ leftIdentityHash: author, rightIdentityHash: values.riskAuditorIdentityHash,
242
+ }) || !authorityPassed('identity-comparator.corrective-replan.author-human-principal', {
243
+ leftIdentityHash: author, rightIdentityHash: values.humanPrincipalIdentityHash,
244
+ }))
245
+ return rejected('credential.receipt.sod-invalid', '/binding/values', 'sod');
246
+ const snapshotGrant = record(plan.snapshot.priorPlanAuthorization);
247
+ const receiptId = safeId(kernel.ports.nextId('receipt'));
248
+ if (!receiptId || snapshotGrant.requiredDisposition !== 'superseded')
249
+ return rejected('credential.receipt.source-invalid', '/snapshot/priorPlanAuthorization', 'authority');
250
+ const validation = { attestationId: plan.attestation.attestationId, attestationHash: plan.attestation.attestationHash,
251
+ planValidationHash: values.planValidationHash, snapshotBindingHash: plan.snapshotBindingHash, planAuthorIdentityHash: values.planAuthorIdentityHash,
252
+ planValidatorIdentityHash: values.planValidatorIdentityHash, findingsHash: hashCanonical(plan.attestation.findings),
253
+ dispositionsHash: hashCanonical(plan.attestation.dispositions), validatedAtMs: plan.attestation.validatedAtMs,
254
+ expiresAtMs: plan.attestation.expiresAtMs };
255
+ const base = { schemaVersion: 1, receiptId, domain: 'codex-workflow/corrective-replan-receipt/v1',
256
+ binding: plan.binding, validation, audit: { riskAuditHash: values.riskAuditHash, riskAuditorIdentityHash: values.riskAuditorIdentityHash },
257
+ human: { challengeId: confirmation.projection.challengeId, challengeHash: confirmation.projection.challengeHash,
258
+ humanPrincipalIdentityHash: confirmation.projection.humanPrincipalIdentityHash, confirmedAtMs: confirmation.projection.confirmedAtMs },
259
+ supersession: { priorGrantHash: snapshotGrant.grantHash, disposition: 'superseded' },
260
+ issuedAtMs: now, expiresAtMs };
261
+ const withDomain = { ...base, domainHash: hashCanonical(base) };
262
+ const receipt = deepFreeze({ ...withDomain, receiptHash: hashCanonical(withDomain) });
263
+ if (!schema('schema.corrective-replan-receipt', receipt))
264
+ return rejected('credential.receipt.invalid', '/receipt', 'schema');
265
+ const handle = opaque();
266
+ kernel.receipts.set(handle, deepFreeze({ plan, confirmation, receipt }));
267
+ kernel.receipted.add(confirmationHandle);
268
+ return accepted({ handle: handle, receipt });
269
+ };
270
+ const verifyReceipt = (issuer, input) => {
271
+ const kernel = kernels.get(object(issuer));
272
+ if (!kernel)
273
+ return verificationRejected('credential.provenance.invalid', '/', 'provenance');
274
+ if (!exactKeys(input, ['receipt', 'candidate']))
275
+ return verificationRejected('credential.envelope.invalid', '/', 'schema');
276
+ const recordValue = kernel.receipts.get(object(input.receipt));
277
+ if (!recordValue)
278
+ return verificationRejected('credential.provenance.invalid', '/receipt', 'provenance');
279
+ const candidate = input.candidate;
280
+ if (!schema('schema.corrective-replan-receipt', candidate))
281
+ return verificationRejected('credential.receipt.invalid', '/candidate', 'schema');
282
+ if (!same(candidate, recordValue.receipt))
283
+ return verificationRejected('credential.receipt.mismatch', '/candidate', 'integrity');
284
+ const freshness = receiptFreshnessIssue(kernel, recordValue.plan);
285
+ if (freshness)
286
+ return verificationRejected(freshness.issueId, freshness.path, freshness.reasonClass);
287
+ const now = safeTime(kernel.ports.now());
288
+ if (now === null)
289
+ return verificationRejected('credential.time.invalid', '/coreClock', 'time');
290
+ if (now < number(recordValue.receipt.issuedAtMs))
291
+ return verificationRejected('credential.receipt.time-invalid', '/coreClock', 'time');
292
+ if (now >= number(recordValue.receipt.expiresAtMs))
293
+ return verificationRejected('credential.receipt.expired', '/coreClock', 'time');
294
+ return verified(recordValue.receipt);
295
+ };
296
+ const materializeStoredEvent = (issuer, input) => {
297
+ const kernel = kernels.get(object(issuer));
298
+ if (!kernel)
299
+ return rejected('credential.provenance.invalid', '/', 'provenance');
300
+ if (!exactKeys(input, ['receipt']))
301
+ return rejected('credential.envelope.invalid', '/', 'schema');
302
+ const handle = object(input.receipt);
303
+ const receipt = kernel.receipts.get(handle);
304
+ if (!receipt || kernel.evented.has(handle))
305
+ return rejected('credential.provenance.invalid', '/receipt', 'provenance');
306
+ const now = safeTime(kernel.ports.now());
307
+ if (now === null)
308
+ return rejected('credential.time.invalid', '/coreClock', 'time');
309
+ if (now < number(receipt.receipt.issuedAtMs))
310
+ return rejected('credential.event.time-invalid', '/coreClock', 'time');
311
+ const freshness = receiptFreshnessIssue(kernel, receipt.plan);
312
+ if (freshness)
313
+ return rejected(freshness.issueId, freshness.path, freshness.reasonClass);
314
+ if (now >= number(receipt.receipt.expiresAtMs))
315
+ return rejected('credential.receipt.expired', '/coreClock', 'time');
316
+ const tail = kernel.ports.readTail(string(get(receipt.receipt, '/binding/values/taskId')));
317
+ const previousEventHash = tail === null ? null : exactKeys(tail, ['eventHash']) ? tail.eventHash : undefined;
318
+ const eventId = safeId(kernel.ports.nextId('plan-validation-event'));
319
+ if (!(previousEventHash === null || hex(previousEventHash)) || !eventId)
320
+ return rejected('credential.event.source-invalid', '/validationEventTailSource', 'integrity');
321
+ const base = { schemaVersion: 1, eventId, previousEventHash, taskId: get(receipt.receipt, '/binding/values/taskId'),
322
+ candidatePlanHash: get(receipt.receipt, '/binding/values/candidatePlanHash'), attestationId: get(receipt.receipt, '/validation/attestationId'),
323
+ attestationHash: get(receipt.receipt, '/validation/attestationHash'), receiptId: receipt.receipt.receiptId,
324
+ receiptHash: receipt.receipt.receiptHash, receiptDomainHash: receipt.receipt.domainHash,
325
+ challengeId: receipt.confirmation.projection.challengeId, challengeHash: receipt.confirmation.projection.challengeHash,
326
+ recordedAt: new Date(now).toISOString(), recordedAtMs: now };
327
+ const event = deepFreeze({ ...base, eventHash: hashCanonical(base) });
328
+ if (!schema('schema.corrective-replan-stored-plan-validation-event', event))
329
+ return rejected('credential.event.invalid', '/event', 'schema');
330
+ const eventHandle = opaque();
331
+ kernel.events.set(eventHandle, deepFreeze({ receipt, event }));
332
+ kernel.evented.add(handle);
333
+ return accepted({ handle: eventHandle, event });
334
+ };
335
+ const verifyStoredEvent = (issuer, input) => {
336
+ const kernel = kernels.get(object(issuer));
337
+ if (!kernel)
338
+ return verificationRejected('credential.provenance.invalid', '/', 'provenance');
339
+ if (!exactKeys(input, ['event', 'candidate']))
340
+ return verificationRejected('credential.envelope.invalid', '/', 'schema');
341
+ const recordValue = kernel.events.get(object(input.event));
342
+ if (!recordValue)
343
+ return verificationRejected('credential.provenance.invalid', '/event', 'provenance');
344
+ const candidate = input.candidate;
345
+ if (!schema('schema.corrective-replan-stored-plan-validation-event', candidate))
346
+ return verificationRejected('credential.event.invalid', '/candidate', 'schema');
347
+ if (!same(candidate, recordValue.event))
348
+ return verificationRejected('credential.event.mismatch', '/candidate', 'integrity');
349
+ return verified(recordValue.event);
350
+ };
351
+ const functions = [issuePlanValidation, issueHumanChallenge, confirmHuman, issueReceipt, verifyReceipt, materializeStoredEvent, verifyStoredEvent];
352
+ const ids = ['credential-materializer.corrective-replan.plan-validation-attestation', 'credential-materializer.corrective-replan.expected-human-challenge',
353
+ 'credential-verifier.corrective-replan.human-confirmation', 'credential-materializer.corrective-replan.receipt',
354
+ 'credential-verifier.corrective-replan.receipt', 'credential-materializer.corrective-replan.stored-plan-validation-event',
355
+ 'credential-verifier.corrective-replan.stored-plan-validation-event'];
356
+ export const correctiveReplanCredentialFunctionBindings = deepFreeze(ids.map((id, index) => ({ id, version: 1,
357
+ kind: id.includes('materializer') ? 'materializer' : 'verifier', implementationId: `implementation.${id}`,
358
+ implementationVersion: 1, wiring: 'invoked', callable: functions[index] })));
359
+ function loadCanonicalSnapshot(kernel, taskId) {
360
+ const source = kernel.ports.readSnapshot(taskId);
361
+ if (!isRecord(source))
362
+ return issue('credential.snapshot.missing', '/taskId', 'binding');
363
+ if (source.bindingManifest !== correctiveReplanBindingManifest)
364
+ return issue('credential.snapshot.manifest-invalid', '/snapshot/bindingManifest', 'binding');
365
+ const invalid = snapshotIssue(source, taskId);
366
+ if (invalid)
367
+ return invalid;
368
+ const snapshot = deepFreeze({ ...clone(source), bindingManifest: correctiveReplanBindingManifest });
369
+ return { snapshot, snapshotBindingHash: hashCanonical(snapshot) };
370
+ }
371
+ function receiptFreshnessIssue(kernel, plan) {
372
+ const loaded = loadCanonicalSnapshot(kernel, string(get(plan.binding, '/values/taskId')));
373
+ if ('issueId' in loaded)
374
+ return issue('credential.receipt.snapshot-stale', '/snapshotBindingHash', 'binding');
375
+ if (!same(loaded.snapshot.priorPlanAuthorization, plan.snapshot.priorPlanAuthorization))
376
+ return issue('credential.receipt.grant-stale', '/snapshot/priorPlanAuthorization/grantHash', 'authority');
377
+ return loaded.snapshotBindingHash === plan.snapshotBindingHash ? null : issue('credential.receipt.snapshot-stale', '/snapshotBindingHash', 'binding');
378
+ }
379
+ function snapshotIssue(snapshot, taskId) {
380
+ if (!exactKeys(snapshot, ['snapshotVersion', 'bindingManifest', 'worktree', 'baseValues', 'validationExpectation', 'priorPlanAuthorization']) || snapshot.snapshotVersion !== 2)
381
+ return issue('credential.snapshot.invalid', '/snapshot', 'schema');
382
+ const base = record(snapshot.baseValues);
383
+ const expected = record(snapshot.validationExpectation);
384
+ if (base.taskId !== taskId || base.transitionId !== 'task.plan.corrective-replan' || base.capabilityId !== 'capability.task.corrective-replan'
385
+ || base.capabilityVersion !== 1 || base.lifecycleEpoch !== LIFECYCLE_EPOCH || !canonicalManifestValues(base, false))
386
+ return issue('credential.snapshot.values-invalid', '/snapshot/baseValues', 'binding');
387
+ if (!validWorktree(snapshot.worktree, base.gitHead) || !validExpectation(expected) || !exactKeys(snapshot.priorPlanAuthorization, ['grantHash', 'requiredDisposition'])
388
+ || !hex(record(snapshot.priorPlanAuthorization).grantHash) || record(snapshot.priorPlanAuthorization).requiredDisposition !== 'superseded')
389
+ return issue('credential.snapshot.invalid', '/snapshot/validationExpectation', 'schema');
390
+ const pairs = [['taskId', 'taskId'], ['revision', 'revision'], ['currentPlanHash', 'currentPlanHash'],
391
+ ['briefHash', 'briefHash'], ['knowledgeRevision', 'knowledgeRevision'], ['knowledgeHash', 'knowledgeHash'], ['gitHead', 'gitHead'],
392
+ ['guardedStepId', 'guardedStepId'], ['correctiveDecisionHash', 'correctiveDecisionHash'], ['remediationTailHash', 'remediationTailHash']];
393
+ if (pairs.some(([sourceKey, baseKey]) => get(expected, `/source/${sourceKey}`) !== base[baseKey])
394
+ || get(expected, '/candidate/planHash') !== base.candidatePlanHash || get(expected, '/candidate/stepSetHash') !== base.candidateStepSetHash
395
+ || get(expected, '/planAuthor/identityHash') !== base.planAuthorIdentityHash || get(expected, '/validator/identityHash') !== base.planValidatorIdentityHash)
396
+ return issue('credential.snapshot.cross-link-invalid', '/snapshot/validationExpectation', 'binding');
397
+ return null;
398
+ }
399
+ function validWorktree(value, gitHead) {
400
+ if (!exactKeys(value, ['kind', 'version', 'gitHead', 'changeSha256', 'entries'])
401
+ || value.kind !== 'guarded-step-worktree' || value.version !== 1 || value.gitHead !== gitHead
402
+ || !hex(value.changeSha256) || !Array.isArray(value.entries))
403
+ return false;
404
+ const entries = value.entries;
405
+ if (entries.length > 256)
406
+ return false;
407
+ const paths = new Set();
408
+ for (const candidate of entries) {
409
+ if (!isRecord(candidate) || typeof candidate.path !== 'string' || paths.has(candidate.path))
410
+ return false;
411
+ paths.add(candidate.path);
412
+ if (candidate.disposition === 'deleted') {
413
+ if (!exactKeys(candidate, ['path', 'disposition']))
414
+ return false;
415
+ }
416
+ else if (candidate.disposition === 'present') {
417
+ if (!exactKeys(candidate, ['path', 'disposition', 'executable', 'contentSha256'])
418
+ || typeof candidate.executable !== 'boolean' || !hex(candidate.contentSha256))
419
+ return false;
420
+ }
421
+ else
422
+ return false;
423
+ }
424
+ return entries.every((entry, index) => index === 0
425
+ || String(entries[index - 1].path).localeCompare(String(entry.path)) < 0)
426
+ && value.changeSha256 === hashCanonical({ domain: 'codex-workflow/corrective-replan-worktree/v1', entries });
427
+ }
428
+ function canonicalManifestValues(values, includePlanValidationHash) {
429
+ const rows = correctiveReplanBindingManifest.rows
430
+ .filter((row) => includePlanValidationHash || row.bindingId !== 'planValidationHash');
431
+ if (Object.keys(values).sort().join('\0') !== rows.map((row) => string(row.bindingId)).sort().join('\0'))
432
+ return false;
433
+ return rows.every((row) => {
434
+ const id = string(row.bindingId);
435
+ const value = values[id];
436
+ switch (row.canonicalization) {
437
+ case 'lowercase-hex': return hex(value);
438
+ case 'safe-nonnegative-integer': return safeTime(value) !== null;
439
+ case 'nfc-trim': return canonicalId(value);
440
+ case 'lowercase-git-oid': return typeof value === 'string' && /^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(value);
441
+ case 'registered-enum': return value === 'delivery-coordinator' || value === 'technical-planner';
442
+ case 'exact': return value === (id === 'transitionId' ? 'task.plan.corrective-replan' : 'capability.task.corrective-replan');
443
+ default: return false;
444
+ }
445
+ });
446
+ }
447
+ function validExpectation(value) {
448
+ return exactKeys(value, ['source', 'candidate', 'requirements', 'acceptance', 'architecture', 'planAuthor', 'plannerContext', 'validator'])
449
+ && exactKeys(value.source, ['taskId', 'revision', 'currentPlanHash', 'briefHash', 'knowledgeRevision', 'knowledgeHash', 'gitHead', 'guardedStepId', 'correctiveDecisionHash', 'remediationTailHash'])
450
+ && exactKeys(value.candidate, ['planHash', 'stepSetHash']) && validCoverage(value.requirements) && validCoverage(value.acceptance)
451
+ && validArchitecture(value.architecture) && validIdentity(value.planAuthor) && validIdentity(value.validator)
452
+ && validContext(value.plannerContext, true);
453
+ }
454
+ function exactDraft(value) {
455
+ if (!exactKeys(value, ['schemaVersion', 'requirements', 'acceptance', 'architecture', 'validatorContext', 'passed', 'findings', 'dispositions']))
456
+ return false;
457
+ const draft = value;
458
+ const findings = array(draft.findings);
459
+ const dispositions = array(draft.dispositions);
460
+ return draft.schemaVersion === 1 && draft.passed === true && validCoverage(draft.requirements) && validCoverage(draft.acceptance)
461
+ && validArchitecture(draft.architecture) && validContext(draft.validatorContext, false) && findings.length <= 128 && dispositions.length <= 128
462
+ && findings.every(validFinding) && dispositions.every(validDisposition);
463
+ }
464
+ function validCoverage(value) { return exactKeys(value, ['sourceHash', 'coverageHash', 'passed']) && hex(value.sourceHash) && hex(value.coverageHash) && value.passed === true; }
465
+ function validArchitecture(value) { return exactKeys(value, ['sourceHash', 'compatibilityHash', 'passed']) && hex(value.sourceHash) && hex(value.compatibilityHash) && value.passed === true; }
466
+ function validIdentity(value) { return exactKeys(value, ['identityHash']) && hex(value.identityHash); }
467
+ function validContext(value, captured) { return exactKeys(value, captured ? ['contextHash', 'capturedAtMs'] : ['contextHash']) && hex(value.contextHash) && (!captured || safeTime(value.capturedAtMs) !== null); }
468
+ function validFinding(value) { return exactKeys(value, ['findingId', 'severity', 'requirementRef', 'evidenceHash']) && canonicalId(value.findingId) && canonicalId(value.requirementRef) && ['low', 'medium', 'high'].includes(string(value.severity)) && hex(value.evidenceHash); }
469
+ function validDisposition(value) { return exactKeys(value, ['findingId', 'decision', 'evidenceHash']) && canonicalId(value.findingId) && ['resolved', 'accepted-documented-limitation'].includes(string(value.decision)) && hex(value.evidenceHash); }
470
+ function keyedBijection(findings, dispositions) {
471
+ const findingIds = findings.map((entry) => string(record(entry).findingId));
472
+ const dispositionIds = dispositions.map((entry) => string(record(entry).findingId));
473
+ return findingIds.length === dispositions.length
474
+ && findingIds.every(Boolean) && new Set(findingIds).size === findingIds.length && new Set(dispositionIds).size === dispositionIds.length
475
+ && [...findingIds].sort().join('\0') === [...dispositionIds].sort().join('\0');
476
+ }
477
+ function sortRows(rows) { return rows.map(clone).sort((a, b) => { const left = string(record(a).findingId); const right = string(record(b).findingId); return left < right ? -1 : left > right ? 1 : 0; }); }
478
+ function schema(id, value) { return correctiveReplanCredentialSchemaValidators.find((entry) => entry.id === id)?.callable(value) === true; }
479
+ function accepted(value) { return deepFreeze({ ok: true, value: deepFreeze(value), issues: [] }); }
480
+ function rejected(issueId, path, reasonClass) { const issues = [issue(issueId, path, reasonClass)]; return deepFreeze({ ok: false, value: null, issues, reportHash: hashCanonical(issues) }); }
481
+ function verified(projection) { const content = { valid: true, projection: deepFreeze(projection), issues: [] }; return deepFreeze({ ...content, reportHash: hashCanonical(content) }); }
482
+ function verificationRejected(issueId, path, reasonClass) { const issues = [issue(issueId, path, reasonClass)]; return deepFreeze({ valid: false, projection: null, issues, reportHash: hashCanonical(issues) }); }
483
+ function issue(issueId, path, reasonClass) { return { issueId, path, reasonClass }; }
484
+ function totalResult(invoke) { try {
485
+ return invoke();
486
+ }
487
+ catch {
488
+ return rejected('credential.operation.malformed', '/', 'schema');
489
+ } }
490
+ function totalVerification(invoke) { try {
491
+ return invoke();
492
+ }
493
+ catch {
494
+ return verificationRejected('credential.operation.malformed', '/', 'schema');
495
+ } }
496
+ function activePreparation(kernel, plan) { const current = kernel.preparations.get(plan.preparationKey); return current?.status === 'active' && current.generation === plan.generation; }
497
+ function exactKeys(value, keys) { return isRecord(value) && Object.keys(value).sort().join('\0') === [...keys].sort().join('\0'); }
498
+ function isRecord(value) { return value !== null && typeof value === 'object' && !Array.isArray(value); }
499
+ function copyOwnedJson(value, budget = { nodes: 0, bytes: 0, active: new Set() }, depth = 0) {
500
+ if (++budget.nodes > 4096 || (budget.bytes += 8) > 262_144 || depth > 32)
501
+ return LIMIT;
502
+ if (typeof value === 'string') {
503
+ budget.bytes += Buffer.byteLength(value, 'utf8');
504
+ return budget.bytes > 262_144 ? LIMIT : value;
505
+ }
506
+ if (value === null || typeof value === 'boolean')
507
+ return value;
508
+ if (typeof value === 'number')
509
+ return Number.isSafeInteger(value) ? value : MALFORMED;
510
+ if (typeof value !== 'object' || utilTypes.isProxy(value) || budget.active.has(value))
511
+ return MALFORMED;
512
+ const arrayValue = Array.isArray(value);
513
+ const prototype = Object.getPrototypeOf(value);
514
+ if (prototype !== (arrayValue ? Array.prototype : Object.prototype) && prototype !== null)
515
+ return MALFORMED;
516
+ const keys = Reflect.ownKeys(value);
517
+ if (keys.some((key) => typeof key !== 'string'))
518
+ return MALFORMED;
519
+ const names = keys.filter((key) => !arrayValue || key !== 'length');
520
+ const descriptors = Object.getOwnPropertyDescriptors(value);
521
+ if (arrayValue && (names.length !== value.length || names.some((key, index) => key !== String(index))))
522
+ return MALFORMED;
523
+ const result = arrayValue ? [] : Object.create(null);
524
+ budget.active.add(value);
525
+ for (const key of names) {
526
+ const descriptor = descriptors[key];
527
+ budget.bytes += Buffer.byteLength(key, 'utf8');
528
+ if (budget.bytes > 262_144)
529
+ return LIMIT;
530
+ if (!descriptor?.enumerable || !('value' in descriptor))
531
+ return MALFORMED;
532
+ const child = copyOwnedJson(descriptor.value, budget, depth + 1);
533
+ if (child === LIMIT || child === MALFORMED)
534
+ return child;
535
+ result[key] = child;
536
+ }
537
+ budget.active.delete(value);
538
+ return result;
539
+ }
540
+ function record(value) { return isRecord(value) ? value : {}; }
541
+ function object(value) { return value !== null && typeof value === 'object' ? value : Object.freeze(Object.create(null)); }
542
+ function opaque() { return Object.freeze(Object.create(null)); }
543
+ function array(value) { return Array.isArray(value) ? value : []; }
544
+ function string(value) { return typeof value === 'string' ? value : ''; }
545
+ function number(value) { return typeof value === 'number' ? value : Number.NaN; }
546
+ function safeTime(value) { return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0 && value <= MAX_SAFE ? value : null; }
547
+ function safeId(value) { return canonicalId(value) ? value : ''; }
548
+ function canonicalId(value) { return typeof value === 'string' && value.length > 0 && value.length <= 256 && value === value.trim() && value === value.normalize('NFC'); }
549
+ function hex(value) { return typeof value === 'string' && /^[a-f0-9]{64}$/.test(value); }
550
+ function get(value, path) { return path.split('/').filter(Boolean).reduce((cursor, key) => isRecord(cursor) ? cursor[key] : undefined, value); }
551
+ function same(left, right) { try {
552
+ return hashCanonical(left) === hashCanonical(right);
553
+ }
554
+ catch {
555
+ return false;
556
+ } }
557
+ function authorityPassed(id, input) {
558
+ const binding = installedAuthoritySemanticBindings.find((entry) => entry.id === id);
559
+ return binding !== undefined && record(binding.callable(input)).passed === true;
560
+ }
561
+ function clone(value) { return structuredClone(value); }
562
+ function sha(value) { return createHash('sha256').update(value).digest('hex'); }
563
+ //# sourceMappingURL=corrective-replan-credential-core.js.map