Summary
Two OpenShell lifecycle/API gaps block the policy-bound per-job sandbox integration in NVIDIA-AI-Blueprints/aiq#298 for AI-Q 2.2:
- A newly created sandbox can reach
Ready and expose an effective policy while the same revision remains Pending indefinitely.
- The public Python SDK cannot send gateway-object labels or list sandboxes by label selector, although the protobuf supports both.
AI-Q intentionally fails closed instead of exposing execution without authoritative policy attestation.
Confirmed policy-state behavior
Reproduced on macOS/Apple Silicon with Docker Desktop:
| OpenShell |
Creation path |
Result |
| 0.0.72 |
clean gateway diagnostic |
Ready; effective policy present; matching revision remains Pending; current_policy_version=0 |
| 0.0.77 |
CLI directly, without AI-Q |
Ready; revision 2 is Effective via policy get; revision 2 remains Pending via policy list; revision 1 is Superseded |
The state remained stable rather than transitioning to LOADED. The policy itself was successfully constructed and applied. landlock.compatibility: best_effort is therefore not an attestation bypass or explanation; it controls filesystem-enforcement compatibility.
Linux has not yet been reproduced. The observed behavior is confirmed on the macOS/Docker Desktop path; source inspection suggests shared lifecycle logic, but a Linux run is required to establish platform scope.
Minimal reproduction
- Create a sandbox with an explicit policy.
- Wait until the sandbox reaches
Ready.
- Compare
policy get <sandbox> -o json, policy list <sandbox>, and the sandbox's current_policy_version.
- Observe an effective positive revision while that same revision remains
Pending.
- Delete the sandbox and verify it is absent.
Expected contract
After initial policy construction:
- report the exact sandbox-scoped revision as
LOADED;
- report
FAILED with a load error when construction fails;
- never leave a successfully applied initial revision permanently
Pending;
- continue reporting later hot-reload revisions normally.
Suspected source path
Inspection of v0.0.72 and v0.0.74 found:
load_policy() constructs the initial OpaEngine;
- the first
run_policy_poll_loop() iteration records config_revision and policy_hash;
ReportPolicyStatus(LOADED) is sent only from the later policy_changed branch;
- an unchanged initial hash never enters that branch.
The same runtime symptom is present in 0.0.77; its exact source path should be confirmed against that tag.
Python SDK label/selector gap
CreateSandboxRequest supports request-level labels and ListSandboxes supports label_selector, but the public Python lifecycle API does not expose them:
SandboxClient.create(), create_session(), and Sandbox(...) cannot forward gateway labels;
SandboxClient.list() cannot forward a selector;
SandboxRef does not retain gateway metadata labels.
Template labels reach Docker/runtime resources, but gateway selectors inspect gateway-object metadata. Consequently, a Python-created AI-Q sandbox is not returned by:
openshell sandbox list --selector aiq=deep-research
Proposed fix
Initial policy acknowledgement
- Preserve the fetched sandbox policy version/source through initial construction.
- Report initial success or failure exactly once.
- Track the acknowledged version so later polling does not duplicate it.
- Preserve existing hot-reload behavior.
Python SDK
Add optional, source-compatible parameters:
name and labels for creation/session/Sandbox;
label_selector for listing;
- immutable gateway labels on
SandboxRef.
The lifecycle and SDK fixes may land separately, but AI-Q requires both in a tagged release.
Acceptance criteria
- Initial success and failure acknowledgement tests.
- Later policy-revision/hot-reload regression tests.
- Python request-label and selector-forwarding tests.
- Docker E2E: create →
Ready → LOADED → selector membership → execute → delete.
- Direct lookup and selector both confirm deletion.
- Tagged release with compatible CLI, Python SDK, and gateway versions.
- AI-Q macOS demo validation with explicit
best_effort.
- AI-Q Linux production validation with
hard_requirement.
Downstream impact
This issue blocks AI-Q #298. It blocks only the OpenShell-specific live acceptance for stacked artifact-lifecycle PR AI-Q #305; #305's provider-independent artifact-storage implementation can be restacked onto develop and proceed separately. AI-Q will not treat Pending as success, weaken attestation, or pin an unreleased fork.
A focused implementation PR can be prepared after maintainer triage and the repository's human state:agent-ready gate.
Summary
Two OpenShell lifecycle/API gaps block the policy-bound per-job sandbox integration in NVIDIA-AI-Blueprints/aiq#298 for AI-Q 2.2:
Readyand expose an effective policy while the same revision remainsPendingindefinitely.AI-Q intentionally fails closed instead of exposing execution without authoritative policy attestation.
Confirmed policy-state behavior
Reproduced on macOS/Apple Silicon with Docker Desktop:
Ready; effective policy present; matching revision remainsPending;current_policy_version=0Ready; revision 2 isEffectiveviapolicy get; revision 2 remainsPendingviapolicy list; revision 1 isSupersededThe state remained stable rather than transitioning to
LOADED. The policy itself was successfully constructed and applied.landlock.compatibility: best_effortis therefore not an attestation bypass or explanation; it controls filesystem-enforcement compatibility.Linux has not yet been reproduced. The observed behavior is confirmed on the macOS/Docker Desktop path; source inspection suggests shared lifecycle logic, but a Linux run is required to establish platform scope.
Minimal reproduction
Ready.policy get <sandbox> -o json,policy list <sandbox>, and the sandbox'scurrent_policy_version.Pending.Expected contract
After initial policy construction:
LOADED;FAILEDwith a load error when construction fails;Pending;Suspected source path
Inspection of v0.0.72 and v0.0.74 found:
load_policy()constructs the initialOpaEngine;run_policy_poll_loop()iteration recordsconfig_revisionandpolicy_hash;ReportPolicyStatus(LOADED)is sent only from the laterpolicy_changedbranch;The same runtime symptom is present in 0.0.77; its exact source path should be confirmed against that tag.
Python SDK label/selector gap
CreateSandboxRequestsupports request-level labels andListSandboxessupportslabel_selector, but the public Python lifecycle API does not expose them:SandboxClient.create(),create_session(), andSandbox(...)cannot forward gateway labels;SandboxClient.list()cannot forward a selector;SandboxRefdoes not retain gateway metadata labels.Template labels reach Docker/runtime resources, but gateway selectors inspect gateway-object metadata. Consequently, a Python-created AI-Q sandbox is not returned by:
Proposed fix
Initial policy acknowledgement
Python SDK
Add optional, source-compatible parameters:
nameandlabelsfor creation/session/Sandbox;label_selectorfor listing;SandboxRef.The lifecycle and SDK fixes may land separately, but AI-Q requires both in a tagged release.
Acceptance criteria
Ready→LOADED→ selector membership → execute → delete.best_effort.hard_requirement.Downstream impact
This issue blocks AI-Q #298. It blocks only the OpenShell-specific live acceptance for stacked artifact-lifecycle PR AI-Q #305; #305's provider-independent artifact-storage implementation can be restacked onto
developand proceed separately. AI-Q will not treatPendingas success, weaken attestation, or pin an unreleased fork.A focused implementation PR can be prepared after maintainer triage and the repository's human
state:agent-readygate.