Repository navigation
fix(sdl): rename nested node-service and content-item references with their parent declaration #1573
Description
Gap Claim
rename_sdl_declaration refuses to rename a node when a nodes.<node>.services.<service> reference names it, and refuses to rename a content declaration when a content.<content>.items.<item> reference names it. Both renames return succeeded=False with artifact-transformation.target-invalid.
Cause: _rename_symbols in implementations/python/packages/raes/_transformation_rename.py starts from _identity_symbols, a symbol index built with an empty namespace. In implementations/python/packages/raes/_module_symbols.py, _nested_node_service_aliases and _nested_content_item_aliases skip every node or content entry whose rename-map target equals its own name, so the identity index holds no nested aliases. _rename_symbols then rewrites only existing alias targets that start with nodes.<old>., finds none, and leaves the nested reference unchanged. The candidate no longer validates, and the rename is refused.
Reproduction on dev a391904a. This scenario parses and validates:
name: rename-nested
nodes:
lan: {type: switch}
web:
type: compute
resources: {ram: 1 GiB, cpu: 1}
services: [{port: 80, name: http}]
content:
bundle: {type: dataset, target: web, items: [{name: report}]}
entities:
red-team: {role: red}
agents:
red-agent:
affiliations: [red-team]
actions: [probe]
action_contracts:
probe:
semantic_version: 1.0.0
behavioral_granularity: atomic
procedure_basis: probe the web service
realization_profile: backend-declared
fidelity_claim: records probe intent
preconditions:
- {precondition_id: in-scope, precondition_class: authority, description: the web service is in scope}
effects:
- {effect_id: observed, effect_class: observation_effect, description: probe observation, evidence_refs: [evidence.probe-output]}
failure_classes: [unknown]
behavior_specifications:
probe-behavior:
semantic_version: 1.0.0
lifecycle_state: active
participant_refs: [red-agent]
action_contract_refs: [probe]
authority_scope_refs: [nodes.web.services.http, content.bundle.items.report]| Request | Result |
|---|---|
nodes.web -> frontend |
False ['artifact-transformation.target-invalid'] |
content.bundle -> kit |
False ['artifact-transformation.target-invalid'] |
agents.red-agent -> prober |
True [] |
With authority_scope_refs: [nodes.web, content.bundle] instead, both renames succeed, so the nested spelling alone causes the refusal. Module composition is not affected: an import namespace makes the rename map differ from the identity, so the nested aliases exist there.
This is not #1550, where an infrastructure key that is not a reference blocks a node rename.
Existing Surface Audit
rename_sdl_declarationand module composition share_rewrite_payload_with_symbols(raes/composition/_expand.py), so the rewrite of nested refs already works for imports.nested_node_runtime_family_aliases(raes/_runtime_service_families.py, reached throughnested_node_runtime_aliases) has the same skip (if prefixed_node == node_name: continue) for qualified runtime child refs. The fix covers it, or shows with a test that those refs are unaffected.implementations/python/tests/test_artifact_transformations.pycovers renames of plain and section-qualified references, not nested service or content-item refs.- Found while verifying Verify participant tool authoring across composition and compilation (DSL-117) #298 (PR fix(sdl): keep imported tool affordances bound to their own tool content #1440), which covers the tool and access-account rename paths.
Alternatives
- Build the nested aliases for the identity index too (old ref maps to itself), so
_rename_symbolsfinds and rewrites them: selected. - Special-case nested prefixes in
_rename_symbolsby string rewriting every reference that starts withnodes.<old>.orcontent.<old>.: rejected. It would rewrite strings that are not references and bypass the symbol index that composition uses. - Document the limit: rejected. The rename contract says resolved references are updated, and these references resolve.
Chosen Architecture
Make the identity symbol index carry nodes.<node>.services.<service> and content.<content>.items.<item> aliases, plus qualified runtime child aliases if they show the same gap, each mapping to itself, so _rename_symbols rewrites them through its existing startswith(old_address + ".") branch. Composition output must not change.
The change is package code under implementations/python/packages, which the research-evidence digest covers, so both research captures are republished in the same pull request.
Verification Plan
- Regression tests: the scenario above renames
nodes.webtofrontendandcontent.bundletokit, and the output'sauthority_scope_refsreadnodes.frontend.services.httpandcontent.kit.items.report. - Composition tests for nested refs (
test_sdl_module_registry.py,test_issue_298_tool_authoring.py) stay green. - Both evidence checkers,
verify-fast-feedback,lintandmake policy.
Activity
fix(sdl): reject an imported tool_ref that its own unit finds ambiguous
fix(sdl): reject an imported tool_ref that its own unit finds ambiguous
fix(sdl): rename nested service, runtime and content-item references …
chore(research): record research captures for issue #1573
fix(sdl): keep imported tool affordances bound to their own tool cont…