diff --git a/SCOPE.md b/SCOPE.md index 00e4e64..2b1bfc6 100644 --- a/SCOPE.md +++ b/SCOPE.md @@ -43,11 +43,11 @@ installs the package, runs the suite, and validates the packaged catalog. | Profile/catalog resolution | Implemented and CI-validated | | Unknown, invalid, or known-blocked profile refusal | Implemented before sandbox creation | | Sandbox create/destroy lifecycle | Implemented; live failure paths prove teardown | -| Original-checkout isolation | Enforced by code: it is never a post-create execution fallback | +| Original-checkout isolation | Non-secret owner-execution proof passed: source absent, mutation refused, sandbox-only commit and complete cleanup | | SSH transport construction | Implemented and unit-tested; no current positive post-hardening live proof | -| Same-host bwrap execution | Fail-closed, not operational: both local profiles are declared `blocked` and refused before creation; the underlying proof found consumer `nsenter` denied and no in-sandbox rein runtime | +| Same-host bwrap execution | Owner-mediated boundary and stdin task cleanup are live-proven; both local profiles remain `blocked` pending runtime, credential delivery, and explicit egress acceptance | | `rein-aharness` adapter | Implemented; local selection is blocked before creation, while the remote profile remains an explicitly labeled unverified proof path | -| `rein-openweights` adapter | Implemented; provider credential repair was proven, but current local sandbox execution has the same unresolved owner boundary | +| `rein-openweights` adapter | Implemented; provider credential repair was proven, but current local selection remains blocked pending its runtime, credential, and egress acceptance | | CLI channel | Implemented | | State Hub evidence | Implemented as compact progress evidence, not a complete session/tool audit service | @@ -97,9 +97,10 @@ yet Coulomb's general-purpose agent harness service. ## Active gaps -- `GLAS-WP-0005-T05` / `GLAS-IN-0002`: sand-boxer-owned executable bwrap - reachability, rein runtime availability, explicit egress, and credential - delivery are required for a positive in-sandbox rein proof. +- `GLAS-WP-0012` / `GLAS-IN-0002`: prove the first local rein runtime, + governed credential delivery, and explicit egress through the completed + owner-execution adapter. The open-weight portion remains a separate live + requirement in `GLAS-IN-0002`. See `docs/local-profile-acceptance.md`. - `GLAS-IN-0003`: grandfather the pre-canon `GLAS-0001` identifiers. - `GLAS-IN-0004`: align the documented ad hoc workplan convention with the identifier canon. diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index 55ad404..085a7d9 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -19,6 +19,7 @@ | workplan | GLAS-WP-0009 | finished | — | workplans/GLAS-WP-0009-operational-handoff-truth.md | | workplan | GLAS-WP-0010 | finished | — | workplans/GLAS-WP-0010-transport-and-resolution-hardening.md | | workplan | GLAS-WP-0011 | finished | — | workplans/GLAS-WP-0011-statehub-bootstrap.md | +| workplan | GLAS-WP-0012 | blocked | — | workplans/GLAS-WP-0012-first-local-profile-production-proof.md | | task | GLAS-WP-0001-T01 | done | — | workplans/GLAS-WP-0001-harness-router-foundation.md | | task | GLAS-WP-0001-T02 | done | — | workplans/GLAS-WP-0001-harness-router-foundation.md | | task | GLAS-WP-0001-T03 | done | — | workplans/GLAS-WP-0001-harness-router-foundation.md | @@ -60,6 +61,11 @@ | task | GLAS-WP-0011-T01 | done | — | workplans/GLAS-WP-0011-statehub-bootstrap.md | | task | GLAS-WP-0011-T02 | done | — | workplans/GLAS-WP-0011-statehub-bootstrap.md | | task | GLAS-WP-0011-T03 | done | — | workplans/GLAS-WP-0011-statehub-bootstrap.md | +| task | GLAS-WP-0012-T01 | done | — | workplans/GLAS-WP-0012-first-local-profile-production-proof.md | +| task | GLAS-WP-0012-T02 | wait | — | workplans/GLAS-WP-0012-first-local-profile-production-proof.md | +| task | GLAS-WP-0012-T03 | wait | — | workplans/GLAS-WP-0012-first-local-profile-production-proof.md | +| task | GLAS-WP-0012-T04 | wait | — | workplans/GLAS-WP-0012-first-local-profile-production-proof.md | +| task | GLAS-WP-0012-T05 | wait | — | workplans/GLAS-WP-0012-first-local-profile-production-proof.md | | intake | GLAS-IN-0001 | done | blue | docs/intakes/residuals.md | | intake | GLAS-IN-0002 | todo | red | docs/intakes/residuals.md | | intake | GLAS-IN-0003 | todo | green | docs/intakes/residuals.md | diff --git a/docs/intakes/residuals.md b/docs/intakes/residuals.md index 681ba2d..6813d1b 100644 --- a/docs/intakes/residuals.md +++ b/docs/intakes/residuals.md @@ -93,6 +93,13 @@ description: | does not satisfy this production acceptance. GLAS-WP-0005 can close its boundary-hardening scope with this registered live residual still open. + GLAS-WP-0012 now tracks the first (Claude) local-profile acceptance, starting + from harness.agent-dev-local@1.0.0. Its owner return contract and baseline + are in docs/local-profile-acceptance.md. The corresponding owner dependency + is SAND-WP-0014-T05; its current OpenRouter credential requirement does not + establish the Claude route. Keep this intake open for the open-weight + profile even after the first Claude profile is proven. + Done when a non-secret probe and one real rein command execute inside the namespace, the source checkout is not visible/mutable, required egress is explicit, and teardown removes the sandbox workspace. diff --git a/docs/local-profile-acceptance.md b/docs/local-profile-acceptance.md new file mode 100644 index 0000000..f13bdc4 --- /dev/null +++ b/docs/local-profile-acceptance.md @@ -0,0 +1,125 @@ +# First local profile: runtime requirements and acceptance + +Work record: [GLAS-WP-0012](../workplans/GLAS-WP-0012-first-local-profile-production-proof.md). +Live residual: `GLAS-IN-0002`. Owner dependency: `SAND-WP-0014-T05`. + +Start from `harness.agent-dev-local@1.0.0`: rein-aharness / Claude Code / +`claude-sonnet-4-6` / `green-commit-only`. The future proof candidate is +`harness.agent-dev-local@1.1.0`; it is not yet in the catalog because its runtime, +sandbox profile, and credential route are not resolved. + +## Reviewed baseline, 2026-09-05 + +Glas owner adapter: `63a7f9f`. Sand-boxer: +`b6655d88590e03820675719d6dd574e5f5a9f82e`. Rein-aharness source: +`1429db5ad4c83331b6375349ffde1eb13af9575b`. + +Run `.venv/bin/python scripts/inspect-local-runtime.py` to inspect the current +`profile.bwrap-local` from inside owner-mediated execution. This is a +non-secret inventory, not a model call or a readiness bypass. It does not read +credentials or the interactive user's authentication files. Exit zero means +the inventory ran and cleaned up; it does not mean the profile is ready. + +Recorded run: sandbox `236f3683`, consumer `agt` / `glas-runtime-baseline`, +run id `glas-wp-0012-baseline`. Inventory completed successfully; final state +was `destroyed` and the workspace was absent. + +| Requirement | Current evidence | Required owner deliverable | +|---|---|---| +| Owner execution | Real gateway boundary proof passed in GLAS-WP-0005 | Retain exact identity, argv/stdin, timeout, and teardown semantics | +| Rein runtime | `rein-aharness`, `rein_aharness`, and `llm_connect` absent from sandbox discovery | Read-only, reproducible runtime with all required Python dependencies and working CLI entrypoint | +| Claude runtime | `claude` discoverable; startup/authentication not tested | Pin runtime version; prove startup, model selection, tools, and streaming options under the owner environment | +| Persona preparation | `kaizen-agentic` absent | Explicitly accept the rein's recorded `persona_source=none` for this fixture, or provide the optional runtime | +| Authentication | Selected Glas profile declares no credential route | Claude-compatible value-free route id, owner approval/implementation, delivery and revocation behavior | +| Network | `default: deny`, empty egress, only `lo` | Explicit enforced provider route, required DNS/TLS support, denied-destination proof | +| Writable runtime state | Owner sets `HOME` to the copied worktree | Define private auth/cache/state locations and ensure they cannot enter an agent commit | + +The `SANDBOXER_CREDENTIAL_ROUTE_REFS` environment field only carries route +labels. In the reviewed broker it does not acquire or deliver credentials. +Glas must not invent a route id, borrow an interactive login, or use the +OpenRouter credential as a substitute for the selected Claude route. + +The bwrap implementation unconditionally creates an isolated network namespace +and does not create an outbound interface. Declaring an egress hostname in YAML +alone cannot make the current runtime reach it. Sand-boxer owns the enforcement +implementation and its negative tests. + +The rein uses `llm_connect.claude_code.ClaudeCodeAdapter` and launches Claude +with cwd pinned to the sandbox and a named tool allow-list. Host environment +overrides do not survive the owner's sanitized child environment. The runtime +must work under that actual environment, including Git author configuration, +private writable state, and the applicable tool/streaming CLI options. + +## Owner return contract + +Record exact non-secret artifact/revision references for: + +1. The installed sandbox owner path and host. Glas currently calls the local + creating `SandboxManager`; if the intended deployment requires authenticated + HTTP instead, supply that contract and adapt/prove the client before claiming + equivalence with the local manager proof. +2. The sandbox profile and read-only rein/Claude runtime artifact, Python + dependencies, trust store, executable paths, and writable state placement. +3. The Claude-compatible credential route, delivering component, consumer scope, + and cleanup/revocation behavior. Evidence contains route ids and outcomes, + never values, auth files, or provider responses. +4. The enforced egress destinations and ports, DNS/TLS requirements, and proof + that an undeclared destination remains denied. Provider connectivity does + not grant the agent additional network tools. +5. Non-secret startup checks (`rein-aharness --help`, `claude --version` or + owner-equivalent checks), exact actor/project/run identity, absent source + checkout, and destroyed/absent workspace under the deployed path. + +The current SAND-WP-0014-T05 text mentions an OpenRouter AppRole read. That is +a separate route from the chosen first Claude profile. Resolve this distinction +in owner work before selecting credentials or treating T02 as complete. + +## Real acceptance fixture + +After owner dependencies pass, review the exact versioned candidate as +`unverified` and run it on a disposable repository with no push remote. Use a +local test Git identity and a small non-secret task: create only `PROOF.md` +with a fixed expected line and make exactly one local commit. Bound the run +within the reviewed profile's token/time limits. + +Use the actual Glas gateway, concrete `ReinAharness` adapter, installed +`rein-aharness` CLI, and selected Claude model. The GLAS-WP-0005 deterministic +dispatch cannot substitute for this test. + +Before teardown, validate through owner execution: + +- The expected file content, exactly one new commit, expected changed paths, + and a clean working tree. +- Host source path absent from the sandbox; the source sentinel and Git HEAD + remain unchanged when independently checked on the host. +- Exact actor/project/request id as `consumer.run_id` at create and exec; + declared credential route and network policy match the reviewed candidate. +- No task/auth/cache artifacts in the accepted commit; generated task removed + before destroy, followed by destroyed state and absent workspace. + +Retain actual commit/content-validation results before gateway teardown +destroys the workspace. A returned commit SHA alone is insufficient artifact +verification. Keep the proof observer in the acceptance fixture unless a +separate product requirement justifies a general artifact API. + +Also retain failed-run cleanup evidence for an unavailable runtime, refused +credential route, denied required egress, and timeout. Use owner-controlled +negative fixtures; do not disable host networking or mutate real credentials. + +The current Glas adapter supplies `--no-metrics` and has no repository-grant +field. Rein-aharness explicitly refuses repository-grant runs with +`--no-metrics`. This proof therefore validates its disposable output +independently; it must not claim that the repository-grant contract was exercised. +Production grant propagation, if required by the owner return contract, needs +an explicit adapter/state-storage design before the proof candidate can pass. + +## Readiness and rollback + +Only the proven candidate becomes `ready`, with evidence recording the exact +host/runtime scope and revisions. A ready catalog entry is not a live health +probe for every host. Preserve the blocked `1.0.0` version as the rollback pin; +returning to it must refuse, never invoke another runtime. Do not silently +retarget existing consumers or enable production schedules. + +The open-weight profile remains blocked until its own route and real-rein +proof pass. Keep that portion of `GLAS-IN-0002` live after this workplan closes. diff --git a/profiles/harness.agent-dev-local.yaml b/profiles/harness.agent-dev-local.yaml index 433a31c..dd67711 100644 --- a/profiles/harness.agent-dev-local.yaml +++ b/profiles/harness.agent-dev-local.yaml @@ -4,7 +4,7 @@ contract_version: "1.0" status: enabled operational_readiness: status: blocked - reason: sand-boxer owner-mediated bwrap execution and in-sandbox rein runtime are unavailable + reason: in-sandbox rein runtime, governed credential delivery, and explicit provider egress are not yet verified owner: sand-boxer evidence_ref: GLAS-IN-0002 rein: diff --git a/profiles/harness.agent-dev-openweights-local.yaml b/profiles/harness.agent-dev-openweights-local.yaml index df9e797..3b7fdef 100644 --- a/profiles/harness.agent-dev-openweights-local.yaml +++ b/profiles/harness.agent-dev-openweights-local.yaml @@ -4,7 +4,7 @@ contract_version: "1.0" status: enabled operational_readiness: status: blocked - reason: sand-boxer owner-mediated bwrap execution and in-sandbox rein runtime are unavailable + reason: in-sandbox rein runtime, governed credential delivery, and explicit provider egress are not yet verified owner: sand-boxer evidence_ref: GLAS-IN-0002 rein: diff --git a/scripts/inspect-local-runtime.py b/scripts/inspect-local-runtime.py new file mode 100644 index 0000000..1654f62 --- /dev/null +++ b/scripts/inspect-local-runtime.py @@ -0,0 +1,72 @@ +"""Report non-secret runtime availability inside the existing bwrap profile. + +This diagnostic uses owner execution, never runs a model, and does not change +profile readiness. Command discovery does not prove runtime or authentication +health. Run with .venv/bin/python scripts/inspect-local-runtime.py. +""" + +import json +import tempfile +from pathlib import Path + +from sandboxer.core.manager import SandboxManager +from sandboxer.lifecycle.store import SandboxStore +from sandboxer.models import Consumer, SandboxCreateRequest, SandboxExecRequest +from sandboxer.payments.credits import CreditsStore +from sandboxer.snapshots.store import SnapshotStore + + +PROBE = """ +import importlib.util, json, os, shutil +from pathlib import Path +print(json.dumps({ + 'commands': {name: shutil.which(name) is not None for name in + ['python3', 'git', 'rein-aharness', 'claude', 'kaizen-agentic']}, + 'python_modules': {name: importlib.util.find_spec(name) is not None + for name in ['rein_aharness', 'llm_connect']}, + 'interfaces': [line.split(':', 1)[0].strip() + for line in Path('/proc/net/dev').read_text().splitlines()[2:]], + 'credential_route_refs': json.loads(os.environ['SANDBOXER_CREDENTIAL_ROUTE_REFS']), + 'home_is_workspace': os.environ['HOME'] == str(Path.cwd()), +})) +""" + + +def main(): + with tempfile.TemporaryDirectory(prefix="glas-runtime-baseline-") as temp: + root = Path(temp) + source = root / "source" + source.mkdir() + manager = SandboxManager( + store=SandboxStore(path=root / "sandboxes.json"), + credits=CreditsStore(path=root / "credits.json"), + snapshots=SnapshotStore(path=root / "snapshots.json"), + ) + consumer = Consumer(actor="agt", project="glas-runtime-baseline", + run_id="glas-wp-0012-baseline") + status = manager.create(SandboxCreateRequest( + profile="profile.bwrap-local", inputs={"repo": str(source)}, + consumer=consumer, ttl="5m", + )) + try: + result = manager.execute(status.sandbox_id, SandboxExecRequest( + command=["/usr/bin/python3", "-c", PROBE], consumer=consumer, + timeout_seconds=15, + )) + if result.exit_code or result.timed_out or result.output_truncated: + raise RuntimeError("runtime inventory probe failed") + facts = json.loads(result.stdout) + finally: + destroyed = manager.destroy(status.sandbox_id) + removed = not Path(status.reachability.workspace_dir).exists() + facts.update( + sandbox_id=status.sandbox_id, workspace_removed=removed, + state=destroyed.state.value, network_default=result.network_default, + network_egress=result.network_egress, + ) + print(json.dumps(facts, indent=2)) + return 0 if removed and destroyed.state.value == "destroyed" else 1 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/workplans/GLAS-WP-0012-first-local-profile-production-proof.md b/workplans/GLAS-WP-0012-first-local-profile-production-proof.md new file mode 100644 index 0000000..3b398ef --- /dev/null +++ b/workplans/GLAS-WP-0012-first-local-profile-production-proof.md @@ -0,0 +1,160 @@ +--- +id: GLAS-WP-0012 +type: workplan +title: "Prove the first local rein profile end to end" +domain: infotech +repo: glas-harness +status: blocked +owner: codex +topic_slug: first-local-profile-production-proof +created: "2026-09-05" +updated: "2026-09-05" +state_hub_workstream_id: "170bf1ae-337f-5553-8d1e-03b07100e08f" +--- + +# Prove the first local rein profile end to end + +## Context and scope + +Follow up the Claude-route portion of live residual `GLAS-IN-0002`, originating +in finished `GLAS-WP-0005`. Boundary hardening is committed at `63a7f9f` and +proved with a deterministic non-secret dispatch. That proof did not execute +the real rein CLI or make a model call. + +Start from `harness.agent-dev-local@1.0.0` (rein-aharness, +`claude-sonnet-4-6`, `claude-code-cli`, `green-commit-only`). Review a new +versioned candidate after the owner runtime contract is available. Keep the +existing blocked selection as the rollback pin. The open-weight profile and +remote profile do not acquire readiness from this workplan. + +Glas owns profile selection, its adapter, and acceptance evidence. Sand-boxer +owns runtime provisioning, execution environment, isolation, egress enforcement, +and teardown. The selected rein and credential owner own authentication and +credential acquisition. Use existing owner work `SAND-WP-0014-T05`; its current +OpenRouter dependency must be distinguished from this first Claude-route proof. + +## Establish the exact local baseline and acceptance requirements + +```task +id: GLAS-WP-0012-T01 +status: done +priority: high +state_hub_task_id: "711aeb7e-4664-5078-8c65-3fe6f46f7999" +``` + +Completed 2026-09-05. Reviewed Glas `63a7f9f`, sand-boxer `b6655d8`, and +rein-aharness `1429db5`. Added a reproducible non-secret owner-execution runtime +inventory and the [acceptance contract](../docs/local-profile-acceptance.md). + +The baseline can discover Python, Git, and a `claude` command. It cannot +discover `rein-aharness`, its Python module, or `llm_connect`. Command discovery +alone does not prove that Claude can start or authenticate. The namespace has +only loopback; declared egress and credential route references are empty. +Owner execution and workspace teardown pass. The baseline is therefore +insufficient for a real rein run. + +Reviewed the plan against current implementation. Local preparation is done; +remaining execution waits on the owner inputs in T02. + +## Resolve and verify the owner runtime, credential, and egress contract + +```task +id: GLAS-WP-0012-T02 +status: wait +priority: high +state_hub_task_id: "4209f564-a9ee-57f9-9522-3708988801ef" +``` + +Dependency: sand-boxer `SAND-WP-0014-T05`, with rein-aharness and its credential +owner. Required deliverables are listed in `docs/local-profile-acceptance.md`: + +- Exact runtime artifact/revision, in-sandbox entrypoints and dependencies, + sanitized environment, private writable state, and deployment/host identity. +- A Claude-compatible catalog credential route and owner implementation that + delivers it to the selected runtime. An environment label containing route + references is not credential delivery. +- An owner-defined sandbox profile with explicit enforced provider egress, + DNS/TLS requirements, and negative egress tests. Editing an egress list alone + does not provide connectivity in the current loopback-only implementation. +- Non-secret startup, identity, source-absence, and cleanup evidence through + the same manager/service path the gateway will use. + +Done when these deliverables exist at reviewable revisions and their owner +proofs pass. No rein installation in the source checkout, host home mount, +credential injection from the interactive shell, or unrestricted network +substitution is an acceptance path. + +## Review and validate the versioned Glas proof candidate + +```task +id: GLAS-WP-0012-T03 +status: wait +priority: high +state_hub_task_id: "c660808a-1724-555c-bc59-7318870d3591" +``` + +Depends on T02. Prepare `harness.agent-dev-local@1.1.0` only once the real +sandbox profile and credential route are known. Keep the rein/model route and +tool profile explicit; choose bounded proof limits no greater than the current +900 seconds / 60,000 tokens. Record runtime and sandbox revisions and the +validated host scope in evidence. Account for dependency versions that are not +represented directly in the Glas profile schema. + +Use `unverified` only after known blockers are resolved, to label the bounded +real proof. Validate schema, capabilities, route propagation, timeout behavior, +and refusal of the old blocked version. Version coexistence must make an +unversioned selection ambiguous rather than silently changing consumers. + +Done when the exact candidate resolves, the real runtime starts through its +owner, the focused tests and full suite pass, and rollback to the blocked +`harness.agent-dev-local@1.0.0` pin is documented. + +## Prove one real bounded rein task inside the sandbox + +```task +id: GLAS-WP-0012-T04 +status: wait +priority: high +state_hub_task_id: "3e791432-8f37-54bd-a44a-55eeff11ac19" +``` + +Depends on T03. Run the actual `ReinAharness` adapter and installed +`rein-aharness` CLI with Claude through the candidate profile on a disposable +Git fixture. Do not substitute deterministic dispatch or change the source +checkout to satisfy the task. Verify the acceptance assertions in the contract, +including exactly one intended commit, a clean final tree, unchanged/inaccessible +host source, exact identity, bounded duration, task cleanup, and destruction. + +Collect and validate the sandbox artifact before gateway teardown removes the +workspace. Implement the smallest necessary proof observer in the acceptance +fixture; direct evidence must distinguish actual content validation from a +reported commit SHA. Preserve compact value-free evidence only. + +Done when the bounded real run and relevant failure/cleanup checks pass with +the exact selected profile/runtime pins and credential route identified. + +## Publish evidence and mark only the proven profile ready + +```task +id: GLAS-WP-0012-T05 +status: wait +priority: high +state_hub_task_id: "f7635cf6-e044-52d4-8242-0512e0ccbd7b" +``` + +Depends on T04. Update only the proven candidate to `ready` with evidence that +identifies the host/runtime scope, credential route, egress policy, revisions, +limits, and rollback. Run catalog validation and regression checks. Do not +enable production schedules as a side effect of this proof. + +Update `GLAS-IN-0002` with the Claude acceptance result. Keep its open-weight +portion live, or split that remaining work into a separately registered record +before closing the intake. Synchronize work records and log progress. Finish +this workplan only when the first profile is proven and residuals remain live. + +## Acceptance + +One version-pinned local profile runs its actual rein/model task entirely in +the declared sandbox, produces validated local output, and tears down cleanly. +Its readiness describes the proven runtime scope. Other profile readiness and +consumer schedules remain independently governed.