codex-workflow-v2 2.0.0-beta.13.8 → 2.0.0-beta.14
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/README.md +27 -388
- package/dist/reviewer-runtime-build.json +96 -32
- package/dist/src/alpha6/adoption.d.ts +2 -0
- package/dist/src/alpha6/adoption.js +22 -0
- package/dist/src/alpha6/adoption.js.map +1 -1
- package/dist/src/alpha6/captured-check-evidence.d.ts +51 -0
- package/dist/src/alpha6/captured-check-evidence.js +152 -0
- package/dist/src/alpha6/captured-check-evidence.js.map +1 -0
- package/dist/src/alpha6/component-owner.d.ts +15 -1
- package/dist/src/alpha6/component-owner.js +44 -2
- package/dist/src/alpha6/component-owner.js.map +1 -1
- package/dist/src/alpha6/corrective-decision-boundary.d.ts +4 -0
- package/dist/src/alpha6/corrective-decision-boundary.js +47 -0
- package/dist/src/alpha6/corrective-decision-boundary.js.map +1 -0
- package/dist/src/alpha6/downstream-proof.d.ts +1 -25
- package/dist/src/alpha6/downstream-proof.js +0 -171
- package/dist/src/alpha6/downstream-proof.js.map +1 -1
- package/dist/src/alpha6/failed-step-planning-recovery.d.ts +10 -0
- package/dist/src/alpha6/failed-step-planning-recovery.js +93 -0
- package/dist/src/alpha6/failed-step-planning-recovery.js.map +1 -0
- package/dist/src/alpha6/literal-test-invocation.d.ts +2 -0
- package/dist/src/alpha6/literal-test-invocation.js +106 -0
- package/dist/src/alpha6/literal-test-invocation.js.map +1 -0
- package/dist/src/alpha6/milestone.d.ts +2 -0
- package/dist/src/alpha6/milestone.js +10 -1
- package/dist/src/alpha6/milestone.js.map +1 -1
- package/dist/src/alpha6/navigation-dirty-carryover.d.ts +11 -0
- package/dist/src/alpha6/navigation-dirty-carryover.js +130 -0
- package/dist/src/alpha6/navigation-dirty-carryover.js.map +1 -0
- package/dist/src/alpha6/plan-integrity.js +7 -5
- package/dist/src/alpha6/plan-integrity.js.map +1 -1
- package/dist/src/alpha6/plan-risk.d.ts +2 -0
- package/dist/src/alpha6/plan-risk.js +10 -3
- package/dist/src/alpha6/plan-risk.js.map +1 -1
- package/dist/src/alpha6/remediation.d.ts +6 -21
- package/dist/src/alpha6/remediation.js +161 -476
- package/dist/src/alpha6/remediation.js.map +1 -1
- package/dist/src/alpha6/root-cause-replan-carryover.d.ts +4 -1
- package/dist/src/alpha6/root-cause-replan-carryover.js +29 -5
- package/dist/src/alpha6/root-cause-replan-carryover.js.map +1 -1
- package/dist/src/beta1/project-transaction.d.ts +3 -1
- package/dist/src/beta1/project-transaction.js +6 -2
- package/dist/src/beta1/project-transaction.js.map +1 -1
- package/dist/src/checks/runner.d.ts +26 -0
- package/dist/src/checks/runner.js +223 -0
- package/dist/src/checks/runner.js.map +1 -0
- package/dist/src/checks/task-sync.d.ts +10 -0
- package/dist/src/checks/task-sync.js +41 -0
- package/dist/src/checks/task-sync.js.map +1 -0
- package/dist/src/checks/worker.d.ts +1 -0
- package/dist/src/checks/worker.js +154 -0
- package/dist/src/checks/worker.js.map +1 -0
- package/dist/src/cli-actions.d.ts +2 -2
- package/dist/src/cli-actions.js +3 -15
- package/dist/src/cli-actions.js.map +1 -1
- package/dist/src/cli.js +14 -98
- package/dist/src/cli.js.map +1 -1
- package/dist/src/contracts.d.ts +35 -32
- package/dist/src/dependency-provenance.d.ts +2 -2
- package/dist/src/dependency-provenance.js +12 -69
- package/dist/src/dependency-provenance.js.map +1 -1
- package/dist/src/domain/base-sync-conflict.d.ts +13 -0
- package/dist/src/domain/base-sync-conflict.js +32 -0
- package/dist/src/domain/base-sync-conflict.js.map +1 -0
- package/dist/src/domain/step-start-admission.d.ts +4 -0
- package/dist/src/domain/step-start-admission.js +9 -0
- package/dist/src/domain/step-start-admission.js.map +1 -0
- package/dist/src/domain/virgin-registration.d.ts +3 -0
- package/dist/src/domain/virgin-registration.js +65 -0
- package/dist/src/domain/virgin-registration.js.map +1 -0
- package/dist/src/errors.d.ts +1 -1
- package/dist/src/errors.js.map +1 -1
- package/dist/src/gateway-handshake.js +0 -8
- package/dist/src/gateway-handshake.js.map +1 -1
- package/dist/src/git.d.ts +3 -1
- package/dist/src/git.js +41 -14
- package/dist/src/git.js.map +1 -1
- package/dist/src/graph.js +25 -3
- package/dist/src/graph.js.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/lifecycle/corrective-replan.js +3 -3
- package/dist/src/lifecycle/corrective-replan.js.map +1 -1
- package/dist/src/navigation-actions.d.ts +9 -0
- package/dist/src/navigation-actions.js +72 -0
- package/dist/src/navigation-actions.js.map +1 -0
- package/dist/src/navigation-update-artifact.d.ts +5 -0
- package/dist/src/navigation-update-artifact.js +227 -0
- package/dist/src/navigation-update-artifact.js.map +1 -0
- package/dist/src/navigation-update.d.ts +39 -0
- package/dist/src/navigation-update.js +82 -0
- package/dist/src/navigation-update.js.map +1 -0
- package/dist/src/observation.js +52 -29
- package/dist/src/observation.js.map +1 -1
- package/dist/src/observed-routes.js +5 -6
- package/dist/src/observed-routes.js.map +1 -1
- package/dist/src/pending-review-update.d.ts +0 -13
- package/dist/src/pending-review-update.js +1 -6
- package/dist/src/pending-review-update.js.map +1 -1
- package/dist/src/reviewer.d.ts +1 -1
- package/dist/src/reviewer.js +20 -17
- package/dist/src/reviewer.js.map +1 -1
- package/dist/src/runtime.d.ts +3 -0
- package/dist/src/runtime.js +6 -0
- package/dist/src/runtime.js.map +1 -0
- package/dist/src/state/corrective-replan-executor.d.ts +10 -0
- package/dist/src/state/corrective-replan-executor.js +37 -1
- package/dist/src/state/corrective-replan-executor.js.map +1 -1
- package/dist/src/state/corrective-replan-public-schema.js +15 -2
- package/dist/src/state/corrective-replan-public-schema.js.map +1 -1
- package/dist/src/state/corrective-replan-public.js +6 -5
- package/dist/src/state/corrective-replan-public.js.map +1 -1
- package/dist/src/state/corrective-replan-transaction.d.ts +1 -0
- package/dist/src/state/corrective-replan-transaction.js +12 -11
- package/dist/src/state/corrective-replan-transaction.js.map +1 -1
- package/dist/src/state/corrective-yield-executor.js +2 -2
- package/dist/src/state/corrective-yield-executor.js.map +1 -1
- package/dist/src/state/corrective-yield-transaction.d.ts +1 -0
- package/dist/src/state/corrective-yield-transaction.js +11 -10
- package/dist/src/state/corrective-yield-transaction.js.map +1 -1
- package/dist/src/state/lock.d.ts +4 -0
- package/dist/src/state/lock.js +21 -0
- package/dist/src/state/lock.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/version.js.map +1 -1
- package/dist/src/workflow-blocker-route.d.ts +8 -0
- package/dist/src/workflow-blocker-route.js +106 -0
- package/dist/src/workflow-blocker-route.js.map +1 -0
- package/dist/src/workflow.d.ts +48 -63
- package/dist/src/workflow.js +698 -1470
- package/dist/src/workflow.js.map +1 -1
- package/docs/autonomy-guardrails.md +26 -304
- package/docs/decisions.md +14 -112
- package/docs/development-flow.md +35 -238
- package/docs/project-memory.md +31 -50
- package/docs/release-app-evidence.md +190 -0
- package/docs/release.md +95 -363
- package/docs/updating-existing-project.md +19 -717
- package/package.json +11 -13
- package/plugins/codex-workflow-gateway/.codex-plugin/plugin.json +2 -2
- package/plugins/codex-workflow-gateway/references/chat-dispatch.md +73 -197
- package/plugins/codex-workflow-gateway/references/codebase-memory-routing.md +57 -0
- package/plugins/codex-workflow-gateway/references/protocol.md +42 -445
- package/plugins/codex-workflow-gateway/scripts/chat-dispatch.mjs +7 -1
- package/plugins/codex-workflow-gateway/scripts/chat-model-policy.mjs +10 -8
- package/plugins/codex-workflow-gateway/scripts/chat-registry.mjs +23 -5
- package/plugins/codex-workflow-gateway/skills/codex-workflow-gateway/SKILL.md +66 -740
- package/references/state-machine.md +4 -4
- package/roles/technical-planner.md +1 -1
- package/schemas/corrective-decision-event.schema.json +3 -1
- package/schemas/project-knowledge-map.schema.json +3 -1
- package/schemas/remediation-event.schema.json +10 -1
- package/schemas/task.schema.json +46 -2
- package/schemas/transition-payloads.schema.json +16 -1
- package/src/alpha6/adoption.ts +1123 -0
- package/src/alpha6/captured-check-evidence.ts +132 -0
- package/src/alpha6/check-support-anchor.ts +128 -0
- package/src/alpha6/component-owner.ts +168 -0
- package/src/alpha6/corrective-decision-boundary.ts +39 -0
- package/src/alpha6/downstream-proof.ts +520 -0
- package/src/alpha6/failed-step-planning-recovery.ts +88 -0
- package/src/alpha6/handoff.ts +1443 -0
- package/src/alpha6/journal.ts +473 -0
- package/src/alpha6/literal-test-invocation.ts +84 -0
- package/src/alpha6/mechanical-feasibility.ts +488 -0
- package/src/alpha6/milestone.ts +2192 -0
- package/src/alpha6/navigation-dirty-carryover.ts +154 -0
- package/src/alpha6/npm-check-contract.ts +47 -0
- package/src/alpha6/plan-integrity.ts +298 -0
- package/src/alpha6/plan-risk.ts +1480 -0
- package/src/alpha6/preexecution-replan.ts +187 -0
- package/src/alpha6/remediation-cause.ts +98 -0
- package/src/alpha6/remediation.ts +2438 -0
- package/src/alpha6/review.ts +1198 -0
- package/src/alpha6/root-cause-replan-carryover.ts +491 -0
- package/src/alpha6/store-sidecars.ts +335 -0
- package/src/alpha7/autonomy.ts +411 -0
- package/src/alpha7/corrective-recovery.ts +1332 -0
- package/src/artifacts.ts +130 -0
- package/src/beta1/project-transaction.ts +355 -0
- package/src/change-explanation.ts +153 -0
- package/src/checks/runner.ts +245 -0
- package/src/checks/task-sync.ts +41 -0
- package/src/checks/worker.ts +149 -0
- package/src/cli-actions.ts +107 -0
- package/src/cli.ts +1457 -0
- package/src/contracts.ts +1494 -0
- package/src/credential-output.ts +89 -0
- package/src/credential-transport.ts +215 -0
- package/src/delegation.ts +190 -0
- package/src/dependency-provenance.ts +472 -0
- package/src/diagnostics.ts +93 -0
- package/src/domain/base-sync-conflict.ts +35 -0
- package/src/domain/completed-step-carryover.ts +76 -0
- package/src/domain/discovery.ts +27 -0
- package/src/domain/plan-semantics.ts +58 -0
- package/src/domain/step-start-admission.ts +10 -0
- package/src/domain/validation.ts +177 -0
- package/src/domain/virgin-registration.ts +46 -0
- package/src/errors.ts +24 -0
- package/src/fs-utils.ts +61 -0
- package/src/gateway-handshake.ts +95 -0
- package/src/git.ts +183 -0
- package/src/graph.ts +342 -0
- package/src/historical-step-provenance.ts +136 -0
- package/src/index.ts +23 -0
- package/src/lifecycle/canonical-hash.ts +28 -0
- package/src/lifecycle/catalog.ts +202 -0
- package/src/lifecycle/compiler-inspection.ts +29 -0
- package/src/lifecycle/core-static-readiness.ts +132 -0
- package/src/lifecycle/corrective-replan-authority.ts +136 -0
- package/src/lifecycle/corrective-replan-binding-manifest.ts +51 -0
- package/src/lifecycle/corrective-replan-credential-core.ts +408 -0
- package/src/lifecycle/corrective-replan-credential-schema.ts +54 -0
- package/src/lifecycle/corrective-replan-credentials.ts +48 -0
- package/src/lifecycle/corrective-replan.ts +843 -0
- package/src/lifecycle/evaluator.ts +48 -0
- package/src/lifecycle/fingerprint.ts +488 -0
- package/src/lifecycle/immutable.ts +8 -0
- package/src/lifecycle/implementation-table.ts +118 -0
- package/src/lifecycle/index.ts +8 -0
- package/src/lifecycle/schema-artifact.ts +263 -0
- package/src/lifecycle/semantic-registry.ts +572 -0
- package/src/lifecycle/types.ts +838 -0
- package/src/memory.ts +273 -0
- package/src/migration.ts +161 -0
- package/src/navigation-actions.ts +70 -0
- package/src/navigation-update-artifact.ts +198 -0
- package/src/navigation-update.ts +121 -0
- package/src/observation.ts +225 -0
- package/src/observed-routes.ts +660 -0
- package/src/operational-contract.ts +125 -0
- package/src/pending-review-update.ts +175 -0
- package/src/repository.ts +99 -0
- package/src/reviewer.ts +1879 -0
- package/src/runtime.ts +6 -0
- package/src/state/corrective-replan-executor.ts +818 -0
- package/src/state/corrective-replan-public-schema.ts +83 -0
- package/src/state/corrective-replan-public.ts +908 -0
- package/src/state/corrective-replan-transaction.ts +949 -0
- package/src/state/corrective-yield-executor.ts +327 -0
- package/src/state/corrective-yield-transaction.ts +730 -0
- package/src/state/lock.ts +902 -0
- package/src/state/store.ts +567 -0
- package/src/transition-core.ts +330 -0
- package/src/ulid.ts +24 -0
- package/src/version.ts +2 -0
- package/src/workflow-blocker-route.ts +109 -0
- package/src/workflow.ts +10172 -0
- package/docs/alpha7.1-implementation-brief.md +0 -268
- package/docs/alpha7.2-corrective-context-refresh-brief.md +0 -484
- package/docs/alpha7.2.1-remediation-recovery-brief.md +0 -86
- package/docs/beta1-stabilization-brief.md +0 -165
- package/docs/beta11-plan-integrity-recovery-brief.md +0 -38
- package/docs/beta13.2-signal-review-recovery.md +0 -38
- package/docs/beta2-initial-assembly-navigation-brief.md +0 -616
- package/docs/change-model.md +0 -118
- package/docs/delegated-approval.md +0 -254
- package/docs/lifecycle/state-machine-stabilization.md +0 -641
- package/docs/pdf/README.md +0 -24
- package/docs/pdf/codex-workflow-v2-architecture-ru.pdf +0 -0
- package/docs/pdf/codex-workflow-v2-chat-only-guide-ru.pdf +0 -0
- package/docs/pdf/codex-workflow-v2-technical-reference-ru.pdf +0 -0
- package/docs/pdf/requirements.txt +0 -1
- package/docs/pdf/sources/codex-workflow-v2-architecture-ru.md +0 -478
- package/docs/pdf/sources/codex-workflow-v2-chat-only-guide-ru.md +0 -508
- package/docs/pdf/sources/codex-workflow-v2-technical-reference-ru.md +0 -778
- package/docs/pending-review-update.md +0 -15
- package/docs/problem-briefs/01-pre-implementation-integrity.md +0 -482
- package/docs/problem-briefs/02-minimal-step-integrity.md +0 -411
- package/docs/problem-briefs/03-minimal-agent-context-integrity.md +0 -358
- package/docs/problem-briefs/04-task-dependency-and-structural-replacement-integrity.md +0 -573
- package/docs/problem-briefs/BRIEF-TEMPLATE.md +0 -56
- package/docs/problem-briefs/README.md +0 -120
- package/docs/problem-briefs/evidence/p01-mechanical-feasibility-corpus.md +0 -90
- package/docs/problem-briefs/evidence/signal-v4-pre-m3-replay.md +0 -246
- package/docs/split-required-recovery.md +0 -47
- package/docs/stable-release-defect-register.md +0 -730
- package/docs/validation-report.md +0 -182
- package/scripts/generate-pdf-docs.py +0 -524
- package/scripts/run-pdf-docs.mjs +0 -62
|
@@ -0,0 +1,572 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CoverageProfileRegistryEntry,
|
|
3
|
+
CredentialPolicyRegistryEntry,
|
|
4
|
+
GuardEvaluatorRegistryEntry,
|
|
5
|
+
IdentityComparatorRegistryEntry,
|
|
6
|
+
IdentityRegistryEntry,
|
|
7
|
+
InputRegistryEntry,
|
|
8
|
+
LimitationRegistryEntry,
|
|
9
|
+
ProjectionFieldId,
|
|
10
|
+
ProjectionFieldRef,
|
|
11
|
+
ProjectionRegistryEntry,
|
|
12
|
+
RegisteredCoverageProfileRef,
|
|
13
|
+
RegisteredRef,
|
|
14
|
+
RegisteredReleaseProfileRef,
|
|
15
|
+
ReleaseProfileRegistryEntry,
|
|
16
|
+
SemanticRegistry,
|
|
17
|
+
SemanticRuleRegistryEntry,
|
|
18
|
+
VersionedRegistryEntry,
|
|
19
|
+
} from './types.js';
|
|
20
|
+
import { deepFreeze } from './immutable.js';
|
|
21
|
+
import { correctiveReplanBindingManifest } from './corrective-replan-binding-manifest.js';
|
|
22
|
+
|
|
23
|
+
const v1 = <TId extends string>(id: TId): RegisteredRef<TId> => ({ id, version: 1 });
|
|
24
|
+
|
|
25
|
+
const correctiveSnapshotRef = v1('projection.corrective-replan.snapshot');
|
|
26
|
+
const correctiveBindingRef = v1('projection.corrective-replan.bindings');
|
|
27
|
+
|
|
28
|
+
export const exactTransitionCoverageProfileRef: RegisteredCoverageProfileRef =
|
|
29
|
+
v1('coverage-profile.exact-transition');
|
|
30
|
+
export const exactMutationReleaseProfileRef: RegisteredReleaseProfileRef =
|
|
31
|
+
v1('release-profile.exact-mutation');
|
|
32
|
+
|
|
33
|
+
const schemas = [
|
|
34
|
+
schema('schema.corrective-replan-bindings', 'object', 'Exact corrective transition bindings.'),
|
|
35
|
+
schema('schema.corrective-replan-snapshot', 'object', 'Current corrective transition snapshot.'),
|
|
36
|
+
schema('schema.corrective-replan-binding', 'object', 'Exact state-bound receipt binding.'),
|
|
37
|
+
schema('schema.corrective-replan-plan-validation-attestation', 'object', 'Passed independent Plan Validation attestation.'),
|
|
38
|
+
schema('schema.corrective-replan-receipt', 'object', 'Human-confirmed execution receipt.'),
|
|
39
|
+
schema('schema.corrective-replan-task-transaction', 'object', 'Retained corrective-replan Task transaction journal.'),
|
|
40
|
+
schema('schema.expected-revision', 'integer', 'Expected Task revision.'),
|
|
41
|
+
schema('schema.plan-risk-audit-input', 'object', 'Replacement Plan Risk Audit input.'),
|
|
42
|
+
schema('schema.task-id', 'string', 'Task identity.'),
|
|
43
|
+
schema('schema.task-plan-input', 'object', 'Materialized replacement Task Plan input.'),
|
|
44
|
+
schema('schema.task-state-readback', 'object', 'Task state readback after Plan replacement.'),
|
|
45
|
+
] as const;
|
|
46
|
+
|
|
47
|
+
const manifestFields = correctiveReplanBindingManifest.rows.map(({ projection: _projection, ...entry }) => entry.fieldId);
|
|
48
|
+
const manifestProjectionFields = (projectionId: string) => correctiveReplanBindingManifest.rows
|
|
49
|
+
.filter((entry) => entry.projection.id === projectionId)
|
|
50
|
+
.map((entry) => entry.fieldId);
|
|
51
|
+
const executionKeyFields = correctiveReplanBindingManifest.rows.map(({ projection, fieldId }) => ({ projection, fieldId }));
|
|
52
|
+
|
|
53
|
+
const projections: readonly ProjectionRegistryEntry[] = [
|
|
54
|
+
projection('projection.corrective-replan.bindings', 'schema.corrective-replan-bindings', [
|
|
55
|
+
'field.candidate-plan-hash',
|
|
56
|
+
'field.candidate-step-ids',
|
|
57
|
+
'field.corrective-decision-event-id',
|
|
58
|
+
'field.current-plan-hash',
|
|
59
|
+
'field.expected-revision',
|
|
60
|
+
'field.step-id',
|
|
61
|
+
'field.task-id',
|
|
62
|
+
], 'Current navigation and candidate execution bindings.'),
|
|
63
|
+
projection('projection.corrective-replan.protocol', 'schema.corrective-replan-binding', manifestProjectionFields('projection.corrective-replan.protocol'), 'Protocol and catalog receipt bindings.'),
|
|
64
|
+
projection('projection.corrective-replan.state', 'schema.corrective-replan-binding', manifestProjectionFields('projection.corrective-replan.state'), 'Current Task, Knowledge, Git, and corrective posture bindings.'),
|
|
65
|
+
projection('projection.corrective-replan.candidate', 'schema.corrective-replan-binding', manifestProjectionFields('projection.corrective-replan.candidate'), 'Candidate Plan, Validation, and Risk Audit bindings.'),
|
|
66
|
+
projection('projection.corrective-replan.authority', 'schema.corrective-replan-binding', manifestProjectionFields('projection.corrective-replan.authority'), 'Actor, Human principal, and capability bindings.'),
|
|
67
|
+
projection('projection.corrective-replan.execution-receipt', 'schema.corrective-replan-receipt', manifestFields, 'Exact 30-field execution receipt binding.'),
|
|
68
|
+
projection('projection.corrective-replan.snapshot', 'schema.corrective-replan-snapshot', [
|
|
69
|
+
'field.candidate-plan-hash',
|
|
70
|
+
'field.candidate-step-ids',
|
|
71
|
+
'field.corrective-decision-decision',
|
|
72
|
+
'field.corrective-decision-event-id',
|
|
73
|
+
'field.corrective-decision-plan-hash',
|
|
74
|
+
'field.corrective-decision-step-id',
|
|
75
|
+
'field.corrective-decision-triggering-attempt-count',
|
|
76
|
+
'field.corrective-posture',
|
|
77
|
+
'field.current-plan-hash',
|
|
78
|
+
'field.in-progress-step-ids',
|
|
79
|
+
'field.remediation-attempt-count',
|
|
80
|
+
'field.step-id',
|
|
81
|
+
'field.step-status',
|
|
82
|
+
'field.task-id',
|
|
83
|
+
'field.task-revision',
|
|
84
|
+
'field.task-status',
|
|
85
|
+
'field.actor-role-eligible',
|
|
86
|
+
'field.c1-claim-absent',
|
|
87
|
+
'field.writer-lease-absent',
|
|
88
|
+
'field.plan-validation-passed',
|
|
89
|
+
'field.receipt-valid',
|
|
90
|
+
'field.risk-audit-passed',
|
|
91
|
+
], 'Current mutation-free corrective evaluator snapshot.'),
|
|
92
|
+
projection('projection.input.expected-revision', 'schema.expected-revision', [
|
|
93
|
+
'field.expected-revision',
|
|
94
|
+
], 'Expected revision input.'),
|
|
95
|
+
projection('projection.input.plan-risk-audit', 'schema.plan-risk-audit-input', [
|
|
96
|
+
'field.risk-audit-hash',
|
|
97
|
+
'field.risk-auditor-identity-hash',
|
|
98
|
+
], 'Replacement Plan Risk Audit input.'),
|
|
99
|
+
projection('projection.input.plan-validation', 'schema.corrective-replan-plan-validation-attestation', [
|
|
100
|
+
'field.plan-validation-hash', 'field.plan-validator-identity-hash',
|
|
101
|
+
], 'Independent candidate-bound Plan Validation input.'),
|
|
102
|
+
projection('projection.input.execution-receipt', 'schema.corrective-replan-receipt', manifestFields, 'Explicit state-bound corrective-replan receipt.'),
|
|
103
|
+
projection('projection.input.replacement-plan', 'schema.task-plan-input', [
|
|
104
|
+
'field.candidate-plan-hash',
|
|
105
|
+
'field.candidate-step-ids',
|
|
106
|
+
'field.candidate-step-set-hash',
|
|
107
|
+
], 'Prepared replacement Plan input.'),
|
|
108
|
+
projection('projection.input.task-id', 'schema.task-id', [
|
|
109
|
+
'field.task-id',
|
|
110
|
+
], 'Task identity input.'),
|
|
111
|
+
projection('projection.task-state.readback', 'schema.task-state-readback', [
|
|
112
|
+
'field.task-id',
|
|
113
|
+
'field.task-plan-hash',
|
|
114
|
+
'field.task-revision',
|
|
115
|
+
'field.task-status',
|
|
116
|
+
], 'Task state post-effect readback projection.'),
|
|
117
|
+
projection('projection.corrective-replan.terminal-readback', 'schema.task-state-readback', [
|
|
118
|
+
'field.task-id', 'field.task-revision', 'field.task-status', 'field.current-plan-hash',
|
|
119
|
+
'field.plan-validation-hash', 'field.risk-audit-hash', 'field.runtime-fingerprint', 'field.catalog-hash',
|
|
120
|
+
], 'Domain and retained-terminal-journal readback projection.'),
|
|
121
|
+
];
|
|
122
|
+
|
|
123
|
+
const inputs: readonly InputRegistryEntry[] = [
|
|
124
|
+
input('input.corrective-plan-risk-audit', 'operator-input', 'risk-audit-file', 'schema.plan-risk-audit-input', 'projection.input.plan-risk-audit', 'hash-policy.canonical-json-sha256', 'Replacement Plan Risk Audit.'),
|
|
125
|
+
input('input.corrective-plan-validation', 'operator-input', 'validation-file', 'schema.corrective-replan-plan-validation-attestation', 'projection.input.plan-validation', 'hash-policy.canonical-json-sha256', 'Independent passed Plan Validation.'),
|
|
126
|
+
input('input.corrective-execution-receipt', 'credential', 'credential-file', 'schema.corrective-replan-receipt', 'projection.input.execution-receipt', 'hash-policy.canonical-json-sha256', 'Human-confirmed exact execution receipt.'),
|
|
127
|
+
input('input.corrective-replacement-plan', 'operator-input', 'file', 'schema.task-plan-input', 'projection.input.replacement-plan', 'hash-policy.raw-sha256', 'Replacement Plan.'),
|
|
128
|
+
input('input.expected-revision', 'binding', 'expected-revision', 'schema.expected-revision', 'projection.input.expected-revision', null, 'Expected Task revision.'),
|
|
129
|
+
input('input.task-id', 'binding', 'id', 'schema.task-id', 'projection.input.task-id', null, 'Task identity.'),
|
|
130
|
+
];
|
|
131
|
+
|
|
132
|
+
const identities: readonly IdentityRegistryEntry[] = [
|
|
133
|
+
identity('identity.actor', { kind: 'projection', field: field('projection.corrective-replan.authority', 'field.actor-identity-hash') }, 'Receipt-bound executing actor.'),
|
|
134
|
+
identity('identity.human-principal', { kind: 'projection', field: field('projection.corrective-replan.authority', 'field.human-principal-identity-hash') }, 'Human confirmation principal.'),
|
|
135
|
+
identity('identity.plan-author', { kind: 'projection', field: field('projection.corrective-replan.candidate', 'field.plan-author-identity-hash') }, 'Replacement Plan author.'),
|
|
136
|
+
identity('identity.plan-validator', { kind: 'projection', field: field('projection.corrective-replan.candidate', 'field.plan-validator-identity-hash') }, 'Independent Plan validator.'),
|
|
137
|
+
identity('identity.risk-auditor', { kind: 'projection', field: field('projection.corrective-replan.candidate', 'field.risk-auditor-identity-hash') }, 'Replacement Plan risk auditor.'),
|
|
138
|
+
identity('identity.workflow-core', { kind: 'workflow-core' }, 'Workflow Core audit identity.'),
|
|
139
|
+
];
|
|
140
|
+
|
|
141
|
+
const identityComparators: readonly IdentityComparatorRegistryEntry[] = [
|
|
142
|
+
comparator('identity-comparator.corrective-replan.author-validator', 'sod.plan-author-plan-validator-distinct', 'identity.plan-author', 'identity.plan-validator', 'distinct'),
|
|
143
|
+
comparator('identity-comparator.corrective-replan.author-risk-auditor', 'sod.plan-author-risk-auditor-distinct', 'identity.plan-author', 'identity.risk-auditor', 'distinct'),
|
|
144
|
+
comparator('identity-comparator.corrective-replan.author-human-principal', 'forbidden.plan-author-human-principal-self-authorize', 'identity.plan-author', 'identity.human-principal', 'cannot-authorize'),
|
|
145
|
+
];
|
|
146
|
+
|
|
147
|
+
const guardEvaluators: readonly GuardEvaluatorRegistryEntry[] = [
|
|
148
|
+
guardEvaluator('active-decision', [], 'Active corrective decision evaluator.'),
|
|
149
|
+
guardEvaluator('attempt-threshold', [], 'Corrective remediation threshold evaluator.'),
|
|
150
|
+
guardEvaluator('bindings-current', ['input.expected-revision', 'input.task-id'], 'Exact binding freshness evaluator.'),
|
|
151
|
+
guardEvaluator('guarded-step-retained', ['input.corrective-replacement-plan'], 'Candidate guarded Step retention evaluator.'),
|
|
152
|
+
guardEvaluator('no-step-in-progress', [], 'Running Step exclusion evaluator.'),
|
|
153
|
+
guardEvaluator('semantic-plan-change', ['input.corrective-replacement-plan'], 'Candidate Plan semantic change evaluator.'),
|
|
154
|
+
guardEvaluator('source-posture', [], 'Task and guarded Step source posture evaluator.'),
|
|
155
|
+
guardEvaluator('actor-role-eligible', ['input.corrective-execution-receipt'], 'Exact actor-role eligibility evaluator.'),
|
|
156
|
+
guardEvaluator('no-c1-claim', ['input.corrective-execution-receipt'], 'C1 claim absence under the Task operation lock.'),
|
|
157
|
+
guardEvaluator('no-writer-lease', ['input.corrective-execution-receipt'], 'Writer lease absence under the Task operation lock.'),
|
|
158
|
+
guardEvaluator('plan-validation-passed', ['input.corrective-plan-validation'], 'Exact Plan Validation attestation verifier.'),
|
|
159
|
+
guardEvaluator('receipt-valid', ['input.corrective-execution-receipt'], 'State-bound execution receipt verifier.'),
|
|
160
|
+
guardEvaluator('risk-audit-passed', ['input.corrective-plan-risk-audit'], 'Exact candidate-bound Risk Audit verifier.'),
|
|
161
|
+
];
|
|
162
|
+
|
|
163
|
+
const limitations: readonly LimitationRegistryEntry[] = [
|
|
164
|
+
limitation('limitation.release-profile.verified-evidence-external', 'accepted', 'Package release evidence is verified outside runtime static readiness.'),
|
|
165
|
+
];
|
|
166
|
+
|
|
167
|
+
const coverageProfiles: readonly CoverageProfileRegistryEntry[] = [{
|
|
168
|
+
id: exactTransitionCoverageProfileRef.id,
|
|
169
|
+
version: exactTransitionCoverageProfileRef.version,
|
|
170
|
+
description: 'Exact transition positive, hostile, replay, recovery, and postcondition evidence.',
|
|
171
|
+
requiredEvidenceKinds: [
|
|
172
|
+
'conditional-effect-false',
|
|
173
|
+
'conditional-effect-true',
|
|
174
|
+
'guard-negative',
|
|
175
|
+
'guard-positive',
|
|
176
|
+
'journal-phase',
|
|
177
|
+
'postcondition',
|
|
178
|
+
'recovery-phase',
|
|
179
|
+
'replay-conflicting',
|
|
180
|
+
'replay-identical-completed',
|
|
181
|
+
'replay-identical-in-progress',
|
|
182
|
+
],
|
|
183
|
+
}];
|
|
184
|
+
|
|
185
|
+
const readinessRuleIds = [
|
|
186
|
+
'readiness.atomicity.journal-required',
|
|
187
|
+
'readiness.atomicity.replay-incomplete',
|
|
188
|
+
'readiness.authority.actor-unbound',
|
|
189
|
+
'readiness.authority.exact-capability-missing',
|
|
190
|
+
'readiness.authority.state-bound-receipt-missing',
|
|
191
|
+
'readiness.catalog.coverage-profile-empty',
|
|
192
|
+
'readiness.catalog.coverage-report-invalid',
|
|
193
|
+
'readiness.catalog.coverage-report-missing',
|
|
194
|
+
'readiness.catalog.empty',
|
|
195
|
+
'readiness.definition.limitation-blocked',
|
|
196
|
+
'readiness.effect.narrow-lock-missing',
|
|
197
|
+
'readiness.effect.race-revalidation-incomplete',
|
|
198
|
+
'readiness.evidence.coverage-incomplete',
|
|
199
|
+
'readiness.guard.enforcement-incomplete',
|
|
200
|
+
'readiness.input.required-not-guarded',
|
|
201
|
+
'readiness.readback.postcondition-incomplete',
|
|
202
|
+
] as const;
|
|
203
|
+
|
|
204
|
+
const semanticRules: readonly SemanticRuleRegistryEntry[] = [
|
|
205
|
+
{ id: 'semantic-rule.definition-integrity', version: 1, description: 'Definition limitations and static integrity.', obligationIds: ['obligation.definition-integrity'] },
|
|
206
|
+
{ id: 'semantic-rule.exact-authority', version: 1, description: 'Exact actor, capability, credential, and SoD authority.', obligationIds: ['obligation.exact-authority'] },
|
|
207
|
+
{ id: 'semantic-rule.required-inputs', version: 1, description: 'Required exact mutation inputs and guard coverage.', obligationIds: ['obligation.required-inputs'] },
|
|
208
|
+
{ id: 'semantic-rule.admission-boundary', version: 1, description: 'Exclusive lock and under-lock race revalidation.', obligationIds: ['obligation.admission-boundary'] },
|
|
209
|
+
{ id: 'semantic-rule.reliable-effects', version: 1, description: 'Journal, replay, recovery, and readback completeness.', obligationIds: ['obligation.reliable-effects'] },
|
|
210
|
+
];
|
|
211
|
+
|
|
212
|
+
const releaseProfiles: readonly ReleaseProfileRegistryEntry[] = [{
|
|
213
|
+
id: exactMutationReleaseProfileRef.id,
|
|
214
|
+
version: exactMutationReleaseProfileRef.version,
|
|
215
|
+
description: 'Fail-closed exact mutating transition release profile.',
|
|
216
|
+
coverageProfile: exactTransitionCoverageProfileRef,
|
|
217
|
+
allowedLimitations: [v1('limitation.release-profile.verified-evidence-external')],
|
|
218
|
+
requiredRules: semanticRules.map(({ id, version }) => ({ id, version })),
|
|
219
|
+
requireExactAuthority: true,
|
|
220
|
+
requireExclusiveLockForMutation: true,
|
|
221
|
+
requireJournalForMultiWrite: true,
|
|
222
|
+
}];
|
|
223
|
+
|
|
224
|
+
export const transitionSemanticRegistry: SemanticRegistry = deepFreeze(validateSemanticRegistry({
|
|
225
|
+
inputs,
|
|
226
|
+
schemas,
|
|
227
|
+
projections,
|
|
228
|
+
hashPolicies: [
|
|
229
|
+
{ id: 'hash-policy.canonical-json-sha256', version: 1, description: 'Canonical JSON SHA-256.', algorithm: 'sha256', canonicalization: 'canonical-json' },
|
|
230
|
+
{ id: 'hash-policy.raw-sha256', version: 1, description: 'Raw byte SHA-256.', algorithm: 'sha256', canonicalization: 'raw-bytes' },
|
|
231
|
+
],
|
|
232
|
+
identities,
|
|
233
|
+
identityComparators,
|
|
234
|
+
principalBases: [
|
|
235
|
+
{ id: 'principal-basis.human-confirmation', version: 1, description: 'Exact Human confirmation authority basis.', principalKind: 'human', authoritySource: 'human-confirmation' },
|
|
236
|
+
],
|
|
237
|
+
capabilities: [{
|
|
238
|
+
id: 'capability.task.corrective-replan', version: 1, description: 'Human-issued capability for one exact replacement candidate.',
|
|
239
|
+
transitionId: 'task.plan.corrective-replan', issuer: v1('identity.human-principal'),
|
|
240
|
+
scope: v1('projection.corrective-replan.execution-receipt'), exactCandidateBound: true,
|
|
241
|
+
}],
|
|
242
|
+
credentialPolicies: [{
|
|
243
|
+
id: 'credential-policy.corrective-execution-receipt', version: 1, description: 'Exact state-bound Human-confirmed receipt.',
|
|
244
|
+
credentialKind: 'execution-receipt', schema: v1('schema.corrective-replan-receipt'),
|
|
245
|
+
verifier: v1('credential-verifier.corrective-replan.receipt'), issuer: v1('identity.human-principal'),
|
|
246
|
+
presentation: { mode: 'explicit-input', input: v1('input.corrective-execution-receipt') },
|
|
247
|
+
validity: { mode: 'bounded-ttl', clock: v1('clock.workflow-core-utc'), maxTtlMs: 900_000, skewMs: 30_000, expiryFailureCode: 'CREDENTIAL_EXPIRED' },
|
|
248
|
+
replay: { mode: 'execution-key-bound', executionKeyPolicy: v1('execution-key-policy.corrective-replan-exact') },
|
|
249
|
+
binding: { projection: v1('projection.corrective-replan.execution-receipt'), fieldIds: manifestFields },
|
|
250
|
+
}],
|
|
251
|
+
credentialVerifiers: [{ id: 'credential-verifier.corrective-replan.receipt', version: 1, description: 'The invoked Core credential kernel recomputes receipt and all current bindings.', verifierKind: 'state-bound-sha256' }],
|
|
252
|
+
clocks: [{ id: 'clock.workflow-core-utc', version: 1, description: 'Workflow Core injected UTC clock.', clockKind: 'workflow-core-utc' }],
|
|
253
|
+
delegationPolicies: [
|
|
254
|
+
{ id: 'delegation.forbidden', version: 1, description: 'Delegation is forbidden.', mode: 'forbidden', scopeBound: false, expiryRequired: false, redelegationAllowed: false },
|
|
255
|
+
],
|
|
256
|
+
ownershipPolicies: [
|
|
257
|
+
{ id: 'ownership.corrective-replan-clear', version: 1, description: 'No C1 claim or Writer lease may remain at replan admission.', c1Ownership: 'forbidden', writerLease: 'forbidden', ownerBinding: 'actor' },
|
|
258
|
+
],
|
|
259
|
+
guardEvaluators,
|
|
260
|
+
effectAdapters: [
|
|
261
|
+
{ id: 'effect-adapter.journaled-corrective-replan', version: 1, description: 'Receipt-bound five-target corrective-replan executor.', adapterKind: 'journaled-corrective-replan' },
|
|
262
|
+
],
|
|
263
|
+
resources: [
|
|
264
|
+
{ id: 'resource.plan-artifact', version: 1, description: 'Published Task Plan artifact.', resourceKind: 'artifact' },
|
|
265
|
+
{ id: 'resource.plan-validation-sidecar', version: 1, description: 'Plan Validation evidence sidecar.', resourceKind: 'sidecar' },
|
|
266
|
+
{ id: 'resource.plan-risk-audit-sidecar', version: 1, description: 'Plan Risk Audit sidecar.', resourceKind: 'sidecar' },
|
|
267
|
+
{ id: 'resource.corrective-replan-execution-sidecar', version: 1, description: 'Corrective-replan execution evidence sidecar.', resourceKind: 'sidecar' },
|
|
268
|
+
{ id: 'resource.corrective-replan-journal', version: 1, description: 'Retained Task corrective-replan journal.', resourceKind: 'journal' },
|
|
269
|
+
{ id: 'resource.task-state', version: 1, description: 'Task state.', resourceKind: 'task-state' },
|
|
270
|
+
],
|
|
271
|
+
lockPolicies: [
|
|
272
|
+
{ id: 'lock-policy.corrective-replan-task-exclusive', version: 1, description: 'Same-slot exclusive Task operation lock.', lockKind: 'exclusive-task', scope: slice('projection.corrective-replan.state', ['field.task-id']) },
|
|
273
|
+
],
|
|
274
|
+
executionKeyPolicies: [
|
|
275
|
+
{ id: 'execution-key-policy.corrective-replan-exact', version: 1, description: 'Exact AD-16 28-field execution key.', requiredFields: executionKeyFields },
|
|
276
|
+
],
|
|
277
|
+
journalSchemas: [{ id: 'journal-schema.corrective-replan-task', version: 1, description: 'Closed retained Task transaction journal.', schema: v1('schema.corrective-replan-task-transaction') }],
|
|
278
|
+
journalAdapters: [{ id: 'journal-adapter.corrective-replan-task', version: 1, description: 'Durable exact-target Task journal.', compatibleEffectAdapters: [v1('effect-adapter.journaled-corrective-replan')] }],
|
|
279
|
+
recoveryAdapters: [{ id: 'recovery-adapter.corrective-replan-roll-forward', version: 1, description: 'Explicit apply-or-confirm roll-forward.', compatibleJournalAdapters: [v1('journal-adapter.corrective-replan-task')] }],
|
|
280
|
+
readbackAdapters: [
|
|
281
|
+
{
|
|
282
|
+
id: 'readback-adapter.corrective-replan-terminal',
|
|
283
|
+
version: 1,
|
|
284
|
+
description: 'Domain readback before completion and retained-journal readback after terminal.',
|
|
285
|
+
compatibleEffectAdapters: [v1('effect-adapter.journaled-corrective-replan')],
|
|
286
|
+
wiring: 'invoked-post-effect',
|
|
287
|
+
implementationResult: 'projected-readback',
|
|
288
|
+
validationProjection: v1('projection.corrective-replan.terminal-readback'),
|
|
289
|
+
projectionWiring: 'invoked',
|
|
290
|
+
},
|
|
291
|
+
],
|
|
292
|
+
limitations,
|
|
293
|
+
releaseProfiles,
|
|
294
|
+
coverageProfiles,
|
|
295
|
+
coverageProducers: [],
|
|
296
|
+
semanticRules,
|
|
297
|
+
readinessRuleIds: [...readinessRuleIds],
|
|
298
|
+
}));
|
|
299
|
+
|
|
300
|
+
export function validateSemanticRegistry<TRegistry extends SemanticRegistry>(registry: TRegistry): TRegistry {
|
|
301
|
+
const categories: Array<readonly VersionedRegistryEntry<string>[]> = [
|
|
302
|
+
registry.inputs,
|
|
303
|
+
registry.schemas,
|
|
304
|
+
registry.projections,
|
|
305
|
+
registry.hashPolicies,
|
|
306
|
+
registry.identities,
|
|
307
|
+
registry.identityComparators,
|
|
308
|
+
registry.principalBases,
|
|
309
|
+
registry.capabilities,
|
|
310
|
+
registry.credentialPolicies,
|
|
311
|
+
registry.credentialVerifiers,
|
|
312
|
+
registry.clocks,
|
|
313
|
+
registry.delegationPolicies,
|
|
314
|
+
registry.ownershipPolicies,
|
|
315
|
+
registry.guardEvaluators,
|
|
316
|
+
registry.effectAdapters,
|
|
317
|
+
registry.resources,
|
|
318
|
+
registry.lockPolicies,
|
|
319
|
+
registry.executionKeyPolicies,
|
|
320
|
+
registry.journalSchemas,
|
|
321
|
+
registry.journalAdapters,
|
|
322
|
+
registry.recoveryAdapters,
|
|
323
|
+
registry.readbackAdapters,
|
|
324
|
+
registry.limitations,
|
|
325
|
+
registry.releaseProfiles,
|
|
326
|
+
registry.coverageProfiles,
|
|
327
|
+
registry.coverageProducers,
|
|
328
|
+
registry.semanticRules,
|
|
329
|
+
];
|
|
330
|
+
for (const entries of categories) assertUniqueRegisteredEntries(entries);
|
|
331
|
+
assertUniqueStrings(registry.readinessRuleIds, 'readiness rule IDs');
|
|
332
|
+
for (const projectionEntry of registry.projections) {
|
|
333
|
+
resolveRegistryEntry(registry.schemas, projectionEntry.schema, 'schema');
|
|
334
|
+
assertUniqueStrings(projectionEntry.fieldIds, `${projectionEntry.id} fields`);
|
|
335
|
+
}
|
|
336
|
+
for (const inputEntry of registry.inputs) {
|
|
337
|
+
resolveRegistryEntry(registry.schemas, inputEntry.schema, 'schema');
|
|
338
|
+
resolveRegistryEntry(registry.projections, inputEntry.projection, 'projection');
|
|
339
|
+
if (inputEntry.hashPolicy) resolveRegistryEntry(registry.hashPolicies, inputEntry.hashPolicy, 'hash policy');
|
|
340
|
+
}
|
|
341
|
+
for (const identityEntry of registry.identities) {
|
|
342
|
+
if (identityEntry.normalization) {
|
|
343
|
+
resolveRegistryEntry(registry.hashPolicies, identityEntry.normalization, 'hash policy');
|
|
344
|
+
}
|
|
345
|
+
if (identityEntry.provider.kind === 'projection') assertProjectionField(registry, identityEntry.provider.field);
|
|
346
|
+
}
|
|
347
|
+
for (const comparator of registry.identityComparators) {
|
|
348
|
+
if (comparator.operands.length < 2) throw new TypeError(`Identity comparator ${comparator.id} has fewer than two operands.`);
|
|
349
|
+
assertUniqueStrings(comparator.operands.map((operand) => `${operand.id}@${operand.version}`), `${comparator.id} operands`);
|
|
350
|
+
for (const operand of comparator.operands) resolveRegistryEntry(registry.identities, operand, 'identity comparator operand');
|
|
351
|
+
}
|
|
352
|
+
for (const capabilityEntry of registry.capabilities) {
|
|
353
|
+
resolveRegistryEntry(registry.identities, capabilityEntry.issuer, 'identity');
|
|
354
|
+
resolveRegistryEntry(registry.projections, capabilityEntry.scope, 'projection');
|
|
355
|
+
}
|
|
356
|
+
for (const credentialEntry of registry.credentialPolicies) validateCredentialPolicy(registry, credentialEntry);
|
|
357
|
+
for (const evaluator of registry.guardEvaluators) {
|
|
358
|
+
resolveRegistryEntry(registry.projections, evaluator.snapshot, 'projection');
|
|
359
|
+
resolveRegistryEntry(registry.projections, evaluator.binding, 'projection');
|
|
360
|
+
for (const inputRef of evaluator.allowedInputs) resolveRegistryEntry(registry.inputs, inputRef, 'input');
|
|
361
|
+
}
|
|
362
|
+
for (const profile of registry.coverageProfiles) {
|
|
363
|
+
if (profile.requiredEvidenceKinds.length === 0) throw new TypeError(`Coverage profile ${profile.id} is empty.`);
|
|
364
|
+
assertUniqueStrings(profile.requiredEvidenceKinds, `${profile.id} evidence kinds`);
|
|
365
|
+
}
|
|
366
|
+
for (const profile of registry.releaseProfiles) validateReleaseProfile(registry, profile);
|
|
367
|
+
for (const policy of registry.executionKeyPolicies) {
|
|
368
|
+
if (policy.requiredFields.length === 0) throw new TypeError(`Execution key policy ${policy.id} is empty.`);
|
|
369
|
+
assertUniqueStrings(policy.requiredFields.map(projectionFieldKey), `${policy.id} required fields`);
|
|
370
|
+
for (const requiredField of policy.requiredFields) assertProjectionField(registry, requiredField);
|
|
371
|
+
}
|
|
372
|
+
for (const policy of registry.lockPolicies) {
|
|
373
|
+
if (policy.lockKind === 'none' && policy.scope !== null) throw new TypeError(`Lock policy ${policy.id} cannot declare a scope.`);
|
|
374
|
+
if (policy.lockKind !== 'none' && policy.scope === null) throw new TypeError(`Lock policy ${policy.id} requires a scope.`);
|
|
375
|
+
if (policy.scope) assertProjectionSlice(registry, policy.scope);
|
|
376
|
+
}
|
|
377
|
+
for (const adapter of registry.readbackAdapters) {
|
|
378
|
+
resolveRegistryEntry(registry.projections, adapter.validationProjection, 'readback validation projection');
|
|
379
|
+
if (adapter.implementationResult === 'raw-task-state' && adapter.projectionWiring !== 'unimplemented') {
|
|
380
|
+
throw new TypeError(`Readback adapter ${adapter.id} cannot claim projected validation for a raw TaskState result.`);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
return registry;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
export function resolveRegistryEntry<TEntry extends VersionedRegistryEntry<string>>(
|
|
387
|
+
entries: readonly TEntry[],
|
|
388
|
+
ref: RegisteredRef<string>,
|
|
389
|
+
label: string,
|
|
390
|
+
): TEntry {
|
|
391
|
+
const match = entries.find((entry) => entry.id === ref.id && entry.version === ref.version);
|
|
392
|
+
if (!match) throw new TypeError(`Unknown registered ${label} ${ref.id}@${ref.version}.`);
|
|
393
|
+
return match;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
function validateCredentialPolicy(registry: SemanticRegistry, policy: CredentialPolicyRegistryEntry): void {
|
|
397
|
+
resolveRegistryEntry(registry.schemas, policy.schema, 'credential schema');
|
|
398
|
+
resolveRegistryEntry(registry.credentialVerifiers, policy.verifier, 'credential verifier');
|
|
399
|
+
resolveRegistryEntry(registry.identities, policy.issuer, 'credential issuer');
|
|
400
|
+
assertProjectionSlice(registry, policy.binding);
|
|
401
|
+
if (policy.presentation.mode === 'explicit-input') resolveRegistryEntry(registry.inputs, policy.presentation.input, 'credential input');
|
|
402
|
+
if (policy.validity.mode === 'bounded-ttl') {
|
|
403
|
+
resolveRegistryEntry(registry.clocks, policy.validity.clock, 'clock');
|
|
404
|
+
if (!Number.isInteger(policy.validity.maxTtlMs) || policy.validity.maxTtlMs <= 0) {
|
|
405
|
+
throw new TypeError(`Credential policy ${policy.id} has invalid maxTtlMs.`);
|
|
406
|
+
}
|
|
407
|
+
if (!Number.isInteger(policy.validity.skewMs) || policy.validity.skewMs < 0) {
|
|
408
|
+
throw new TypeError(`Credential policy ${policy.id} has invalid skewMs.`);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
if (policy.replay.mode === 'execution-key-bound') {
|
|
412
|
+
resolveRegistryEntry(registry.executionKeyPolicies, policy.replay.executionKeyPolicy, 'execution key policy');
|
|
413
|
+
}
|
|
414
|
+
if (policy.id === 'credential-policy.corrective-execution-receipt' && policy.version === 1) {
|
|
415
|
+
const exactProjection = resolveRegistryEntry(
|
|
416
|
+
registry.projections,
|
|
417
|
+
v1('projection.corrective-replan.execution-receipt'),
|
|
418
|
+
'exact corrective receipt projection',
|
|
419
|
+
);
|
|
420
|
+
if (policy.binding.projection.id !== exactProjection.id
|
|
421
|
+
|| policy.binding.projection.version !== exactProjection.version
|
|
422
|
+
|| policy.binding.fieldIds.length !== exactProjection.fieldIds.length
|
|
423
|
+
|| exactProjection.fieldIds.some((fieldId) => !policy.binding.fieldIds.includes(fieldId))) {
|
|
424
|
+
throw new TypeError('Exact corrective receipt policy must bind every registered receipt field exactly once.');
|
|
425
|
+
}
|
|
426
|
+
if (policy.presentation.mode !== 'explicit-input'
|
|
427
|
+
|| policy.presentation.input.id !== 'input.corrective-execution-receipt'
|
|
428
|
+
|| policy.validity.mode !== 'bounded-ttl'
|
|
429
|
+
|| policy.replay.mode !== 'execution-key-bound'
|
|
430
|
+
|| policy.verifier.id !== 'credential-verifier.corrective-replan.receipt') {
|
|
431
|
+
throw new TypeError('Exact corrective receipt policy has incomplete presentation, TTL, replay, or verifier semantics.');
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
function validateReleaseProfile(registry: SemanticRegistry, profile: ReleaseProfileRegistryEntry): void {
|
|
437
|
+
resolveRegistryEntry(registry.coverageProfiles, profile.coverageProfile, 'coverage profile');
|
|
438
|
+
assertUniqueStrings(profile.requiredRules.map((rule) => `${rule.id}@${rule.version}`), `${profile.id} semantic rules`);
|
|
439
|
+
for (const ruleRef of profile.requiredRules) {
|
|
440
|
+
resolveRegistryEntry(registry.semanticRules, ruleRef, 'semantic rule');
|
|
441
|
+
}
|
|
442
|
+
for (const limitationRef of profile.allowedLimitations) {
|
|
443
|
+
const limitationEntry = resolveRegistryEntry(registry.limitations, limitationRef, 'limitation');
|
|
444
|
+
if (limitationEntry.disposition !== 'accepted') {
|
|
445
|
+
throw new TypeError(`Release profile ${profile.id} cannot allow unresolved limitation ${limitationRef.id}@${limitationRef.version}.`);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
function assertProjectionField(registry: SemanticRegistry, field: { projection: RegisteredRef<string>; fieldId: ProjectionFieldId }): void {
|
|
451
|
+
const projectionEntry = resolveRegistryEntry(registry.projections, field.projection, 'projection');
|
|
452
|
+
if (!projectionEntry.fieldIds.includes(field.fieldId)) {
|
|
453
|
+
throw new TypeError(`Projection ${field.projection.id}@${field.projection.version} has no field ${field.fieldId}.`);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
function assertProjectionSlice(registry: SemanticRegistry, slice: { projection: RegisteredRef<string>; fieldIds: readonly ProjectionFieldId[] }): void {
|
|
458
|
+
const projectionEntry = resolveRegistryEntry(registry.projections, slice.projection, 'projection');
|
|
459
|
+
assertUniqueStrings(slice.fieldIds, `${slice.projection.id} slice fields`);
|
|
460
|
+
for (const fieldId of slice.fieldIds) {
|
|
461
|
+
if (!projectionEntry.fieldIds.includes(fieldId)) throw new TypeError(`Projection ${slice.projection.id} has no field ${fieldId}.`);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
function assertUniqueRegisteredEntries(entries: readonly VersionedRegistryEntry<string>[]): void {
|
|
466
|
+
assertUniqueStrings(entries.map((entry) => `${entry.id}@${entry.version}`), 'registered ID/version pairs');
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
function assertUniqueStrings(values: readonly string[], label: string): void {
|
|
470
|
+
if (new Set(values).size !== values.length) throw new TypeError(`Duplicate ${label}.`);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
function schema(id: SchemaRegistryEntryId, valueKind: 'string' | 'integer' | 'object' | 'array', description: string) {
|
|
474
|
+
return { id, version: 1, description, valueKind } as const;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
type SchemaRegistryEntryId = `schema.${string}`;
|
|
478
|
+
|
|
479
|
+
function projection(
|
|
480
|
+
id: `projection.${string}`,
|
|
481
|
+
schemaId: `schema.${string}`,
|
|
482
|
+
fieldIds: readonly ProjectionFieldId[],
|
|
483
|
+
description: string,
|
|
484
|
+
): ProjectionRegistryEntry {
|
|
485
|
+
return { id, version: 1, description, schema: v1(schemaId), fieldIds };
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
function input(
|
|
489
|
+
id: `input.${string}`,
|
|
490
|
+
source: InputRegistryEntry['source'],
|
|
491
|
+
cliName: string,
|
|
492
|
+
schemaId: `schema.${string}`,
|
|
493
|
+
projectionId: `projection.${string}`,
|
|
494
|
+
hashPolicyId: `hash-policy.${string}` | null,
|
|
495
|
+
description: string,
|
|
496
|
+
): InputRegistryEntry {
|
|
497
|
+
return {
|
|
498
|
+
id,
|
|
499
|
+
version: 1,
|
|
500
|
+
description,
|
|
501
|
+
source,
|
|
502
|
+
cliName,
|
|
503
|
+
schema: v1(schemaId),
|
|
504
|
+
projection: v1(projectionId),
|
|
505
|
+
hashPolicy: hashPolicyId ? v1(hashPolicyId) : null,
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
function identity(
|
|
510
|
+
id: `identity.${string}`,
|
|
511
|
+
provider: IdentityRegistryEntry['provider'],
|
|
512
|
+
description: string,
|
|
513
|
+
): IdentityRegistryEntry {
|
|
514
|
+
return { id, version: 1, description, provider, normalization: null };
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
function comparator(
|
|
518
|
+
id: `identity-comparator.${string}`,
|
|
519
|
+
constraintId: `sod.${string}` | `forbidden.${string}`,
|
|
520
|
+
left: `identity.${string}`,
|
|
521
|
+
right: `identity.${string}`,
|
|
522
|
+
relation: IdentityComparatorRegistryEntry['relation'],
|
|
523
|
+
): IdentityComparatorRegistryEntry {
|
|
524
|
+
return {
|
|
525
|
+
id, version: 1, description: `Exact ${constraintId} identity comparison.`,
|
|
526
|
+
transitionId: 'task.plan.corrective-replan', constraintId,
|
|
527
|
+
operands: [v1(left), v1(right)], relation, missingIdentity: 'block',
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
function guardEvaluator(
|
|
532
|
+
suffix: string,
|
|
533
|
+
allowedInputIds: readonly `input.${string}`[],
|
|
534
|
+
description: string,
|
|
535
|
+
): GuardEvaluatorRegistryEntry {
|
|
536
|
+
return {
|
|
537
|
+
id: `guard-evaluator.task.corrective-replan.${suffix}`,
|
|
538
|
+
version: 1,
|
|
539
|
+
description,
|
|
540
|
+
transitionId: 'task.plan.corrective-replan',
|
|
541
|
+
guardId: `task.corrective-replan.${suffix}`,
|
|
542
|
+
snapshot: correctiveSnapshotRef,
|
|
543
|
+
binding: correctiveBindingRef,
|
|
544
|
+
allowedInputs: allowedInputIds.map(v1),
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
function limitation(
|
|
549
|
+
id: `limitation.${string}`,
|
|
550
|
+
disposition: LimitationRegistryEntry['disposition'],
|
|
551
|
+
description: string,
|
|
552
|
+
): LimitationRegistryEntry {
|
|
553
|
+
return { id, version: 1, description, disposition };
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
function field<TProjection extends `projection.${string}`>(
|
|
557
|
+
projectionId: TProjection,
|
|
558
|
+
fieldId: ProjectionFieldId,
|
|
559
|
+
): ProjectionFieldRef {
|
|
560
|
+
return { projection: v1(projectionId), fieldId };
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
function slice<TProjection extends `projection.${string}`>(
|
|
564
|
+
projectionId: TProjection,
|
|
565
|
+
fieldIds: readonly ProjectionFieldId[],
|
|
566
|
+
) {
|
|
567
|
+
return { projection: v1(projectionId), fieldIds };
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
function projectionFieldKey(value: ProjectionFieldRef): string {
|
|
571
|
+
return `${value.projection.id}@${value.projection.version}:${value.fieldId}`;
|
|
572
|
+
}
|