You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add target-node CPU architecture semantics to SDL #674
The SDL Node model has no CPU architecture attribute. Resources carries only RAM and CPU count; the existing runtime-package architecture field describes a package artifact, not the architecture required by the target node or guest.
That prevents an authored environment from expressing a realization-relevant node constraint and makes cross-backend equivalence ambiguous.
Current ownership boundary
This issue covers only the architecture semantics of the node described by SDL.
RAES owns the controlled architecture value, schema placement, validation, normalization, and compatibility semantics between a target node and its runtime packages.
env-packs, adapters, and backends own physical runner/host capability declarations, selection, negotiation, and realization evidence.
A backend manifest may say what a host can provide; it must not replace what the SDL says the target node requires.
Outcome
Add a first-class target-node CPU architecture requirement with a governed vocabulary and deterministic compatibility rules.
Acceptance criteria
The schema distinguishes target-node architecture from runtime-package architecture and backend host architecture.
Canonical vocabulary, aliases, normalization, and unknown/custom-value behavior are explicit.
Validation defines compatibility between a target node and each architecture-constrained package.
Absence has defined semantics and does not silently mean the current host architecture.
Generated contracts, examples, and semantic-diff behavior cover the field.
A conformant backend can report whether it can realize the requirement without RAES selecting a runner.
Non-goals
Modeling a specific cloud instance, runner image, or deployment host.
Backend scheduling or capability negotiation.
Assuming target-node and physical-host architectures are always identical.
changed the title [-]SDL gap: no host CPU architecture field on Node (arch exists only per-package)[/-][+]Add target-node CPU architecture semantics to SDL[/+]on Jul 30, 2026
gc workflow phase recorded: preflight (issue #674). Posted by the MCP server to enforce ordering between workflow steps (issue #794 MVP-2). Do not edit or delete — used by downstream tools to gate phase prerequisites.
gc workflow phase recorded: plan (issue #674). Posted by the MCP server to enforce ordering between workflow steps (issue #794 MVP-2). Do not edit or delete — used by downstream tools to gate phase prerequisites.
Plan — Add target-node CPU architecture semantics to SDL (#674)
Requirement-free run; the issue is the delivery contract. Design bound by the architecture-preflight note docs/decisions/issue-674-target-node-cpu-architecture-preflight.md (no new ADR — governed by ADR-001 SDL intent/realization split, ADR-009/061 contract authority + evolution, ADR-012 portable vocabularies, ADR-008/036 processor boundaries, ADR-070 configuration-bound realization).
What ships
A first-class optional Node.architecture VM field: the CPU architecture the target node/guest requires. It is distinct from the runtime-package artifact architecture (RuntimePackage.architecture) and from the backend host/realizer architecture (RealizerConfigurationModel.architecture). It mirrors the existing Node.os / OS-family wiring at every layer (model → schema → concept-authority vocabulary → phase contracts/variables → compiler → planner admission → realization concern → backend manifests → realization envelope), so no new subsystem is introduced.
Binding semantics (from preflight)
Vocabulary. One governed vocabulary. Initial canonical set is deliberately small: x86_64 (aliases amd64, x64, x86-64) and aarch64 (alias arm64). Normalization is case-insensitive with the existing hyphen→underscore rule applied before alias resolution; canonical serialization always emits the canonical token.
Unknown/custom. Unknown unqualified strings fail closed. A custom value is admitted only in the existing governed-extension form x-<owner>:<term> (canonical lowercase), matched by the concept-authority extension pattern; custom values compare by exact token, no aliases. Ambiguous family labels (x86, arm) and package-portability classifiers (noarch, any, all) are rejected. No other/unknown sentinel — absence already expresses "no requirement".
Absence. Absent means no authored architecture requirement. It never means the controller/host/runner/QEMU-default/image/package architecture. Absence stays absent through normalization and semantic comparison.
Compatibility (deterministic, exact, fail-closed). For each node, across its runtime.packages[]:
node absent + every package arch empty → valid (no requirement);
node absent + any package arch present → invalid (package metadata must not become an implicit target-node requirement).
Rule 4 is a published, fail-closed semantic tightening under ADR-061 (recorded in the schema-publication ledger + regression coverage). Variables defer the comparison to instantiation; finite allowed_values are normalized with the same function and re-checked after binding.
Backend reporting (criterion 6). A node-architecture realization concern is compiled from the authored field; realization_support_diagnostics() reports whether a backend can realize it via supported_constraint_kinds; a new supported_node_architectures provisioner-capability set drives pre-mutation admission. Empty/absent set = no claim, and fails only nodes that explicitly require an architecture. No runner selection or scheduling is added.
Acceptance-criteria mapping
Schema distinguishes target vs package vs host arch → new Node.architecture (target), unchanged RuntimePackage.architecture (package, now canonical-token normalized), unchanged RealizerConfigurationModel.architecture (host).
New pass in _verify_nodes implementing rules 1–4 via self._err(...) (canonical semantic pass; runs again post-binding). No relational logic placed in child models.
3. Phase contracts / variables / composition / SAT
phase_contracts.py:171-176 and scenario.py:104 allowlists: add ("nodes","architecture"); scenario.py_constraint_node_refs architecture branch.
instantiate.py_capture_capability_constraints: emit /nodes/<id>/architecture finite-domain constraint from node.architecture.
models/runtime_model.py:85CompiledCapabilityConstraint concern allowlist: add "nodes.architecture". (composition._prefixed_constraint is field-agnostic — no change.)
satisfiability/_translation.py: add ["nodes",_,"architecture"] → {m.value for m in NodeArchitecture} string-domain case.
New descriptor section="nodes", authored_path=("architecture",), concern_kind="node-architecture", payload_path=("architecture",). Flows through realization_requirements.py and realization_support_diagnostics() automatically (reuses existing RealizationConcern.ARCHITECTURE, ConcernDisposition, ObservationStrength — no new envelope concern).
7. Concept-authority vocabulary
contracts/concept-authority/controlled-vocabularies-v1.json: new provisioner-node-architectures (kind=vocabulary, governed-extension, terms x86_64/aarch64, scope capabilities.provisioner.supported_node_architectures); sync the generated copy under contracts/schemas/concept-authority/.
raes_contracts/contracts/base.py: add scope to _BACKEND_CONCEPT_BINDING_SCOPES.
specs/concept-authority/controlled-vocabularies.md: add "node CPU architectures" to the governed-extension list.
8. Backend capability + manifests
raes_backend_protocols/provisioner_capabilities.py: supported_node_architectures: frozenset[str] = frozenset() (optional — empty = no claim), validated via validate_controlled_vocabulary_scope_values; provisioner_manifest.py serialize/rehydrate.
raes_reference_backend/manifest.py, raes_backend_stubs/manifest.py: declare supported_node_architectures={"x86_64","aarch64"}, add "node-architecture" to supported_constraint_kinds, add ConceptBinding for the new scope.
raes_backend_libvirt/: supported_node_architectures from configuration (no hard-coded x86_64); manifest constraint kind + ConceptBinding; add an architecture dimension to capability_envelope.py (mirror os-family row) + _payload._architecture, so out-of-envelope target architecture fails closed.
Normalize RealizerConfigurationModel.architecture canonically and require agreement with the provisioner supported_node_architectures used for admission. Envelope stays configuration-bound evidence; never overwrites authored intent.
10. Schemas + publication
Regenerate the four Node-bearing schemas (sdl-authoring-input-v1, instantiated-scenario-v1, instantiated-scenario-snapshot-v1, scenario-satisfiability-evidence-v1) + backend-manifest-v2 via tools/generate_contract_schemas.py; update each contracts/schema-publication/entries/*.json (content_hash + last_change summary via schema_content_hash()); keep schema_bundle() parity so check_generated_schemas.py passes. Record rule-4 tightening in the SDL entry's last_change (ADR-061).
11. Examples + specs
Add architecture: x86_64 to a representative VM node in examples/scenarios/techvault.sdl.yaml (verify example-library + conformance gates).
Document the field in specs/sdl/sections.md (+ runtime-inventory where package arch is described).
Tests (mirroring the os-family suite)
Model/normalizer/compat (test_sdl_models.py, new normalizer tests, test_runtime_models.py), switch-rejection parametrize, phase-contract/instantiate finite-domain (test_runtime_planner.py), compiler NodeRuntime, realization concern (test_sem_218_realization*.py), provisioner capability + backend manifests (test_backend_manifest.py, reference/stub/libvirt manifest + realization tests, test_out_of_envelope analog), controlled-vocab catalog (test_controlled_vocabularies.py id set), semantic comparison / envelope contract, schema conformance/publication, example conformance. Security-enforcing behavior (compat fail-closed, out-of-envelope rejection) gets behavioral tests that go red if the enforcement is removed.
Security: architecture is bounded non-secret declarative tokens; no host names, argv, env, subprocess, or probe output crosses raes_runtime.backend_calls; guest uname -m remains realization evidence, never intent. One normalizer/vocabulary across SDL, package, variable-domain, capability, envelope, and schema surfaces (single validation seam).
Maintainability/reuse: builds on incumbents (SDLModel, _populated_vm_only_fields, normalize_enum_value, parse_enum_or_var, the collect-all SemanticValidator, NodeRuntime, the realization-concern registry, validate_controlled_vocabulary_scope_values, schema_bundle()); no parallel DTOs/alias maps/diff code.
Extensibility: the seam is the governed term/alias table + finite-domain path + supported_node_architectures. Adding an architecture is a concept-authority/parity edit, not planner/backend conditionals. Field stays singular; ABI/endianness/CPU-features are out of scope, reserved for separately-typed future companions.
Whole-repo view: all four Node-bearing schemas, publication metadata, controlled vocabulary, generated parity, examples, semantic diff, phase, planner, backend manifests, envelope, and conformance treated as one compatibility surface.
Mandatory plan rules
Run check_repo_policy.py, check_requirement_governance.py, verify_all.py before completion. No CHANGELOG.md/changelog.d edits and no _version.py bump (Release Please owns them). Schema-publication ledger updated for every changed published schema (ADR-009 §7). No authority-bearing artifacts outside specs/, contracts/, docs/, implementations/. PR title will be a feat: Conventional Commit that passes check_pr_title.py.
Risk
Broad blast radius (~30 files, ~10 packages) but each touchpoint is a mechanical mirror of the audited os-family wiring. The one behavioral change beyond additions is compatibility rule 4 (fail-closed) — no existing example/fixture sets a package architecture, so nothing currently breaks; it is published under ADR-061 with regression coverage.
gc_codex_review — cycle 1 of 1 (pre-push) on issue #674 (branch 674-node-cpu-architecture) Diff mode: inline — the complete diff was supplied in one prompt
Core review
Verdict:ship-with-fixes
The change has the right overall seam: it introduces a single portable architecture vocabulary, carries it through SDL normalization, semantic compatibility, compilation, capability admission, backend declarations, and published artifacts rather than inferring from host state. The cross-cutting propagation is disciplined and leaves the obvious extension path—governed custom tokens and capability declarations—open. However, the generated normative schemas do not preserve the fail-closed vocabulary boundary that the runtime implementation establishes.
Blocking findings (1):
[class] Published Node schemas accept arbitrary architecture tokens — contracts/schemas/sdl/sdl-authoring-input-v1.json:5019
Each Node.architecture schema unions NodeArchitecture with an unrestricted string branch, so published-contract consumers accept values such as sparc, arm, or arbitrary text despite the SDL parser and stated contract requiring canonical values, aliases, or governed x-<owner>:<term> extensions. This makes the external schema boundary materially broader than the portable vocabulary and permits invalid documents to pass schema validation before reaching a different validator. Encode the permitted extension/variable forms in the schemas (with the authoring aliases where applicable) so all Node-bearing normative contracts enforce the same boundary.
Security review
Verdict:ship
This change introduces target-node architecture as a governed declarative constraint and carries it through parsing, semantic package compatibility, compilation, capability admission, backend manifests, and published schemas. The design seam is coherent: normalization is centralized, package/node agreement is enforced before planning, and backend support is declared rather than inferred from host state. I found no concrete, exploitable security regression in the supplied diff.
gc_codex_review pre-push cycle 1 of 1 complete for issue #674 on branch '674-node-cpu-architecture'. Posted by the MCP server to enforce the pre-push hard-cap-1 contract (issues #796, #804, #906). Do not edit or delete — used by the next gc_codex_review (uncommitted) invocation to count cycles.
Review decision record — codex cycle 1 (issue #674)
Reviewer: codex Cycle: 1
Architectural read:
Core reviewer: The change has the right overall seam: it introduces a single portable architecture vocabulary, carries it through SDL normalization, semantic compatibility, compilation, capability admission, backend declarations, and published artifacts rather than inferring from host state. The cross-cutting propagation is disciplined and leaves the obvious extension path—governed custom tokens and capability declarations—open. However, the generated normative schemas do not preserve the fail-closed vocabulary boundary that the runtime implementation establishes.
Security reviewer: This change introduces target-node architecture as a governed declarative constraint and carries it through parsing, semantic package compatibility, compilation, capability admission, backend manifests, and published schemas. The design seam is coherent: normalization is centralized, package/node agreement is enforced before planning, and backend support is declared rather than inferred from host state. I found no concrete, exploitable security regression in the supplied diff.
Blocking findings: 1
Finding 1 — class (4 instances)
ID:F1
Title: [core] Published Node schemas accept arbitrary architecture tokens
Rationale: Each Node.architecture schema unions NodeArchitecture with an unrestricted string branch, so published-contract consumers accept values such as sparc, arm, or arbitrary text despite the SDL parser and stated contract requiring canonica…
gc_test_quality_review cycle 1 of 1 complete for issue #674 on branch '674-node-cpu-architecture'. Posted by the MCP server to enforce the gc_test_quality_review hard-cap-1 contract (issue #884 follow-up, default lowered in #906). Do not edit or delete — used by the next gc_test_quality_review invocation to count cycles.
Review decision record — test-quality cycle 1 (issue #674)
Reviewer: test-quality Cycle: 1
Architectural read:
This is a vocabulary-and-plumbing feature: a new governed CPU-architecture concept (raes/architectures.py) is threaded through the existing seams — Node field validator, RuntimePackage field validator, the semantic validator's node/package compatibility pass, the compiler's realization-requirement descriptor table, the planner's capability-domain admission checks, the canonical digest, and the JSON-schema governance guard. The new test_node_architecture.py mirrors that seam-by-seam shape with one test class per layer, and every test drives the real function/model/parse_sdl/plan() path rather than mocking internals — normalize_architecture, architectures_compatible, Node, RuntimePackage, parse_sdl, compile_runtime_model, plan(), and canonical_sdl_digest are all exercised directly against production code I verified in raes/architectures.py, raes/nodes.py, raes/runtime_configuration.py, raes/validator/_nodes_infra_network.py, raes_processor/planner/capability_domains.py, and raes_processor/semantics/realization_concerns.py. The five small one-line diffs in the other five test files are fixture-count/vocab-id bumps that track corresponding production/schema changes, not new assertion logic, so they don't introduce their own risk. I would ship this without changes.
SDL authors can now declare the CPU architecture a VM node requires (e.g. x86_64 or aarch64) as a first-class, optional, governed field, distinct from a runtime package's artifact architecture and from the backend host architecture. Node/package compatibility is checked deterministically and fails closed (an architecture-less node may not carry an architecture-constrained package), absence never assumes the host architecture, and a backend can report whether it can realize a required architecture without the processor selecting a runner.
Add target-node CPU architecture semantics to SDL (#674): a governed NodeArchitecture vocabulary (canonical x86_64/aarch64 with authoring aliases and an x-: extension form) threaded through the Node model, semantic node/package compatibility validation, the compiler, planner capability admission, realization-support disclosure, backend manifests, the realization envelope, the concept-authority controlled vocabulary, and all four Node-bearing published schemas plus backend-manifest-v2 — mirroring the existing os-family wiring rather than introducing a new subsystem. Implements DSL-438.
In-scope requirements
DSL-438 (Target-Node CPU Architecture Semantics) — ACTIVE — Implemented across model, semantic validation, compiler, planner, realization concern, backend manifests, envelope, concept-authority vocabulary, and published schemas.
gc workflow phase recorded: traceability_reconciled (issue #674). Posted by the MCP server to enforce ordering between workflow steps (issue #794 MVP-2). Do not edit or delete — used by downstream tools to gate phase prerequisites.
SDL authors can now declare the CPU architecture a VM node requires (e.g. x86_64 or aarch64) as a first-class, optional, governed field, distinct from a runtime package's artifact architecture and from the backend host architecture. Node/package compatibility is checked deterministically and fails closed (an architecture-less node may not carry an architecture-constrained package), absence never assumes the host architecture, and a backend can report whether it can realize a required architecture without the processor selecting a runner.
Add target-node CPU architecture semantics to SDL (#674): a governed NodeArchitecture vocabulary (canonical x86_64/aarch64 with authoring aliases and an x-: extension form) threaded through the Node model, semantic node/package compatibility validation, the compiler, planner capability admission, realization-support disclosure, backend manifests, the realization envelope, the concept-authority controlled vocabulary, and all four Node-bearing published schemas plus backend-manifest-v2. Merged via PR #1056. Implements DSL-438.
In-scope requirements
DSL-438 (Target-Node CPU Architecture Semantics) — ACTIVE — Materially implemented and shipped in PR feat: add target-node CPU architecture semantics to SDL #1056; requirement was already ACTIVE (created ACTIVE so implementation-time IMPLEMENTS/TESTS links could attach), so the Phase E transition is a no-op.
codex: Core: ship-with-fixes; 1 blocking finding - published Node schemas accepted arbitrary architecture tokens the runtime rejects. Fixed via JSON-Schema patterns, ledger re-hash, and a regression test. Security: ship, no findings.
test-quality: 0 findings, clean run. test_node_architecture.py mirrors the feature seam-by-seam, driving real production paths (normalize/compat, Node/RuntimePackage, parse_sdl, compile, plan(), canonical digest) not mocks. Verdict: ship.
Traceability reconciliation
IMPLEMENTS / TESTS / DOCUMENTS added: 3
Links updated: 0
Stale links removed: 0
25 IMPLEMENTS code links + 6 TESTS links pre-existed from implementation and cover every Python artifact of record in the diff; reconciliation added the GitHub-issue link and two contract-defining artifact-of-record links. Diff had no deleted/renamed files and no stale links.
Activity
[-]SDL gap: no host CPU architecture field on Node (arch exists only per-package)[/-][+]Add target-node CPU architecture semantics to SDL[/+]Brad-Edwards commentedon Aug 2, 2026
🛠️ Picked up by /implement - driver claude-code, branch
674-node-cpu-architecture, 2026-08-02T05:45:23.850Z.Brad-Edwards commentedon Aug 2, 2026
gc workflow phase recorded:
preflight(issue #674). Posted by the MCP server to enforce ordering between workflow steps (issue #794 MVP-2). Do not edit or delete — used by downstream tools to gate phase prerequisites.Brad-Edwards commentedon Aug 2, 2026
gc workflow phase recorded:
plan(issue #674). Posted by the MCP server to enforce ordering between workflow steps (issue #794 MVP-2). Do not edit or delete — used by downstream tools to gate phase prerequisites.Plan — Add target-node CPU architecture semantics to SDL (#674)
Requirement-free run; the issue is the delivery contract. Design bound by the architecture-preflight note
docs/decisions/issue-674-target-node-cpu-architecture-preflight.md(no new ADR — governed by ADR-001 SDL intent/realization split, ADR-009/061 contract authority + evolution, ADR-012 portable vocabularies, ADR-008/036 processor boundaries, ADR-070 configuration-bound realization).What ships
A first-class optional
Node.architectureVM field: the CPU architecture the target node/guest requires. It is distinct from the runtime-package artifactarchitecture(RuntimePackage.architecture) and from the backend host/realizer architecture (RealizerConfigurationModel.architecture). It mirrors the existingNode.os/ OS-family wiring at every layer (model → schema → concept-authority vocabulary → phase contracts/variables → compiler → planner admission → realization concern → backend manifests → realization envelope), so no new subsystem is introduced.Binding semantics (from preflight)
Vocabulary. One governed vocabulary. Initial canonical set is deliberately small:
x86_64(aliasesamd64,x64,x86-64) andaarch64(aliasarm64). Normalization is case-insensitive with the existing hyphen→underscore rule applied before alias resolution; canonical serialization always emits the canonical token.Unknown/custom. Unknown unqualified strings fail closed. A custom value is admitted only in the existing governed-extension form
x-<owner>:<term>(canonical lowercase), matched by the concept-authority extension pattern; custom values compare by exact token, no aliases. Ambiguous family labels (x86,arm) and package-portability classifiers (noarch,any,all) are rejected. Noother/unknownsentinel — absence already expresses "no requirement".Absence. Absent means no authored architecture requirement. It never means the controller/host/runner/QEMU-default/image/package architecture. Absence stays absent through normalization and semantic comparison.
Compatibility (deterministic, exact, fail-closed). For each node, across its
runtime.packages[]:Rule 4 is a published, fail-closed semantic tightening under ADR-061 (recorded in the schema-publication ledger + regression coverage). Variables defer the comparison to instantiation; finite
allowed_valuesare normalized with the same function and re-checked after binding.Backend reporting (criterion 6). A
node-architecturerealization concern is compiled from the authored field;realization_support_diagnostics()reports whether a backend can realize it viasupported_constraint_kinds; a newsupported_node_architecturesprovisioner-capability set drives pre-mutation admission. Empty/absent set = no claim, and fails only nodes that explicitly require an architecture. No runner selection or scheduling is added.Acceptance-criteria mapping
Node.architecture(target), unchangedRuntimePackage.architecture(package, now canonical-token normalized), unchangedRealizerConfigurationModel.architecture(host).NodeArchitectureenum +raes/architectures.pynormalizer/alias map + governedprovisioner-node-architecturescatalog vocabulary +x-<owner>:<term>extension.supported_node_architectures+supported_constraint_kinds+ support diagnostics.Changes (TDD, by layer — test-first at each)
1. Vocabulary + model (
raes/)raes/architectures.py:NodeArchitecture(str, Enum)=X86_64/AARCH64;ARCHITECTURE_ALIASES;ARCHITECTURE_EXTENSION_PATTERN;normalize_architecture()/parse_architecture_or_var()(var passthrough → extension-token validate → alias→canonical enum → else fail closed);architectures_compatible(node, pkg). Single source of truth (no duplicate alias maps).nodes.py:Node.architecture: NodeArchitecture | str | None = None+normalize_architecturefield validator; add"architecture"to_populated_vm_only_fields(switch rejects it); export in__all__.runtime_configuration.py:RuntimePackage.architecturegains a before-validator normalizing populated values to canonical tokens (empty stays empty = unconstrained).2. Compatibility validation (
raes/validator/_nodes_infra_network.py)_verify_nodesimplementing rules 1–4 viaself._err(...)(canonical semantic pass; runs again post-binding). No relational logic placed in child models.3. Phase contracts / variables / composition / SAT
phase_contracts.py:171-176andscenario.py:104allowlists: add("nodes","architecture");scenario.py_constraint_node_refsarchitecture branch.instantiate.py_capture_capability_constraints: emit/nodes/<id>/architecturefinite-domain constraint fromnode.architecture.models/runtime_model.py:85CompiledCapabilityConstraintconcern allowlist: add"nodes.architecture". (composition._prefixed_constraintis field-agnostic — no change.)satisfiability/_translation.py: add["nodes",_,"architecture"]→{m.value for m in NodeArchitecture}string-domain case.4. Compiler (
raes_processor/)models/resources.pyNodeRuntime: addarchitecture: str = "".compiler/provisioning.py_record_node_runtime:architecture=node_spec.get("architecture","") or "". (_compile_capability_constraintsderives concernnodes.architectureautomatically.)5. Planner admission (
raes_processor/planner/)capability_domains.py:_validate_node_architecture(+_architecture_allowed_value(s)) mirroring the os-family finite-domain check againstsupported_node_architectures.manifest_validation.py: call it alongside_validate_node_os_family.6. Realization concern (
raes_processor/semantics/realization_concerns.py)section="nodes", authored_path=("architecture",), concern_kind="node-architecture", payload_path=("architecture",). Flows throughrealization_requirements.pyandrealization_support_diagnostics()automatically (reuses existingRealizationConcern.ARCHITECTURE,ConcernDisposition,ObservationStrength— no new envelope concern).7. Concept-authority vocabulary
contracts/concept-authority/controlled-vocabularies-v1.json: newprovisioner-node-architectures(kind=vocabulary, governed-extension, termsx86_64/aarch64, scopecapabilities.provisioner.supported_node_architectures); sync the generated copy undercontracts/schemas/concept-authority/.raes_contracts/contracts/base.py: add scope to_BACKEND_CONCEPT_BINDING_SCOPES.specs/concept-authority/controlled-vocabularies.md: add "node CPU architectures" to the governed-extension list.8. Backend capability + manifests
raes_backend_protocols/provisioner_capabilities.py:supported_node_architectures: frozenset[str] = frozenset()(optional — empty = no claim), validated viavalidate_controlled_vocabulary_scope_values;provisioner_manifest.pyserialize/rehydrate.raes_contracts/contracts/capabilities.pyProvisionerCapabilitiesModel: optionalsupported_node_architectures: list[...] = []+ controlled-vocab validation (regeneratesbackend-manifest-v2schema).raes_reference_backend/manifest.py,raes_backend_stubs/manifest.py: declaresupported_node_architectures={"x86_64","aarch64"}, add"node-architecture"tosupported_constraint_kinds, add ConceptBinding for the new scope.raes_backend_libvirt/:supported_node_architecturesfrom configuration (no hard-codedx86_64); manifest constraint kind + ConceptBinding; add an architecture dimension tocapability_envelope.py(mirror os-family row) +_payload._architecture, so out-of-envelope target architecture fails closed.9. Realization envelope agreement (
raes_contracts/realization_envelope_carrier.py)RealizerConfigurationModel.architecturecanonically and require agreement with the provisionersupported_node_architecturesused for admission. Envelope stays configuration-bound evidence; never overwrites authored intent.10. Schemas + publication
sdl-authoring-input-v1,instantiated-scenario-v1,instantiated-scenario-snapshot-v1,scenario-satisfiability-evidence-v1) +backend-manifest-v2viatools/generate_contract_schemas.py; update eachcontracts/schema-publication/entries/*.json(content_hash+last_changesummary viaschema_content_hash()); keepschema_bundle()parity socheck_generated_schemas.pypasses. Record rule-4 tightening in the SDL entry'slast_change(ADR-061).11. Examples + specs
architecture: x86_64to a representative VM node inexamples/scenarios/techvault.sdl.yaml(verify example-library + conformance gates).specs/sdl/sections.md(+ runtime-inventory where package arch is described).Tests (mirroring the os-family suite)
Model/normalizer/compat (
test_sdl_models.py, new normalizer tests,test_runtime_models.py), switch-rejection parametrize, phase-contract/instantiate finite-domain (test_runtime_planner.py), compiler NodeRuntime, realization concern (test_sem_218_realization*.py), provisioner capability + backend manifests (test_backend_manifest.py, reference/stub/libvirt manifest + realization tests,test_out_of_envelopeanalog), controlled-vocab catalog (test_controlled_vocabularies.pyid set), semantic comparison / envelope contract, schema conformance/publication, example conformance. Security-enforcing behavior (compat fail-closed, out-of-envelope rejection) gets behavioral tests that go red if the enforcement is removed.Whole-repo / security / maintainability / extensibility
raes_runtime.backend_calls; guestuname -mremains realization evidence, never intent. One normalizer/vocabulary across SDL, package, variable-domain, capability, envelope, and schema surfaces (single validation seam).SDLModel,_populated_vm_only_fields,normalize_enum_value,parse_enum_or_var, the collect-allSemanticValidator,NodeRuntime, the realization-concern registry,validate_controlled_vocabulary_scope_values,schema_bundle()); no parallel DTOs/alias maps/diff code.supported_node_architectures. Adding an architecture is a concept-authority/parity edit, not planner/backend conditionals. Field stays singular; ABI/endianness/CPU-features are out of scope, reserved for separately-typed future companions.Mandatory plan rules
Run
check_repo_policy.py,check_requirement_governance.py,verify_all.pybefore completion. NoCHANGELOG.md/changelog.dedits and no_version.pybump (Release Please owns them). Schema-publication ledger updated for every changed published schema (ADR-009 §7). No authority-bearing artifacts outsidespecs/,contracts/,docs/,implementations/. PR title will be afeat:Conventional Commit that passescheck_pr_title.py.Risk
Broad blast radius (~30 files, ~10 packages) but each touchpoint is a mechanical mirror of the audited os-family wiring. The one behavioral change beyond additions is compatibility rule 4 (fail-closed) — no existing example/fixture sets a package
architecture, so nothing currently breaks; it is published under ADR-061 with regression coverage.Brad-Edwards commentedon Aug 2, 2026
gc_codex_review — cycle 1 of 1 (pre-push) on issue #674 (branch
674-node-cpu-architecture)Diff mode: inline — the complete diff was supplied in one prompt
Core review
Verdict:
ship-with-fixesThe change has the right overall seam: it introduces a single portable architecture vocabulary, carries it through SDL normalization, semantic compatibility, compilation, capability admission, backend declarations, and published artifacts rather than inferring from host state. The cross-cutting propagation is disciplined and leaves the obvious extension path—governed custom tokens and capability declarations—open. However, the generated normative schemas do not preserve the fail-closed vocabulary boundary that the runtime implementation establishes.
Blocking findings (1):
contracts/schemas/sdl/sdl-authoring-input-v1.json:5019Each Node.architecture schema unions NodeArchitecture with an unrestricted string branch, so published-contract consumers accept values such as
sparc,arm, or arbitrary text despite the SDL parser and stated contract requiring canonical values, aliases, or governedx-<owner>:<term>extensions. This makes the external schema boundary materially broader than the portable vocabulary and permits invalid documents to pass schema validation before reaching a different validator. Encode the permitted extension/variable forms in the schemas (with the authoring aliases where applicable) so all Node-bearing normative contracts enforce the same boundary.Security review
Verdict:
shipThis change introduces target-node architecture as a governed declarative constraint and carries it through parsing, semantic package compatibility, compilation, capability admission, backend manifests, and published schemas. The design seam is coherent: normalization is centralized, package/node agreement is enforced before planning, and backend support is declared rather than inferred from host state. I found no concrete, exploitable security regression in the supplied diff.
No blocking findings.
Brad-Edwards commentedon Aug 2, 2026
gc_codex_review pre-push cycle 1 of 1 complete for issue #674 on branch '674-node-cpu-architecture'. Posted by the MCP server to enforce the pre-push hard-cap-1 contract (issues #796, #804, #906). Do not edit or delete — used by the next
gc_codex_review(uncommitted) invocation to count cycles.Brad-Edwards commentedon Aug 2, 2026
Review decision record — codex cycle 1 (issue #674)
Reviewer: codex
Cycle: 1
Architectural read:
Blocking findings: 1
Finding 1 —
class(4 instances)F1contracts/schemas/sdl/sdl-authoring-input-v1.json:5019sparc,arm, or arbitrary text despite the SDL parser and stated contract requiring canonica…contracts/schemas/sdl/sdl-authoring-input-v1.json:5019contracts/schemas/sdl/instantiated-scenario-v1.json:5824contracts/schemas/sdl/instantiated-scenario-snapshot-v1.json:6467contracts/schemas/satisfiability/scenario-satisfiability-evidence-v1.json:5315Brad-Edwards commentedon Aug 2, 2026
gc_test_quality_review cycle 1 of 1 — issue #674
Reviewer: test-quality (claude-sonnet-5 via gc_test_quality_review)
Branch:
674-node-cpu-architectureCycle: 1 / 1
Findings: 0 (clean run)
Brad-Edwards commentedon Aug 2, 2026
gc_test_quality_review cycle 1 of 1 complete for issue #674 on branch '674-node-cpu-architecture'. Posted by the MCP server to enforce the gc_test_quality_review hard-cap-1 contract (issue #884 follow-up, default lowered in #906). Do not edit or delete — used by the next
gc_test_quality_reviewinvocation to count cycles.Brad-Edwards commentedon Aug 2, 2026
Review decision record — test-quality cycle 1 (issue #674)
Reviewer: test-quality
Cycle: 1
Architectural read:
Blocking findings: 0 (clean run)
Brad-Edwards commentedon Aug 2, 2026
Pre-PR base synchronization
refs/remotes/origin/devat5254cd57bcd47df4d5feadecd0c64ec45b96a198merged_clean5465eb21b6c914973fba6369f67f52e0d66aa5bdac6c16d3a25f748323fca3afb11cedf6b2bd6c9fBrad-Edwards commentedon Aug 2, 2026
Pre-PR base synchronization
refs/remotes/origin/devat645ef61f382cc7e69538b2fd4e643a96366bc98emerged_clean2a48ff753126cea781af02cd78e46dd93c1abf271366db860d9d801338b79e56b74fb91439d52040Brad-Edwards commentedon Aug 2, 2026
Pre-PR base synchronization
refs/remotes/origin/devat645ef61f382cc7e69538b2fd4e643a96366bc98ealready_current7313e03b77e4ecb63a037d206125dcd57f8051e3e27a1c068e80afa16f1d62e744ef3b68495f9a00Brad-Edwards commentedon Aug 2, 2026
Ready for review — issue #674
PR: #1056
Plan: #674 (comment)
Outcome
SDL authors can now declare the CPU architecture a VM node requires (e.g. x86_64 or aarch64) as a first-class, optional, governed field, distinct from a runtime package's artifact architecture and from the backend host architecture. Node/package compatibility is checked deterministically and fails closed (an architecture-less node may not carry an architecture-constrained package), absence never assumes the host architecture, and a backend can report whether it can realize a required architecture without the processor selecting a runner.
Add target-node CPU architecture semantics to SDL (#674): a governed NodeArchitecture vocabulary (canonical x86_64/aarch64 with authoring aliases and an x-: extension form) threaded through the Node model, semantic node/package compatibility validation, the compiler, planner capability admission, realization-support disclosure, backend manifests, the realization envelope, the concept-authority controlled vocabulary, and all four Node-bearing published schemas plus backend-manifest-v2 — mirroring the existing os-family wiring rather than introducing a new subsystem. Implements DSL-438.
In-scope requirements
DSL-438(Target-Node CPU Architecture Semantics) — ACTIVE — Implemented across model, semantic validation, compiler, planner, realization concern, backend manifests, envelope, concept-authority vocabulary, and published schemas.Files changed
Added:
docs/decisions/issue-674-target-node-cpu-architecture-preflight.mdimplementations/python/packages/raes/architectures.pyimplementations/python/tests/test_node_architecture.pyModified:
contracts/concept-authority/controlled-vocabularies-v1.jsoncontracts/fixtures/backend-manifest/backend-manifest-v2/valid/stub.jsoncontracts/fixtures/concept-authority/controlled-vocabularies-v1/valid/reference.jsoncontracts/schema-publication/entries/backend-manifest-v2.jsoncontracts/schema-publication/entries/instantiated-scenario-snapshot-v1.jsoncontracts/schema-publication/entries/instantiated-scenario-v1.jsoncontracts/schema-publication/entries/scenario-satisfiability-evidence-v1.jsoncontracts/schema-publication/entries/sdl-authoring-input-v1.jsoncontracts/schemas/backend-manifest/backend-manifest-v2.jsoncontracts/schemas/satisfiability/scenario-satisfiability-evidence-v1.jsoncontracts/schemas/sdl/instantiated-scenario-snapshot-v1.jsoncontracts/schemas/sdl/instantiated-scenario-v1.jsoncontracts/schemas/sdl/sdl-authoring-input-v1.jsondocs/explain/sdl/sections.mddocs/research/formal-semantic-validation/bundles/base-v1.2.jsondocs/research/formal-semantic-validation/bundles/retest-v2.jsondocs/research/formal-semantic-validation/bundles/satisfiability-v1.jsondocs/research/formal-semantic-validation/corpus/exploit-path-invalid-v2.jsondocs/research/formal-semantic-validation/corpus/exploit-path-valid-v2.jsondocs/research/formal-semantic-validation/evidence/finite-domain-satisfiable-v2.jsondocs/research/formal-semantic-validation/evidence/typed-exploit-path-invalid-v2.jsondocs/research/formal-semantic-validation/evidence/typed-exploit-path-valid-v2.jsondocs/research/formal-semantic-validation/execution-snapshot-v1.2.jsondocs/research/formal-semantic-validation/execution-snapshot-v2.jsonexamples/library/templates/scenario/minimal-validated-scenario.yamlimplementations/python/packages/raes/instantiate.pyimplementations/python/packages/raes/nodes.pyimplementations/python/packages/raes/phase_contracts.pyimplementations/python/packages/raes/runtime_configuration.pyimplementations/python/packages/raes/scenario.pyimplementations/python/packages/raes/validator/_nodes_infra_network.pyimplementations/python/packages/raes_backend_libvirt/_payload.pyimplementations/python/packages/raes_backend_libvirt/capability_envelope.pyimplementations/python/packages/raes_backend_libvirt/manifest.pyimplementations/python/packages/raes_backend_libvirt/target.pyimplementations/python/packages/raes_backend_protocols/provisioner_capabilities.pyimplementations/python/packages/raes_backend_protocols/provisioner_manifest.pyimplementations/python/packages/raes_backend_stubs/manifest.pyimplementations/python/packages/raes_contracts/contracts/base.pyimplementations/python/packages/raes_contracts/contracts/capabilities.pyimplementations/python/packages/raes_contracts/realization_envelope_carrier.pyimplementations/python/packages/raes_processor/compiler/provisioning.pyimplementations/python/packages/raes_processor/models/resources.pyimplementations/python/packages/raes_processor/models/runtime_model.pyimplementations/python/packages/raes_processor/planner/capability_domains.pyimplementations/python/packages/raes_processor/planner/manifest_validation.pyimplementations/python/packages/raes_processor/satisfiability/_translation.pyimplementations/python/packages/raes_processor/semantics/realization_concerns.pyimplementations/python/packages/raes_reference_backend/manifest.pyimplementations/python/tests/test_backend_manifest.pyimplementations/python/tests/test_controlled_vocabularies.pyimplementations/python/tests/test_libvirt_backend_manifest_publication.pyimplementations/python/tests/test_sdl_models.pyimplementations/python/tests/test_sem_218_realization_designation.pyspecs/concept-authority/controlled-vocabularies.mdtools/policy/historical_identity_records.jsontools/policy/requirement_order.yamlReviews
Traceability reconciliation
Status
Brad-Edwards commentedon Aug 2, 2026
gc workflow phase recorded:
traceability_reconciled(issue #674). Posted by the MCP server to enforce ordering between workflow steps (issue #794 MVP-2). Do not edit or delete — used by downstream tools to gate phase prerequisites.Brad-Edwards commentedon Aug 2, 2026
Final report — issue #674 complete
PR: #1056
Plan: #674 (comment)
Outcome
SDL authors can now declare the CPU architecture a VM node requires (e.g. x86_64 or aarch64) as a first-class, optional, governed field, distinct from a runtime package's artifact architecture and from the backend host architecture. Node/package compatibility is checked deterministically and fails closed (an architecture-less node may not carry an architecture-constrained package), absence never assumes the host architecture, and a backend can report whether it can realize a required architecture without the processor selecting a runner.
Add target-node CPU architecture semantics to SDL (#674): a governed NodeArchitecture vocabulary (canonical x86_64/aarch64 with authoring aliases and an x-: extension form) threaded through the Node model, semantic node/package compatibility validation, the compiler, planner capability admission, realization-support disclosure, backend manifests, the realization envelope, the concept-authority controlled vocabulary, and all four Node-bearing published schemas plus backend-manifest-v2. Merged via PR #1056. Implements DSL-438.
In-scope requirements
DSL-438(Target-Node CPU Architecture Semantics) — ACTIVE — Materially implemented and shipped in PR feat: add target-node CPU architecture semantics to SDL #1056; requirement was already ACTIVE (created ACTIVE so implementation-time IMPLEMENTS/TESTS links could attach), so the Phase E transition is a no-op.Files changed
Added:
docs/decisions/issue-674-target-node-cpu-architecture-preflight.mdimplementations/python/packages/raes/architectures.pyimplementations/python/tests/test_node_architecture.pyModified:
contracts/concept-authority/controlled-vocabularies-v1.jsoncontracts/fixtures/backend-manifest/backend-manifest-v2/valid/stub.jsoncontracts/fixtures/concept-authority/controlled-vocabularies-v1/valid/reference.jsoncontracts/schema-publication/entries/backend-manifest-v2.jsoncontracts/schema-publication/entries/instantiated-scenario-snapshot-v1.jsoncontracts/schema-publication/entries/instantiated-scenario-v1.jsoncontracts/schema-publication/entries/scenario-satisfiability-evidence-v1.jsoncontracts/schema-publication/entries/sdl-authoring-input-v1.jsoncontracts/schemas/backend-manifest/backend-manifest-v2.jsoncontracts/schemas/satisfiability/scenario-satisfiability-evidence-v1.jsoncontracts/schemas/sdl/instantiated-scenario-snapshot-v1.jsoncontracts/schemas/sdl/instantiated-scenario-v1.jsoncontracts/schemas/sdl/sdl-authoring-input-v1.jsondocs/explain/sdl/sections.mddocs/research/formal-semantic-validation/bundles/base-v1.2.jsondocs/research/formal-semantic-validation/bundles/retest-v2.jsondocs/research/formal-semantic-validation/bundles/satisfiability-v1.jsondocs/research/formal-semantic-validation/corpus/exploit-path-invalid-v2.jsondocs/research/formal-semantic-validation/corpus/exploit-path-valid-v2.jsondocs/research/formal-semantic-validation/evidence/finite-domain-satisfiable-v2.jsondocs/research/formal-semantic-validation/evidence/typed-exploit-path-invalid-v2.jsondocs/research/formal-semantic-validation/evidence/typed-exploit-path-valid-v2.jsondocs/research/formal-semantic-validation/execution-snapshot-v1.2.jsondocs/research/formal-semantic-validation/execution-snapshot-v2.jsonexamples/library/templates/scenario/minimal-validated-scenario.yamlimplementations/python/packages/raes/instantiate.pyimplementations/python/packages/raes/nodes.pyimplementations/python/packages/raes/phase_contracts.pyimplementations/python/packages/raes/runtime_configuration.pyimplementations/python/packages/raes/scenario.pyimplementations/python/packages/raes/validator/_nodes_infra_network.pyimplementations/python/packages/raes_backend_libvirt/_payload.pyimplementations/python/packages/raes_backend_libvirt/capability_envelope.pyimplementations/python/packages/raes_backend_libvirt/manifest.pyimplementations/python/packages/raes_backend_libvirt/target.pyimplementations/python/packages/raes_backend_protocols/provisioner_capabilities.pyimplementations/python/packages/raes_backend_protocols/provisioner_manifest.pyimplementations/python/packages/raes_backend_stubs/manifest.pyimplementations/python/packages/raes_contracts/contracts/base.pyimplementations/python/packages/raes_contracts/contracts/capabilities.pyimplementations/python/packages/raes_contracts/realization_envelope_carrier.pyimplementations/python/packages/raes_processor/compiler/provisioning.pyimplementations/python/packages/raes_processor/models/resources.pyimplementations/python/packages/raes_processor/models/runtime_model.pyimplementations/python/packages/raes_processor/planner/capability_domains.pyimplementations/python/packages/raes_processor/planner/manifest_validation.pyimplementations/python/packages/raes_processor/satisfiability/_translation.pyimplementations/python/packages/raes_processor/semantics/realization_concerns.pyimplementations/python/packages/raes_reference_backend/manifest.pyimplementations/python/tests/test_backend_manifest.pyimplementations/python/tests/test_controlled_vocabularies.pyimplementations/python/tests/test_libvirt_backend_manifest_publication.pyimplementations/python/tests/test_sdl_models.pyimplementations/python/tests/test_sem_218_realization_designation.pyspecs/concept-authority/controlled-vocabularies.mdtools/policy/historical_identity_records.jsontools/policy/requirement_order.yamlReviews
Traceability reconciliation
25 IMPLEMENTS code links + 6 TESTS links pre-existed from implementation and cover every Python artifact of record in the diff; reconciliation added the GitHub-issue link and two contract-defining artifact-of-record links. Diff had no deleted/renamed files and no stale links.
Status