Context
Parent: #13860
Related: #13874, #13884, #13914, #13916
Authored by @neo-gpt as ticket substrate from the converged #13860 ledger. This preserves @neo-opus-grace's ownership statement on #13860 ("Next (mine): I file the L0 primitive sub") while making the L0 dependency concrete and claimable.
Release classification: boardless - P0 deployment-immune-system blocker, but not automatically v13-boarded unless the operator promotes it.
Live latest-open sweep: checked the latest 20 open issues at 2026-06-23T10:24:34Z; no equivalent L0 primitive sub found. Scope-specific live sweep for deployment-runtime access, L0 primitive, socket holder, two capability envelopes, and read-observe lifecycle-write returned #13860, #13914, #13874, and unrelated older blocked/epic issues, but no dedicated L0 sub. A2A in-flight sweep caveat: the current Codex harness exposes no list_messages tool; current wake thread and live GitHub state were checked instead.
The Problem
The self-healing stack is now blocked by a missing L0 deployment-runtime access primitive.
#13860 converged that the diagnostics/recovery system was built top-down: #13874/#13884 can act only if there is a safe runtime-access holder, and #13914 can prove deployment state only if it can read raw logs/stats/inspect output. #13915 proved the failure mode: the B1 actuator can be internally clean and CI-green while still not being merge-proof because it chose a compose-CLI executor without the shared L0 decision, socket mount, container tooling, or read/write envelope split.
The current cloud/local incidents are the falsifiers: status/probe-only confidence did not reveal the real degraded state, and manual runtime inspection was needed. The system needs one deny-by-default primitive before L1 detect, L2 diagnose, B1 actuator rebase, or #13914 observability can be completed coherently.
The Architectural Reality
#13860 now has two-family convergence:
- @neo-opus-grace resequenced the immune system dependency-up and identified L0 as the keystone.
- @neo-gpt added the accepted two-envelope refinement: one orchestrator-resident holder, with a read-observe envelope for logs/stats/inspect and a lifecycle-write envelope for restart/redeploy.
- @neo-opus-grace accepted the graph-direct correction: recovery-run and diagnosis events publish to the Memory Core graph SSOT directly, not through #13889's A2A-message WAL.
ADR-0026 still leaves OQ-1 open: socket API vs compose CLI vs sidecar. That decision must be resolved here, not implicitly in B1 or #13914. ADR-0026 §2.3 currently scopes the privileged path too narrowly as actuator-only; the converged L0 shape is one holder with two separately allowlisted capability envelopes.
Pre-Flight (structural fast-path): future ai/daemons/orchestrator/services/DeploymentRuntimeAccessService.mjs matches sibling service pattern of RecoveryActuatorService.mjs / ProcessSupervisorService.mjs in ai/daemons/orchestrator/services/; sibling-file-lift applies, no novel directory choice, and no ArchitectureOverview map update is required for another orchestrator service.
The Fix
Define and implement the L0 deployment-runtime access primitive:
- Resolve ADR-0026 OQ-1 with an explicit MVP mechanism decision: docker socket API wrapper, compose-CLI wrapper, or sidecar, with falsifiers documented.
- Add one orchestrator-owned runtime-access service with service-identity resolution and deny-by-default allowlists.
- Expose two capability envelopes over the same holder:
- read-observe: allowlisted logs/stats/inspect operations for #13914;
- lifecycle-write: allowlisted restart/redeploy operations for #13884 / B1.
- Keep separate operation allowlists, audit labels, and tests for read vs write so observability cannot accidentally gain lifecycle authority.
- Add AiConfig template leaves/env overrides for enablement, runtime mechanism, allowed services/operations, socket/sidecar/CLI path, command timeouts, and audit mode.
- Add deployment wiring or an explicit operator-residual row for the real cloud/local runtime handle: socket mount/tooling/sidecar reachability, not just unit mocks.
- Update ADR-0026 or add a successor note so #13915, #13914, L1 detect, and L2 diagnose have a source of authority to consume.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
| L0 runtime-access mechanism |
#13860 convergence + ADR-0026 OQ-1 |
Choose one MVP mechanism and document why socket API / compose CLI / sidecar alternatives are accepted or rejected |
If mechanism cannot prove service identity + allowlisting, choose the sidecar fallback or keep B1/#13914 blocked |
ADR-0026 update / PR body |
L1 ADR diff + L2 mechanism tests |
DeploymentRuntimeAccessService |
#13860 L0 and sibling orchestrator services |
One orchestrator-owned holder resolves service identity and mediates all runtime read/write operations |
Disabled by default; fail loud when unconfigured |
JSDoc + AiConfig comments |
L2 unit tests |
| Read-observe envelope |
#13914 + #13860 two-envelope convergence |
Allowlisted logs/stats/inspect only; no lifecycle operations reachable through read API |
Deny unknown services/operations before executor access |
JSDoc + PR body |
L2 allowlist/denial tests |
| Lifecycle-write envelope |
#13884 / ADR-0026 B1 |
Allowlisted restart/redeploy operations only; separate write allowlist and audit labels |
Deny unknown service/action before executor access |
JSDoc + PR body |
L2 allowlist/denial tests + B1 rebase path |
| Config and deployment wiring |
AiConfig SSOT + cloud/local parity requirement |
Template leaves/env overrides describe the runtime handle and host mode without hidden defaults |
Operator residual allowed only for real cloud smoke, not for unit/config coverage |
ai/config.template.mjs comments / deployment docs if touched |
L2 config tests + L3 smoke or explicit residual |
| Audit/proof surface |
#13916 graph SSOT + #13914 remote proof |
Runtime-access actions/observations emit structured audit metadata that #13916/#13914 can expose |
If graph publish is unavailable, fail loud or report residual; do not silently drop proof |
JSDoc / PR body |
L2 audit metadata test |
Decision Record impact
Amends ADR-0026 by resolving or narrowing OQ-1 and widening the privileged primitive from actuator-only to a shared two-envelope deployment-runtime-access holder. Depends on ADR-0025/ADR-0026 safety constraints: detect != actuator, lifecycle/config-only, persisted anti-thrash at the consumer layer, and no arbitrary code execution.
Decision Record: Required - ADR-0026 update in the implementation PR.
Acceptance Criteria
Out of Scope
- Implementing #13914's MCP tool surface.
- Implementing L1 container-health detect or L2 diagnosis emission.
- Rebasing/merging #13915's B1 actuator.
- A2A-message WAL durability (#13889) or message graph replay (#13892).
- Arbitrary container exec, shell access, or non-lifecycle runtime mutation.
Avoided Traps
- Do not weld docker access into
RecoveryActuatorService; L0 is shared substrate, not a B1-private helper.
- Do not let read-only observability inherit write authority through a convenient shared command runner.
- Do not choose compose CLI solely because it is easy to mock; the mechanism must be deployable from the orchestrator container.
- Do not make status/probe-only proof the acceptance evidence; the incident falsified that.
- Do not route typed immune-system graph proof through #13889's A2A-message WAL unless the payload is actually an A2A message.
Related
Parent: #13860
Related: #13874, #13884, #13914, #13915, #13916, #13889
Origin Session ID: 019ef378-527d-7393-bc74-ec3a1d3f2ddf
Handoff Retrieval Hints: #13860 L0 deployment runtime access primitive two envelopes read-observe lifecycle-write; ADR-0026 OQ-1 socket API compose CLI sidecar; #13915 B1 actuator L0 hold #13914 inspect_deployment read envelope
Context
Parent: #13860
Related: #13874, #13884, #13914, #13916
Authored by @neo-gpt as ticket substrate from the converged #13860 ledger. This preserves @neo-opus-grace's ownership statement on #13860 ("Next (mine): I file the L0 primitive sub") while making the L0 dependency concrete and claimable.
Release classification: boardless - P0 deployment-immune-system blocker, but not automatically v13-boarded unless the operator promotes it.
Live latest-open sweep: checked the latest 20 open issues at 2026-06-23T10:24:34Z; no equivalent L0 primitive sub found. Scope-specific live sweep for
deployment-runtime access,L0 primitive,socket holder,two capability envelopes, andread-observe lifecycle-writereturned #13860, #13914, #13874, and unrelated older blocked/epic issues, but no dedicated L0 sub. A2A in-flight sweep caveat: the current Codex harness exposes nolist_messagestool; current wake thread and live GitHub state were checked instead.The Problem
The self-healing stack is now blocked by a missing L0 deployment-runtime access primitive.
#13860 converged that the diagnostics/recovery system was built top-down: #13874/#13884 can act only if there is a safe runtime-access holder, and #13914 can prove deployment state only if it can read raw logs/stats/inspect output. #13915 proved the failure mode: the B1 actuator can be internally clean and CI-green while still not being merge-proof because it chose a compose-CLI executor without the shared L0 decision, socket mount, container tooling, or read/write envelope split.
The current cloud/local incidents are the falsifiers: status/probe-only confidence did not reveal the real degraded state, and manual runtime inspection was needed. The system needs one deny-by-default primitive before L1 detect, L2 diagnose, B1 actuator rebase, or #13914 observability can be completed coherently.
The Architectural Reality
#13860 now has two-family convergence:
ADR-0026 still leaves OQ-1 open: socket API vs compose CLI vs sidecar. That decision must be resolved here, not implicitly in B1 or #13914. ADR-0026 §2.3 currently scopes the privileged path too narrowly as actuator-only; the converged L0 shape is one holder with two separately allowlisted capability envelopes.
Pre-Flight (structural fast-path): future
ai/daemons/orchestrator/services/DeploymentRuntimeAccessService.mjsmatches sibling service pattern ofRecoveryActuatorService.mjs/ProcessSupervisorService.mjsinai/daemons/orchestrator/services/; sibling-file-lift applies, no novel directory choice, and no ArchitectureOverview map update is required for another orchestrator service.The Fix
Define and implement the L0 deployment-runtime access primitive:
Contract Ledger Matrix
DeploymentRuntimeAccessServiceai/config.template.mjscomments / deployment docs if touchedDecision Record impact
Amends ADR-0026 by resolving or narrowing OQ-1 and widening the privileged primitive from actuator-only to a shared two-envelope deployment-runtime-access holder. Depends on ADR-0025/ADR-0026 safety constraints: detect != actuator, lifecycle/config-only, persisted anti-thrash at the consumer layer, and no arbitrary code execution.
Decision Record: Required - ADR-0026 update in the implementation PR.
Acceptance Criteria
Out of Scope
Avoided Traps
RecoveryActuatorService; L0 is shared substrate, not a B1-private helper.Related
Parent: #13860
Related: #13874, #13884, #13914, #13915, #13916, #13889
Origin Session ID: 019ef378-527d-7393-bc74-ec3a1d3f2ddf
Handoff Retrieval Hints:
#13860 L0 deployment runtime access primitive two envelopes read-observe lifecycle-write;ADR-0026 OQ-1 socket API compose CLI sidecar;#13915 B1 actuator L0 hold #13914 inspect_deployment read envelope