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,48 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ExecutableTransitionDefinition,
|
|
3
|
+
TransitionEvaluation,
|
|
4
|
+
TransitionEvaluationPhase,
|
|
5
|
+
TransitionGuardResult,
|
|
6
|
+
} from './types.js';
|
|
7
|
+
|
|
8
|
+
export function evaluateTransition<TSnapshot, TBindings>(
|
|
9
|
+
definition: ExecutableTransitionDefinition<TSnapshot, TBindings>,
|
|
10
|
+
snapshot: Readonly<TSnapshot>,
|
|
11
|
+
bindings: Readonly<TBindings>,
|
|
12
|
+
phase: TransitionEvaluationPhase,
|
|
13
|
+
): TransitionEvaluation<TBindings> {
|
|
14
|
+
const guardResults: TransitionGuardResult[] = definition.guards.map((guard) => {
|
|
15
|
+
if (guard.metadata.phase === 'execution' && phase === 'availability') {
|
|
16
|
+
return {
|
|
17
|
+
guardId: guard.metadata.guardId,
|
|
18
|
+
status: 'pending',
|
|
19
|
+
passed: false,
|
|
20
|
+
reasonCode: 'PENDING_OPERATOR_INPUT',
|
|
21
|
+
message: 'Guard requires operator input and will be evaluated before effects.',
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
const result = guard.evaluate(snapshot, bindings);
|
|
25
|
+
if (result.guardId !== guard.metadata.guardId) {
|
|
26
|
+
throw new TypeError(
|
|
27
|
+
`Guard ${guard.metadata.guardId} returned result for ${result.guardId}.`,
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
return result;
|
|
31
|
+
});
|
|
32
|
+
const blockingGuardIds = guardResults
|
|
33
|
+
.filter((result) => result.status === 'failed')
|
|
34
|
+
.map((result) => result.guardId);
|
|
35
|
+
const pendingGuardIds = guardResults
|
|
36
|
+
.filter((result) => result.status === 'pending')
|
|
37
|
+
.map((result) => result.guardId);
|
|
38
|
+
return {
|
|
39
|
+
transitionId: definition.metadata.transitionId,
|
|
40
|
+
semanticFingerprint: definition.semanticFingerprint,
|
|
41
|
+
phase,
|
|
42
|
+
allowed: blockingGuardIds.length === 0,
|
|
43
|
+
bindings,
|
|
44
|
+
guardResults,
|
|
45
|
+
blockingGuardIds,
|
|
46
|
+
pendingGuardIds,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
import { transitionSemanticRegistry } from './semantic-registry.js';
|
|
2
|
+
import { hashCanonical } from './canonical-hash.js';
|
|
3
|
+
export { hashCanonical } from './canonical-hash.js';
|
|
4
|
+
export type { CanonicalJsonValue } from './canonical-hash.js';
|
|
5
|
+
import { coreReleaseRuleDescriptors, correctiveReplanExecutableSemanticIdentity } from './implementation-table.js';
|
|
6
|
+
import {
|
|
7
|
+
LIFECYCLE_EPOCH,
|
|
8
|
+
TRANSITION_CATALOG_FORMAT_VERSION,
|
|
9
|
+
type EffectCondition,
|
|
10
|
+
type ProjectionFieldRef,
|
|
11
|
+
type ProjectionSliceRef,
|
|
12
|
+
type RegisteredRef,
|
|
13
|
+
type RegisteredRacePrecondition,
|
|
14
|
+
type SemanticRegistry,
|
|
15
|
+
type SerializedTransitionDefinition,
|
|
16
|
+
type TransitionDefinitionMetadata,
|
|
17
|
+
type TransitionEffectNode,
|
|
18
|
+
type TransitionGuardMetadata,
|
|
19
|
+
type TransitionId,
|
|
20
|
+
type TransitionJournalPhase,
|
|
21
|
+
type TransitionPostcondition,
|
|
22
|
+
type TransitionRevalidation,
|
|
23
|
+
type VersionedRegistryEntry,
|
|
24
|
+
} from './types.js';
|
|
25
|
+
|
|
26
|
+
type RuntimeRegistryCategory = Exclude<keyof SemanticRegistry,
|
|
27
|
+
'coverageProducers' | 'coverageProfiles' | 'limitations' | 'readinessRuleIds' | 'releaseProfiles' | 'semanticRules'>;
|
|
28
|
+
type ReadinessRegistryCategory = 'coverageProducers' | 'coverageProfiles' | 'limitations' | 'releaseProfiles' | 'semanticRules';
|
|
29
|
+
|
|
30
|
+
export interface RuntimeSemanticProjection {
|
|
31
|
+
readonly semantics: unknown;
|
|
32
|
+
readonly resolvedRegistryEntries: readonly unknown[];
|
|
33
|
+
readonly executableSemantics: unknown;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface DefinitionManifestProjection {
|
|
37
|
+
readonly runtimeSemanticFingerprint: string;
|
|
38
|
+
readonly readinessManifest: unknown;
|
|
39
|
+
readonly traceability: unknown;
|
|
40
|
+
readonly resolvedReadinessRegistryEntries: readonly unknown[];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function runtimeSemanticProjection(
|
|
44
|
+
metadata: TransitionDefinitionMetadata,
|
|
45
|
+
): RuntimeSemanticProjection {
|
|
46
|
+
if (arguments.length !== 1) throw new TypeError('Custom semantic registries are not accepted by installed identity helpers.');
|
|
47
|
+
resolveRegistryClosure(metadata.readinessManifest, readinessRegistryCategories(transitionSemanticRegistry));
|
|
48
|
+
const {
|
|
49
|
+
readinessManifest: _readinessManifest,
|
|
50
|
+
traceability: _traceability,
|
|
51
|
+
documentation: _documentation,
|
|
52
|
+
...runtimeMetadata
|
|
53
|
+
} = metadata;
|
|
54
|
+
const semantics = normalizeRuntimeMetadata(runtimeMetadata as Omit<
|
|
55
|
+
TransitionDefinitionMetadata,
|
|
56
|
+
'documentation' | 'readinessManifest' | 'traceability'
|
|
57
|
+
>);
|
|
58
|
+
return {
|
|
59
|
+
semantics,
|
|
60
|
+
resolvedRegistryEntries: resolveRegistryClosure(semantics, runtimeRegistryCategories(transitionSemanticRegistry)),
|
|
61
|
+
executableSemantics: defaultExecutableSemantics(),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** @deprecated Use runtimeSemanticProjection. */
|
|
66
|
+
export const semanticTransitionProjection = runtimeSemanticProjection;
|
|
67
|
+
|
|
68
|
+
export function runtimeSemanticFingerprint(
|
|
69
|
+
metadata: TransitionDefinitionMetadata,
|
|
70
|
+
): string {
|
|
71
|
+
if (arguments.length !== 1) throw new TypeError('Custom semantic registries are not accepted by installed identity helpers.');
|
|
72
|
+
return hashCanonical(runtimeSemanticProjection(metadata));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** @deprecated Protocol-v1 compatibility name. */
|
|
76
|
+
export const semanticTransitionFingerprint = runtimeSemanticFingerprint;
|
|
77
|
+
|
|
78
|
+
export function definitionManifestProjection(
|
|
79
|
+
metadata: TransitionDefinitionMetadata,
|
|
80
|
+
semanticFingerprint: string,
|
|
81
|
+
): DefinitionManifestProjection {
|
|
82
|
+
if (arguments.length !== 2) throw new TypeError('Installed manifest projection accepts metadata and its runtime fingerprint only.');
|
|
83
|
+
const readinessManifest = {
|
|
84
|
+
...metadata.readinessManifest,
|
|
85
|
+
limitations: sortRefs(metadata.readinessManifest.limitations),
|
|
86
|
+
evidence: [...metadata.readinessManifest.evidence]
|
|
87
|
+
.sort((left, right) => left.evidenceId.localeCompare(right.evidenceId)),
|
|
88
|
+
};
|
|
89
|
+
const traceability = {
|
|
90
|
+
defectIds: sortedStrings(metadata.traceability.defectIds),
|
|
91
|
+
invariantIds: sortedStrings(metadata.traceability.invariantIds),
|
|
92
|
+
positiveEvidence: sortedStrings(metadata.traceability.positiveEvidence),
|
|
93
|
+
hostileEvidence: sortedStrings(metadata.traceability.hostileEvidence),
|
|
94
|
+
};
|
|
95
|
+
return {
|
|
96
|
+
runtimeSemanticFingerprint: semanticFingerprint,
|
|
97
|
+
readinessManifest,
|
|
98
|
+
traceability,
|
|
99
|
+
resolvedReadinessRegistryEntries: resolveRegistryClosure(
|
|
100
|
+
readinessManifest,
|
|
101
|
+
readinessRegistryCategories(transitionSemanticRegistry),
|
|
102
|
+
),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function transitionDefinitionManifestHash(
|
|
107
|
+
metadata: TransitionDefinitionMetadata,
|
|
108
|
+
semanticFingerprint = runtimeSemanticFingerprint(metadata),
|
|
109
|
+
): string {
|
|
110
|
+
if (arguments.length > 2) throw new TypeError('Custom semantic registries are not accepted by installed identity helpers.');
|
|
111
|
+
return hashCanonical(definitionManifestProjection(metadata, semanticFingerprint));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export const definitionManifestHash = transitionDefinitionManifestHash;
|
|
115
|
+
|
|
116
|
+
export interface CatalogRuntimeHashEntry {
|
|
117
|
+
readonly transitionId: TransitionId;
|
|
118
|
+
readonly runtimeSemanticFingerprint: string;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function runtimeCatalogHash(
|
|
122
|
+
definitions: readonly Pick<SerializedTransitionDefinition, 'runtimeSemanticFingerprint' | 'transitionId'>[],
|
|
123
|
+
): string {
|
|
124
|
+
const transitions: CatalogRuntimeHashEntry[] = definitions
|
|
125
|
+
.map((definition) => ({
|
|
126
|
+
transitionId: definition.transitionId,
|
|
127
|
+
runtimeSemanticFingerprint: definition.runtimeSemanticFingerprint,
|
|
128
|
+
}))
|
|
129
|
+
.sort((left, right) => left.transitionId.localeCompare(right.transitionId));
|
|
130
|
+
return hashCanonical({
|
|
131
|
+
catalogFormatVersion: TRANSITION_CATALOG_FORMAT_VERSION,
|
|
132
|
+
lifecycleEpoch: LIFECYCLE_EPOCH,
|
|
133
|
+
transitions,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** @deprecated Use runtimeCatalogHash. */
|
|
138
|
+
export const semanticCatalogHash = runtimeCatalogHash;
|
|
139
|
+
|
|
140
|
+
export function catalogDefinitionManifestHash(
|
|
141
|
+
definitions: readonly Pick<SerializedTransitionDefinition, 'definitionManifestHash' | 'transitionId'>[],
|
|
142
|
+
): string {
|
|
143
|
+
return hashCanonical({
|
|
144
|
+
catalogFormatVersion: TRANSITION_CATALOG_FORMAT_VERSION,
|
|
145
|
+
definitions: definitions
|
|
146
|
+
.map((definition) => ({
|
|
147
|
+
transitionId: definition.transitionId,
|
|
148
|
+
definitionManifestHash: definition.definitionManifestHash,
|
|
149
|
+
}))
|
|
150
|
+
.sort((left, right) => left.transitionId.localeCompare(right.transitionId)),
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function normalizeRuntimeMetadata(
|
|
155
|
+
metadata: Omit<TransitionDefinitionMetadata, 'documentation' | 'readinessManifest' | 'traceability'>,
|
|
156
|
+
): unknown {
|
|
157
|
+
return {
|
|
158
|
+
...metadata,
|
|
159
|
+
sourcePosture: {
|
|
160
|
+
taskStatuses: sortedStrings(metadata.sourcePosture.taskStatuses),
|
|
161
|
+
milestoneStatuses: sortedStrings(metadata.sourcePosture.milestoneStatuses),
|
|
162
|
+
stepStatuses: sortedStrings(metadata.sourcePosture.stepStatuses),
|
|
163
|
+
correctivePostures: sortedStrings(metadata.sourcePosture.correctivePostures),
|
|
164
|
+
},
|
|
165
|
+
inputContract: [...metadata.inputContract]
|
|
166
|
+
.map((input) => ({ ...input }))
|
|
167
|
+
.sort((left, right) => refKey(left.input).localeCompare(refKey(right.input))),
|
|
168
|
+
outputContract: [...metadata.outputContract]
|
|
169
|
+
.map((output) => ({ ...output }))
|
|
170
|
+
.sort((left, right) => left.outputId.localeCompare(right.outputId)),
|
|
171
|
+
guards: metadata.guards.map(normalizeGuard),
|
|
172
|
+
authority: {
|
|
173
|
+
...metadata.authority,
|
|
174
|
+
eligibleRoles: sortedStrings(metadata.authority.eligibleRoles),
|
|
175
|
+
principal: {
|
|
176
|
+
...metadata.authority.principal,
|
|
177
|
+
allowedKinds: sortedStrings(metadata.authority.principal.allowedKinds),
|
|
178
|
+
},
|
|
179
|
+
capabilities: [...metadata.authority.capabilities]
|
|
180
|
+
.sort((left, right) => refKey(left.capability).localeCompare(refKey(right.capability))),
|
|
181
|
+
credentials: sortRefs(metadata.authority.credentials),
|
|
182
|
+
executionBoundaries: sortedStrings(metadata.authority.executionBoundaries),
|
|
183
|
+
separationOfDuty: [...metadata.authority.separationOfDuty]
|
|
184
|
+
.sort((left, right) => left.constraintId.localeCompare(right.constraintId)),
|
|
185
|
+
forbiddenCombinations: [...metadata.authority.forbiddenCombinations]
|
|
186
|
+
.map((constraint) => ({ ...constraint, subjects: sortRefs(constraint.subjects) }))
|
|
187
|
+
.sort((left, right) => left.constraintId.localeCompare(right.constraintId)),
|
|
188
|
+
},
|
|
189
|
+
effects: {
|
|
190
|
+
...metadata.effects,
|
|
191
|
+
taskStatus: { ...metadata.effects.taskStatus, from: sortedStrings(metadata.effects.taskStatus.from) },
|
|
192
|
+
milestoneStatus: { ...metadata.effects.milestoneStatus, from: sortedStrings(metadata.effects.milestoneStatus.from) },
|
|
193
|
+
stepStatus: { ...metadata.effects.stepStatus, from: sortedStrings(metadata.effects.stepStatus.from) },
|
|
194
|
+
orderedNodes: metadata.effects.orderedNodes.map(normalizeEffectNode),
|
|
195
|
+
postconditions: [...metadata.effects.postconditions]
|
|
196
|
+
.map(normalizePostcondition)
|
|
197
|
+
.sort((left, right) => left.postconditionId.localeCompare(right.postconditionId)),
|
|
198
|
+
},
|
|
199
|
+
admissionBoundary: {
|
|
200
|
+
...metadata.admissionBoundary,
|
|
201
|
+
lock: {
|
|
202
|
+
...metadata.admissionBoundary.lock,
|
|
203
|
+
scope: normalizeProjectionSlice(metadata.admissionBoundary.lock.scope),
|
|
204
|
+
},
|
|
205
|
+
orderedRevalidations: metadata.admissionBoundary.orderedRevalidations.map(normalizeRevalidation),
|
|
206
|
+
},
|
|
207
|
+
atomicity: {
|
|
208
|
+
...metadata.atomicity,
|
|
209
|
+
executionKey: {
|
|
210
|
+
...metadata.atomicity.executionKey,
|
|
211
|
+
fields: sortProjectionFields(metadata.atomicity.executionKey.fields),
|
|
212
|
+
},
|
|
213
|
+
journal: metadata.atomicity.journal.mode === 'none'
|
|
214
|
+
? metadata.atomicity.journal
|
|
215
|
+
: {
|
|
216
|
+
...metadata.atomicity.journal,
|
|
217
|
+
orderedPhases: metadata.atomicity.journal.orderedPhases.map(normalizeJournalPhase),
|
|
218
|
+
},
|
|
219
|
+
recovery: metadata.atomicity.recovery.mode === 'manual-integrity-stop'
|
|
220
|
+
? {
|
|
221
|
+
...metadata.atomicity.recovery,
|
|
222
|
+
fromPhaseIds: sortedStrings(metadata.atomicity.recovery.fromPhaseIds),
|
|
223
|
+
}
|
|
224
|
+
: {
|
|
225
|
+
...metadata.atomicity.recovery,
|
|
226
|
+
fromPhaseIds: sortedStrings(metadata.atomicity.recovery.fromPhaseIds),
|
|
227
|
+
orderedSteps: metadata.atomicity.recovery.orderedSteps.map((step) => ({ ...step })),
|
|
228
|
+
},
|
|
229
|
+
readback: {
|
|
230
|
+
...metadata.atomicity.readback,
|
|
231
|
+
postconditionIds: sortedStrings(metadata.atomicity.readback.postconditionIds),
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
racePreconditions: [...metadata.racePreconditions]
|
|
235
|
+
.map(normalizeRace)
|
|
236
|
+
.sort((left, right) => left.raceId.localeCompare(right.raceId)),
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function normalizeGuard(guard: TransitionGuardMetadata): unknown {
|
|
241
|
+
return {
|
|
242
|
+
...guard,
|
|
243
|
+
reads: sortProjectionSlices(guard.reads),
|
|
244
|
+
requiredInputs: sortRefs(guard.requiredInputs),
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function normalizeEffectNode(node: TransitionEffectNode): unknown {
|
|
249
|
+
return {
|
|
250
|
+
...node,
|
|
251
|
+
conditions: [...node.conditions].sort((left, right) => conditionKey(left).localeCompare(conditionKey(right))),
|
|
252
|
+
dependsOn: sortedStrings(node.dependsOn),
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function normalizePostcondition(postcondition: TransitionPostcondition): TransitionPostcondition {
|
|
257
|
+
return {
|
|
258
|
+
...postcondition,
|
|
259
|
+
reads: sortProjectionSlices(postcondition.reads),
|
|
260
|
+
effectNodeIds: sortedStrings(postcondition.effectNodeIds),
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function normalizeRevalidation(revalidation: TransitionRevalidation): unknown {
|
|
265
|
+
return { ...revalidation, reads: sortProjectionSlices(revalidation.reads) };
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function normalizeRace(race: RegisteredRacePrecondition): RegisteredRacePrecondition {
|
|
269
|
+
return {
|
|
270
|
+
...race,
|
|
271
|
+
reads: sortProjectionSlices(race.reads),
|
|
272
|
+
allowedFailureCodes: sortedStrings(race.allowedFailureCodes),
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function normalizeJournalPhase(phase: TransitionJournalPhase): unknown {
|
|
277
|
+
return {
|
|
278
|
+
...phase,
|
|
279
|
+
allowedNextPhaseIds: sortedStrings(phase.allowedNextPhaseIds),
|
|
280
|
+
effectNodeIds: sortedStrings(phase.effectNodeIds),
|
|
281
|
+
digestFields: sortProjectionFields(phase.digestFields),
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function sortProjectionSlices(slices: readonly ProjectionSliceRef[]): ProjectionSliceRef[] {
|
|
286
|
+
const grouped = new Map<string, { projection: ProjectionSliceRef['projection']; fieldIds: Set<ProjectionSliceRef['fieldIds'][number]> }>();
|
|
287
|
+
for (const slice of slices) {
|
|
288
|
+
const key = refKey(slice.projection);
|
|
289
|
+
const current = grouped.get(key) ?? { projection: slice.projection, fieldIds: new Set() };
|
|
290
|
+
slice.fieldIds.forEach((fieldId) => current.fieldIds.add(fieldId));
|
|
291
|
+
grouped.set(key, current);
|
|
292
|
+
}
|
|
293
|
+
return [...grouped.values()]
|
|
294
|
+
.map((entry) => ({ projection: entry.projection, fieldIds: sortedStrings([...entry.fieldIds]) }))
|
|
295
|
+
.sort((left, right) => refKey(left.projection).localeCompare(refKey(right.projection)));
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function normalizeProjectionSlice(slice: ProjectionSliceRef): ProjectionSliceRef {
|
|
299
|
+
return { ...slice, fieldIds: sortedStrings(slice.fieldIds) };
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function sortProjectionFields(fields: readonly ProjectionFieldRef[]): ProjectionFieldRef[] {
|
|
303
|
+
return [...fields].sort((left, right) =>
|
|
304
|
+
`${refKey(left.projection)}\0${left.fieldId}`.localeCompare(`${refKey(right.projection)}\0${right.fieldId}`));
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function sortRefs<TRef extends RegisteredRef<string>>(refs: readonly TRef[]): TRef[] {
|
|
308
|
+
return [...refs].sort((left, right) => refKey(left).localeCompare(refKey(right)));
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function sortedStrings<TValue extends string>(values: readonly TValue[]): TValue[] {
|
|
312
|
+
return [...values].sort((left, right) => left.localeCompare(right));
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
function conditionKey(condition: EffectCondition): string {
|
|
316
|
+
return condition.kind === 'input-present'
|
|
317
|
+
? `input-present\0${refKey(condition.input)}`
|
|
318
|
+
: `guard-passed\0${condition.guardId}`;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function refKey(ref: RegisteredRef<string>): string {
|
|
322
|
+
return `${ref.id}@${ref.version}`;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
interface CategorizedRegistryEntry {
|
|
326
|
+
readonly category: string;
|
|
327
|
+
readonly entry: VersionedRegistryEntry<string>;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function runtimeRegistryCategories(registry: SemanticRegistry): CategorizedRegistryEntry[] {
|
|
331
|
+
const categoryNames: readonly RuntimeRegistryCategory[] = [
|
|
332
|
+
'inputs',
|
|
333
|
+
'schemas',
|
|
334
|
+
'projections',
|
|
335
|
+
'hashPolicies',
|
|
336
|
+
'identities',
|
|
337
|
+
'identityComparators',
|
|
338
|
+
'principalBases',
|
|
339
|
+
'capabilities',
|
|
340
|
+
'credentialPolicies',
|
|
341
|
+
'credentialVerifiers',
|
|
342
|
+
'clocks',
|
|
343
|
+
'delegationPolicies',
|
|
344
|
+
'ownershipPolicies',
|
|
345
|
+
'guardEvaluators',
|
|
346
|
+
'effectAdapters',
|
|
347
|
+
'resources',
|
|
348
|
+
'lockPolicies',
|
|
349
|
+
'executionKeyPolicies',
|
|
350
|
+
'journalSchemas',
|
|
351
|
+
'journalAdapters',
|
|
352
|
+
'recoveryAdapters',
|
|
353
|
+
'readbackAdapters',
|
|
354
|
+
];
|
|
355
|
+
return categoryNames.flatMap((category) => registry[category].map((entry) => ({ category, entry })));
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
function readinessRegistryCategories(registry: SemanticRegistry): CategorizedRegistryEntry[] {
|
|
359
|
+
const categoryNames: readonly ReadinessRegistryCategory[] = [
|
|
360
|
+
'coverageProducers',
|
|
361
|
+
'coverageProfiles',
|
|
362
|
+
'limitations',
|
|
363
|
+
'releaseProfiles',
|
|
364
|
+
'semanticRules',
|
|
365
|
+
];
|
|
366
|
+
return categoryNames.flatMap((category) => registry[category].map((entry) => ({ category, entry })));
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function resolveRegistryClosure(root: unknown, entries: readonly CategorizedRegistryEntry[]): unknown[] {
|
|
370
|
+
const resolved = new Map<string, CategorizedRegistryEntry>();
|
|
371
|
+
const pending = findRegisteredRefs(root);
|
|
372
|
+
while (pending.length > 0) {
|
|
373
|
+
const ref = pending.pop()!;
|
|
374
|
+
const key = refKey(ref);
|
|
375
|
+
if (resolved.has(key)) continue;
|
|
376
|
+
const matches = entries.filter((entry) => refKey(entry.entry) === key);
|
|
377
|
+
if (matches.length !== 1) {
|
|
378
|
+
const error = new TypeError(`Unresolved semantic reference ${key}: expected exact one installed entry, got ${matches.length}.`);
|
|
379
|
+
Object.assign(error, { code: 'UNRESOLVED_SEMANTIC_REFERENCE', ref: key });
|
|
380
|
+
throw error;
|
|
381
|
+
}
|
|
382
|
+
const candidate = matches[0]!;
|
|
383
|
+
resolved.set(key, candidate);
|
|
384
|
+
for (const nested of findRegisteredRefs(candidate.entry)) {
|
|
385
|
+
if (refKey(nested) !== key) pending.push(nested);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
return [...resolved.values()]
|
|
389
|
+
.sort((left, right) => `${left.category}\0${refKey(left.entry)}`.localeCompare(`${right.category}\0${refKey(right.entry)}`))
|
|
390
|
+
.map(({ category, entry }) => ({ category, entry: normalizeRegistryEntry(category, entry) }));
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
function findRegisteredRefs(value: unknown): RegisteredRef<string>[] {
|
|
394
|
+
const refs: RegisteredRef<string>[] = [];
|
|
395
|
+
visit(value);
|
|
396
|
+
return refs;
|
|
397
|
+
|
|
398
|
+
function visit(candidate: unknown): void {
|
|
399
|
+
if (Array.isArray(candidate)) {
|
|
400
|
+
candidate.forEach(visit);
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
if (candidate === null || typeof candidate !== 'object') return;
|
|
404
|
+
const object = candidate as Record<string, unknown>;
|
|
405
|
+
if (typeof object.id === 'string' && Number.isInteger(object.version)) {
|
|
406
|
+
refs.push({ id: object.id, version: object.version as number });
|
|
407
|
+
}
|
|
408
|
+
Object.values(object).forEach(visit);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
function normalizeRegistryEntry(category: string, entry: VersionedRegistryEntry<string>): unknown {
|
|
413
|
+
const record = entry as VersionedRegistryEntry<string> & Record<string, unknown>;
|
|
414
|
+
switch (category) {
|
|
415
|
+
case 'projections':
|
|
416
|
+
return { ...record, fieldIds: sortedUnknownStrings(record.fieldIds) };
|
|
417
|
+
case 'guardEvaluators':
|
|
418
|
+
return { ...record, allowedInputs: sortUnknownRefs(record.allowedInputs) };
|
|
419
|
+
case 'credentialPolicies': {
|
|
420
|
+
const binding = record.binding as ProjectionSliceRef | undefined;
|
|
421
|
+
return { ...record, binding: binding ? normalizeProjectionSlice(binding) : binding };
|
|
422
|
+
}
|
|
423
|
+
case 'identityComparators':
|
|
424
|
+
return { ...record, operands: sortUnknownRefs(record.operands) };
|
|
425
|
+
case 'executionKeyPolicies':
|
|
426
|
+
return { ...record, requiredFields: sortUnknownProjectionFields(record.requiredFields) };
|
|
427
|
+
case 'lockPolicies': {
|
|
428
|
+
const scope = record.scope as ProjectionSliceRef | null | undefined;
|
|
429
|
+
return { ...record, scope: scope ? normalizeProjectionSlice(scope) : scope };
|
|
430
|
+
}
|
|
431
|
+
case 'journalAdapters':
|
|
432
|
+
return { ...record, compatibleEffectAdapters: sortUnknownRefs(record.compatibleEffectAdapters) };
|
|
433
|
+
case 'recoveryAdapters':
|
|
434
|
+
return { ...record, compatibleJournalAdapters: sortUnknownRefs(record.compatibleJournalAdapters) };
|
|
435
|
+
case 'readbackAdapters':
|
|
436
|
+
return { ...record, compatibleEffectAdapters: sortUnknownRefs(record.compatibleEffectAdapters) };
|
|
437
|
+
case 'releaseProfiles':
|
|
438
|
+
return {
|
|
439
|
+
...record,
|
|
440
|
+
allowedLimitations: sortUnknownRefs(record.allowedLimitations),
|
|
441
|
+
requiredRules: sortUnknownRefs(record.requiredRules),
|
|
442
|
+
};
|
|
443
|
+
case 'coverageProfiles':
|
|
444
|
+
return { ...record, requiredEvidenceKinds: sortedUnknownStrings(record.requiredEvidenceKinds) };
|
|
445
|
+
default:
|
|
446
|
+
return record;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
function defaultExecutableSemantics(): unknown {
|
|
451
|
+
return {
|
|
452
|
+
rules: coreReleaseRuleDescriptors.map(([id, suffix]) => ({
|
|
453
|
+
id, version: 1, implementationId: `implementation.release-rule.${suffix}`, implementationVersion: 1,
|
|
454
|
+
})),
|
|
455
|
+
bindings: [...correctiveReplanExecutableSemanticIdentity]
|
|
456
|
+
.sort((left, right) => `${left.category}\0${left.id}@${left.version}`.localeCompare(`${right.category}\0${right.id}@${right.version}`)),
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
function sortedUnknownStrings(value: unknown): string[] {
|
|
461
|
+
return Array.isArray(value) && value.every((entry) => typeof entry === 'string')
|
|
462
|
+
? [...value].sort((left, right) => left.localeCompare(right))
|
|
463
|
+
: [];
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
function sortUnknownRefs(value: unknown): RegisteredRef<string>[] {
|
|
467
|
+
return Array.isArray(value)
|
|
468
|
+
? sortRefs(value.filter((entry): entry is RegisteredRef<string> =>
|
|
469
|
+
entry !== null
|
|
470
|
+
&& typeof entry === 'object'
|
|
471
|
+
&& typeof (entry as { id?: unknown }).id === 'string'
|
|
472
|
+
&& Number.isInteger((entry as { version?: unknown }).version)))
|
|
473
|
+
: [];
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
function sortUnknownProjectionFields(value: unknown): ProjectionFieldRef[] {
|
|
477
|
+
return Array.isArray(value)
|
|
478
|
+
? sortProjectionFields(value.filter((entry): entry is ProjectionFieldRef => {
|
|
479
|
+
if (entry === null || typeof entry !== 'object') return false;
|
|
480
|
+
const field = entry as { projection?: unknown; fieldId?: unknown };
|
|
481
|
+
return typeof field.fieldId === 'string'
|
|
482
|
+
&& field.projection !== null
|
|
483
|
+
&& typeof field.projection === 'object'
|
|
484
|
+
&& typeof (field.projection as { id?: unknown }).id === 'string'
|
|
485
|
+
&& Number.isInteger((field.projection as { version?: unknown }).version);
|
|
486
|
+
}))
|
|
487
|
+
: [];
|
|
488
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export function deepFreeze<T>(value: T): T {
|
|
2
|
+
if (typeof value === 'function') return Object.freeze(value);
|
|
3
|
+
if (value !== null && typeof value === 'object' && !Object.isFrozen(value)) {
|
|
4
|
+
Object.freeze(value);
|
|
5
|
+
Object.values(value as Record<string, unknown>).forEach(deepFreeze);
|
|
6
|
+
}
|
|
7
|
+
return value;
|
|
8
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type { ExecutableSemanticBinding } from './types.js';
|
|
2
|
+
import { deepFreeze } from './immutable.js';
|
|
3
|
+
|
|
4
|
+
type Callable = (...arguments_: never[]) => unknown;
|
|
5
|
+
|
|
6
|
+
export interface CorrectiveReplanImplementationCallables {
|
|
7
|
+
readonly guards: readonly Callable[];
|
|
8
|
+
readonly identityComparators: readonly Callable[];
|
|
9
|
+
readonly verifyReceipt: Callable;
|
|
10
|
+
readonly acquireTaskLock: Callable;
|
|
11
|
+
readonly createJournalIntent: Callable;
|
|
12
|
+
readonly recoverCorrectiveReplan: Callable;
|
|
13
|
+
readonly executeCorrectiveReplan: Callable;
|
|
14
|
+
readonly terminalReadback: Callable;
|
|
15
|
+
readonly canonicalJsonSha256: Callable;
|
|
16
|
+
readonly rawPlanSha256: Callable;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const coreReleaseRuleDescriptors = deepFreeze([
|
|
20
|
+
['semantic-rule.definition-integrity', 'definition-integrity'],
|
|
21
|
+
['semantic-rule.exact-authority', 'exact-authority'],
|
|
22
|
+
['semantic-rule.required-inputs', 'required-inputs'],
|
|
23
|
+
['semantic-rule.admission-boundary', 'admission-boundary'],
|
|
24
|
+
['semantic-rule.reliable-effects', 'reliable-effects'],
|
|
25
|
+
] as const);
|
|
26
|
+
|
|
27
|
+
const guardSuffixes = [
|
|
28
|
+
'bindings-current', 'source-posture', 'no-step-in-progress', 'active-decision', 'attempt-threshold',
|
|
29
|
+
'semantic-plan-change', 'guarded-step-retained', 'actor-role-eligible', 'no-c1-claim', 'no-writer-lease',
|
|
30
|
+
'plan-validation-passed', 'receipt-valid', 'risk-audit-passed',
|
|
31
|
+
] as const;
|
|
32
|
+
const implementationDescriptors = [
|
|
33
|
+
...guardSuffixes.map((suffix) => ['guardEvaluators', `guard-evaluator.task.corrective-replan.${suffix}`, `guard.${suffix}`, 'evaluate'] as const),
|
|
34
|
+
['identityComparators', 'identity-comparator.corrective-replan.author-validator', 'identity-comparator.corrective-replan.author-validator', 'compare'],
|
|
35
|
+
['identityComparators', 'identity-comparator.corrective-replan.author-risk-auditor', 'identity-comparator.corrective-replan.author-risk-auditor', 'compare'],
|
|
36
|
+
['identityComparators', 'identity-comparator.corrective-replan.author-human-principal', 'identity-comparator.corrective-replan.author-human-principal', 'compare'],
|
|
37
|
+
['credentialVerifiers', 'credential-verifier.corrective-replan.receipt', 'credential-verifier.corrective-replan.receipt', 'verify'],
|
|
38
|
+
['lockPolicies', 'lock-policy.corrective-replan-task-exclusive', 'lock.corrective-replan.task-exclusive', 'execute'],
|
|
39
|
+
['effectAdapters', 'effect-adapter.journaled-corrective-replan', 'effect.journaled-corrective-replan', 'execute'],
|
|
40
|
+
['journalAdapters', 'journal-adapter.corrective-replan-task', 'journal.corrective-replan.task', 'execute'],
|
|
41
|
+
['recoveryAdapters', 'recovery-adapter.corrective-replan-roll-forward', 'recovery.corrective-replan.roll-forward', 'execute'],
|
|
42
|
+
['readbackAdapters', 'readback-adapter.corrective-replan-terminal', 'readback.corrective-replan-terminal', 'execute'],
|
|
43
|
+
['hashPolicies', 'hash-policy.canonical-json-sha256', 'hash.canonical-json-sha256', 'hash'],
|
|
44
|
+
['hashPolicies', 'hash-policy.raw-sha256', 'hash.corrective-plan-raw-sha256', 'hash'],
|
|
45
|
+
] as const;
|
|
46
|
+
|
|
47
|
+
export const correctiveReplanExecutableSemanticIdentity = deepFreeze(implementationDescriptors.map(
|
|
48
|
+
([category, id, semanticSuffix, callableKind]) => ({
|
|
49
|
+
category,
|
|
50
|
+
id,
|
|
51
|
+
version: 1,
|
|
52
|
+
semanticId: `implementation.${semanticSuffix}`,
|
|
53
|
+
semanticVersion: 1,
|
|
54
|
+
wiring: ['credentialVerifiers', 'effectAdapters', 'identityComparators', 'journalAdapters', 'lockPolicies', 'readbackAdapters', 'recoveryAdapters'].includes(category) ? 'invoked' : null,
|
|
55
|
+
implementationResult: category === 'readbackAdapters' ? 'projected-readback' : null,
|
|
56
|
+
projectionWiring: category === 'readbackAdapters' ? 'invoked' : null,
|
|
57
|
+
callableKind,
|
|
58
|
+
}),
|
|
59
|
+
));
|
|
60
|
+
|
|
61
|
+
/** Explicit Core-owned implementation inventory. It is intentionally not derived from registry rows. */
|
|
62
|
+
export function createCorrectiveReplanImplementationTable(
|
|
63
|
+
callables: CorrectiveReplanImplementationCallables,
|
|
64
|
+
): Readonly<Record<string, readonly ExecutableSemanticBinding[]>> {
|
|
65
|
+
return deepFreeze({
|
|
66
|
+
guardEvaluators: [
|
|
67
|
+
...guardSuffixes.map((suffix, index) => binding(
|
|
68
|
+
`guard-evaluator.task.corrective-replan.${suffix}`, `guard.${suffix}`, 'evaluate', callables.guards[index]!,
|
|
69
|
+
)),
|
|
70
|
+
],
|
|
71
|
+
identityComparators: callables.identityComparators.map((callable, index) => {
|
|
72
|
+
const suffix = ['author-validator', 'author-risk-auditor', 'author-human-principal'][index]!;
|
|
73
|
+
return binding(`identity-comparator.corrective-replan.${suffix}`, `identity-comparator.corrective-replan.${suffix}`, 'compare', callable);
|
|
74
|
+
}),
|
|
75
|
+
credentialVerifiers: [
|
|
76
|
+
binding('credential-verifier.corrective-replan.receipt', 'credential-verifier.corrective-replan.receipt', 'verify', callables.verifyReceipt),
|
|
77
|
+
],
|
|
78
|
+
lockPolicies: [
|
|
79
|
+
{ ...binding('lock-policy.corrective-replan-task-exclusive', 'lock.corrective-replan.task-exclusive', 'execute', callables.acquireTaskLock), wiring: 'invoked' },
|
|
80
|
+
],
|
|
81
|
+
effectAdapters: [
|
|
82
|
+
{ ...binding('effect-adapter.journaled-corrective-replan', 'effect.journaled-corrective-replan', 'execute', callables.executeCorrectiveReplan), wiring: 'invoked' },
|
|
83
|
+
],
|
|
84
|
+
journalAdapters: [
|
|
85
|
+
{ ...binding('journal-adapter.corrective-replan-task', 'journal.corrective-replan.task', 'execute', callables.createJournalIntent), wiring: 'invoked' },
|
|
86
|
+
],
|
|
87
|
+
recoveryAdapters: [
|
|
88
|
+
{ ...binding('recovery-adapter.corrective-replan-roll-forward', 'recovery.corrective-replan.roll-forward', 'execute', callables.recoverCorrectiveReplan), wiring: 'invoked' },
|
|
89
|
+
],
|
|
90
|
+
readbackAdapters: [
|
|
91
|
+
{
|
|
92
|
+
...binding('readback-adapter.corrective-replan-terminal', 'readback.corrective-replan-terminal', 'execute', callables.terminalReadback),
|
|
93
|
+
wiring: 'invoked',
|
|
94
|
+
implementationResult: 'projected-readback',
|
|
95
|
+
projectionWiring: 'invoked',
|
|
96
|
+
},
|
|
97
|
+
],
|
|
98
|
+
hashPolicies: [
|
|
99
|
+
binding('hash-policy.canonical-json-sha256', 'hash.canonical-json-sha256', 'hash', callables.canonicalJsonSha256),
|
|
100
|
+
binding('hash-policy.raw-sha256', 'hash.corrective-plan-raw-sha256', 'hash', callables.rawPlanSha256),
|
|
101
|
+
],
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function binding(
|
|
106
|
+
id: string,
|
|
107
|
+
semanticSuffix: string,
|
|
108
|
+
kind: 'compare' | 'evaluate' | 'execute' | 'hash' | 'verify',
|
|
109
|
+
callable: Callable,
|
|
110
|
+
): ExecutableSemanticBinding {
|
|
111
|
+
return {
|
|
112
|
+
id,
|
|
113
|
+
version: 1,
|
|
114
|
+
semanticId: `implementation.${semanticSuffix}`,
|
|
115
|
+
semanticVersion: 1,
|
|
116
|
+
[kind]: callable,
|
|
117
|
+
};
|
|
118
|
+
}
|