Skip to content

Hosted snapshot: drop Docker (A1), rabbitmq mgmt present-not-enabled (A3), guarantee /run/futureagi + /work layout (P5) - #66

Open
azain-commits wants to merge 36 commits into
feat/hosted-harness-e2e-runtimefrom
feat/hosted-harness-e2e-runtime-azain
Open

Hosted snapshot: drop Docker (A1), rabbitmq mgmt present-not-enabled (A3), guarantee /run/futureagi + /work layout (P5)#66
azain-commits wants to merge 36 commits into
feat/hosted-harness-e2e-runtimefrom
feat/hosted-harness-e2e-runtime-azain

Conversation

@azain-commits

@azain-commits azain-commits commented Aug 25, 2026

Copy link
Copy Markdown

Summary

The hosted Daytona snapshot (Dockerfile.hosted + scripts/daytona-snapshot.sh publisher/CI) and the in-sandbox guest runtime it ships for the hosted harness e2e. Aligned to spine hosted-execution-seams §0. Net-new-and-owned here is the snapshot; the guest runtime is merged from base + feat/hosted-execution-guest (see convergence note).

Snapshot (Dockerfile.hosted)

  • A1 — drop Docker. No docker-ce/compose or DOCKER_HOST; the guest runtime is process-based ("no container runtime in the sandbox").
  • A3 — rabbitmq management present-not-enabled. Management plugin .ez files present but enabled_plugins stripped — available and disabled at boot; the guest enables it and pins its port (amqp_port + 10000).
  • P5 — guaranteed filesystem layout. /run/futureagi (0700 svc-control), /work + /work/artifacts (0755 svc-control) — matches the gateway writing control files there and the guest reading them.
  • Uniform-user provisioning + uv baked in; scripts/daytona-snapshot.sh publishes the snapshot from the Dockerfile (env-driven name/resources, SNAP_DRY_RUN, prints name/state/digest + .env pin) with a manual-publish CI hook.

Guest runtime shipped (merged)

World handle over per-world Postgres, environment-bundle.v2 models + seal, in-sandbox provisioner (build/spawn/readiness/seed/baseline/worlds/reset), hosted scheduler (world pool, scenario loop, retry, receipts), outbound channels (capabilities, canonicalization, spool), scenario-source adapter, platform receipt registration, and the real-voice CallRunner (provider-neutral credentials — Vertex/Deepgram, tool_trace capture, agent-name metadata). Retired the stopgap hosted_sink.py.

Verification

  • Snapshot alk-hosted-v17 live: svc-control uid 2000; /run/futureagi 700, /work(/artifacts) 755; docker → NO_DOCKER; rabbitmq mgmt plugins present + all disabled, no enabled_plugins.
  • Paired e2e with platform PR Hosted harness gateway: retry (P1), /run/futureagi paths (P5), NaN-strict canon (P4a), exit-4 label (P3) future-agi#2332: guest boots → reads /run/futureagi/capabilities.json → world builds over the agent's live Postgres + tools-API → real voice calls placed through self-hosted EU LiveKit via coturn → events + graded receipts post, artifacts upload 201, sandbox verified-deleted at terminal.

Convergence note (read before merging)

This branch merged the guest at an older point. The guest/CallRunner has since advanced on feat/hosted-execution-guest and the integration branch test/manual-e2e, which now carry the run-level build/result/log finalize uploads — the fix for the manifest_required_artifact_missing 422 that currently blocks terminal ack. Recommend converging the ALK-guest side on the integration branch and rebuilding the shared snapshot from it; the snapshot pieces here (Dockerfile.hosted, daytona-snapshot.sh) are what's uniquely owned by this PR.

azain-commits and others added 20 commits August 25, 2026 15:25
… into feat/hosted-harness-e2e-runtime-azain

# Conflicts:
#	src/fi/alk/harness/job.py
#	tests/test_harness_architecture.py
Phase 1 of the hosted execution guest: the typed world surface
(state/put/change/drop/call/query) scenario code receives, backed by a
per-world logical database — baseline-measured state caps, read-only
sub-handles, SQL statement guards, typed errors, and offline + docker
test lanes. call() raises until the http_tool shim wire format is
pinned (recorded contract defect). Known defects tracked in the
implementation ledger.

Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
…contract

check(): empty/whitespace strings count as held; any non-string,
non-False value is a broken check, not an agent failure. ready(): bare
False and any non-string value are broken ready code; setup stays
advisory. Bare state() excludes unmeasured tables the same way it
excludes over-cap ones, so nothing the agent does during a call can
change which tables raise; the typed refusal stays on the explicit
selector.

Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
Typed models for the hosted bundle manifest: runtime kinds with the
evidence seam, managed/source processes, seed stores with per-protocol
sentinels, capability wiring, and the byte-exact inputs-digest helper.
Strategy-engine pairing keys on the capability protocol; the manifest
re-gains the resolved-secret sweep, scoped so v2's own secret_purposes
field is not mistaken for a credential. Riders: runnable-check predicate
parity, broken-value message truncation, cap-exclusion coverage.

Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
The complete §2e checklist as typed preflight errors — digest and
filesystem verification scoped to the real directory, secret material
scanning, unknown-field translation, placeholder vocabulary, secret
purposes both directions, depends_on graph, engine catalog, reserved
names, inputs-digest verification, and the compose gate ahead of all
file-level checks so the dispositive code wins. seal_bundle_v2() is the
normative §2d digest producer, pinned by a hand-computed byte vector.
Model layer gains the user-assignment, engine-agreement, and
reserved-configuration-name rules.

Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
The execution half of the provisioner: per-world/job-shared port
allocation, closed-vocabulary env rendering, copy-based build trees, and
process spawn — every customer process dropped to its declared
unprivileged user, the customer checkout copied with symlinks preserved
and escaping links rejected, process names constrained so a name can
never escape its build/scratch directory. depends_on waits on all of a
dependency's readiness probes; healthy() only ever demotes. Managed
engines start with atomically-created credential files and are probed
with real queries.

Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
…ool, transport clients

The guest's three reporting channels per outbound-channels v1.3 and seam
contract v1.12: the capabilities loader with its closed rejection
vocabulary, byte-exact canonicalization with fixed digest vectors, the
crash-safe sequenced spool (fsync-first, watermark clamp, corruption
degrade-not-wedge, process registry), and the events/results/artifacts
transport clients with the closed HTTP error map, fence latching,
deadline-bounded retries, and redaction before emit.

Four cold review rounds; survivors recorded as known defects in
.claude/harness-alk/reports/outbound-review-r4.md (fork-path lock
pairing, refusal-log volume, stale v1.11 pin).

Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
…eceipts

The scheduler that drains a job's scenarios across W provisioned worlds
per seam contract v1.12: the world pool with §4.5b-serialized provider
calls, degrade-tolerant start, pool-owned world_unhealthy emission and
the §5.4 zero-ready grace rule; per-scenario reset-lease-run-grade with
the v3.4 receipt vocabulary, retry-once on another world, exact skipped
synthesis, and cancel awareness; scenario phases dispatched on a
dedicated executor so a leaked thread can never starve the provider.

Three cold review rounds, closed by a 23-mutant mutation run; survivors
(S1–S10, KD-1–6) recorded in .claude/harness-alk/reports/p9-review-r3.md.

Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
…, conformance

The provisioner's second half per seam contract v1.12: seed/migration
application from the verified bundle under the store's own user, secrets
loaded and deleted before any customer process with purposes from
job.json, baseline freeze for all three engines (explicit redis SAVE,
node-name-free rabbitmq mnesia path), per-world clone and reset with
polled readiness promotion, the two-world conformance gate that never
raises, the healthy() port method (demote-only), dead shared-engine
respawn, reverse-order termination with engine-appropriate signals, and
typed §2f failure codes on every path. Plus the P5-round-2 rider
cleanups (bundle_v2, process_preflight) and the run_world_check
exception-message truncation in checks.py.

Five cold review rounds; the round-5 gate closed on mutation evidence.
Known defects (rabbitmq datadir_copy baselines are world-0-only —
disclosed in-code with the definitions-export follow-up recorded;
sentinel read-only guard is defense-in-depth; promote-poll cost) are
consolidated in .claude/harness-alk/reports/p6-review-r5.md.

Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
…suite's mutation blind spots

Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
… latch, close serialization

Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
…ode contract, W from job parallelism

Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
…dent

Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
…scenario validation, single domain map

Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
…A3), guarantee /run/futureagi + /work dirs (P5)

- A1: remove docker-ce/compose + DOCKER_HOST; process-based runtime per spine §0
- A3: strip enabled_plugins so rabbitmq management is present but disabled at boot
- P5: create /run/futureagi (0700 svc-control), /work + /work/artifacts (0755 svc-control)
…o feat/hosted-harness-e2e-runtime-azain

# Conflicts:
#	src/fi/alk/harness/hosted_entrypoint.py
@azain-commits azain-commits self-assigned this Aug 25, 2026
… scenarios

Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
khushalsonawat and others added 7 commits August 26, 2026 12:10
…liver

Wire register_with_platform() into BundleScenarioSource.build(): one
provision + one begin call on the attempt's scenarios endpoint (single
POST, body-level operation field — the route the platform actually
serves), platform-assigned ids matched to documents BY scenario_key with
hard guards (missing/unknown/duplicate key -> typed failure, never a
partial assignment), and the full key set sent on begin.

Scenario result receipts now carry the platform-assigned scenario_id, so
they deliver instead of being dropped for an empty id. The P12 pinning
test is split honestly: a delivery proof plus a drop-guard preservation
test for the one path that can still see an unregistered scenario.

Also guards empty scenario_key before the network call, keeping that
deterministic content defect in the environment domain instead of
letting the platform's 400 reclassify it as platform_sync.

ScenariosClient path defaults collapse to "" (provision/begin suffixes
would 404 against the real router).

Cold review: CLEARS — 7/7 mutations killed, 823 passed / 0 failed x2.

Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
… PR dry-run)

- scripts/daytona-snapshot.sh: env-driven publish from Dockerfile.hosted via the
  Daytona SDK; caches an SDK venv; prints name+digest to pin ALK_DAYTONA_SNAPSHOT
  [_DIGEST]. SNAP_DRY_RUN validates the Dockerfile/build-context without a key.
- .github/workflows/daytona-snapshot.yml: workflow_dispatch publishes a named
  snapshot (DAYTONA_API_KEY secret); PR/push to runtime paths runs the dry run.
Daytona forces the sandbox to a fixed non-root user (svc-control) and ignores
os_user overrides, so the guest cannot setuid/chown to the bundle's declared
svc-agent/svc-tools/svc-data users. Run every process uniformly as svc-control:
- ProcessRuntimeProvider gains a construction-time require_declared_user (default
  True); provision() falls back to it when the caller passes nothing.
- hosted_entrypoint build_provider default constructs the provider with a null
  user_resolver + require_declared_user=False.
- Dockerfile.hosted bakes uv (astral) for source-process builds (uv sync).
Bundles may still declare svc-* users (model validates); not enforced at runtime.
The gateway delivers /work/source read-only (chmod a-w) for integrity and
copytree preserves that mode, so a source process's build workspace was
read-only and 'python -m venv .venv' failed with EPERM. Restore owner-write on
the copied build tree before running build_commands.
…data

Completes the hosted voice pipeline so a graded call runs in Daytona:
- hosted_call_runner.VoiceCallRunner: drives the proven voice case (run/sdk_voice via
  run.call.place_the_call) against the provisioned agent (livekit_agent_name from
  runtime.metadata) and reads the agent's HARNESS_TOOL_TRACE via _semantic_calls.
- hosted_entrypoint: build_call_runner default -> VoiceCallRunner; peek_secret_map()
  populates caller-lane provider creds into os.environ before the provisioner deletes
  secrets.json (the voice case reads them from the env).
- process_runtime: _control_metadata surfaces livekit_agent_name + tool_trace_path on
  EnvironmentRuntime.metadata per world (rendered from the control service's env).
azain-commits and others added 8 commits August 26, 2026 17:28
CallSummary.started_at/ended_at must be RFC3339 UTC 'Z' millisecond strings
(is_valid_rfc3339_millis); datetime.isoformat() renders +00:00/microseconds and
fails receipt validation. Use outbound.format_rfc3339_millis.
CallRunner: ADC materialization+cleanup, dynamic voice_case, Vertex pre-check,
P=1 root-cause preservation, named dispatch via engine. Provisioner: per-world
livekit_agent_name+tool_trace_path metadata. Entrypoint: caller-lane creds
population, 2-arg build_call_runner, VoiceCallRunner default. Snapshot script:
prefer python3.12/3.11. Bundle authoring script persisted.
214+20 ALK tests green.
Replace the typed not-wired call seam with a real LiveKit runner when the
job's connector is livekit: pre-dial validation of credentials and
dispatch identity, an in-process SimulationSpec drive of the voice
engine, deterministic per-scenario room naming, and a runner-owned call
budget (config voice_call_timeout_seconds, default 300).

Evidence follows the bundle-declared seam: tool_trace reads the world's
database endpoint after the call; http_tool has no guest-side capture
surface today and stays a typed stop rather than an invented proxy.
Transcripts and recordings upload through the artifacts channel before
the receipt references them, and artifact-level refusals degrade to null.

Failure semantics are three distinct paths, each pinned by tests: an
agent that never joins retires the world; any post-dial failure keeps
its measured timing on the receipt; a silent zero-turn agent surfaces as
missing evidence rather than a graded verdict or a false infrastructure
failure.

Voice credentials are captured from the job's secrets before the
provisioner deletes them and exported once for the engine's own reads;
values never appear in logs and stay inside the redaction set.

Cold reviews: round 1 found 1 High (test-honesty) + 2 Medium, all fixed;
round 2 CLEARS — 18 mutation runs killed or validated, 863 passed twice.

Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
…rompt.md

sdk_voice requires this for the caller spec; the hosted lane reads it from the
bundle (matching the local lane's simulator_prompt.md), falling back to the
scenario instruction.
Merges feat/hosted-execution-guest (ef4c5a7): CallRunnerImpl using SimulationRunner
directly, purpose-filtered secret peek, connector-gated factory, per-scenario
room naming, artifact upload. Retires hosted_call_runner.py; keeps uniform-user
provisioner, per-world metadata, build-tree-writable, snapshot script fixes.
203 tests green.
Accept LiveKit URL from config or target-provider secret. Support Google API-key
or Vertex ADC caller auth; materialize service-account JSON mode-0600. Derive
simulator LLM/STT/TTS providers and models from job config/env with generic
defaults. No target-agent/domain-specific runtime logic.
HarnessJob now requires runtime isolation; the test fixture predated that
and would fail construction. Adds RuntimeRequirements(DEDICATED_VM, cpu_units=1).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants