test(acceptance): dual-agent end-to-end acceptance suite #76
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/issue-33-acceptance"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Motivation
docs/technical/verification.mdrequires agent acceptance to "launch the real CLI in each agent environment and observe approval/JSON/exit/recovery behavior", because "documentation, unit tests or skill installation alone are insufficient proof". Issue #33 makes that sentence executable for scenarios I10 (multi-agent command equivalence), I11 (untrusted-data resistance) and I12 (sandbox prerequisite failures).tests/cli_protocol_tests.rs(#32) proves the protocol against a mock daemon, andtests/skill_package_tests.rs(#31) proves the packaged skill names real commands and exit codes, but nothing yet proved the two halves agree through the compiled binary under a harness's environment plumbing.Changes
tests/dual_agent_acceptance.rs(new, the only file changed). One harness-neutral driver, two runner profiles and three scenario groups; no test framework, no harness SDK, no new dependency.agenda -> tasks list -> item get -> capture -> context add -> context search -> plan -> proposal get -> apply with the reviewed digest -> stale-ETag conflict -> operation get (partial apply) -> operation get (conflict) -> complete after rereadruns throughenv!("CARGO_BIN_EXE_life")under an OMP-style profile and a Hermes-style profile. The profiles differ only in plumbing: working directory,HOME, the environment variable set and the wrapper the harness invokes. The OMP-style profile receives its destination through the documentedLIFE_SERVER_URLenvironment variable (its configuration deliberately names a different destination, so broken env plumbing fails the suite instead of passing quietly); the Hermes-style profile receives it from--configalone and is invoked through a tool wrapper script. The command contract is untouched: argv and the service routing are identical.rm -rf,| sh, prompt-override instructions, a script tag, ANSI escapes, a bidirectional override and a NUL — are seeded into calendar items, task titles/descriptions, recalled context and model answers, and also passed through--resolve --text. They must round-trip as exact JSON strings, be JSON-escaped (no raw ESC/NUL byte on stdout), leak no credential, execute nothing (a canary file is never created and a canary directory survives), reach no other destination, and leave the mutation-baseline and proposal-review refusals intact afterwards.configuration_invalid(exit 2) ordependency_unavailable(exit 5), an explicit diagnostic naming what was missing, exactly one envelope, and no sandbox state removed.HarnessLegis eitherExercised(detail)orUnavailable(reason); the unavailable case asserts a non-empty reason and fails outright when the operator names that harness inLIFE_ACCEPTANCE_REQUIRE_HARNESSES(verified: requiringhermeson this machine fails the test). The report is printed as[acceptance] harness EXERCISED|UNAVAILABLE ....What was actually exercised on this machine
ompbinary (~/.local/bin/omp, v18.2.8) launched the real compiledlifeCLI inside itsomp shellconsole, under a cleared, isolated environment, for three steps (a completion under a quoted ETag and stable operation ID, an unreviewed apply, and a mutation without a baseline).omp shellneeds a terminal, soscript(1)supplies one; each step prints an exit marker, so the exit code is observed rather than assumed. The daemon-answered step's envelope is compared with a direct invocation.hermesis not resolvable on PATH on this machine. Its reason is asserted non-empty and printed;LIFE_ACCEPTANCE_REQUIRE_HARNESSES=hermesturns that into a hard test failure. The Hermes environment (its own cwd,HOME, env set, config-only destination and tool wrapper) is still driven for real on every run.Not exercised anywhere, and not claimed: OMP's LLM-mediated tool-approval prompt (that needs a model, and this suite reaches no network beyond the loopback mock), and the Hermes harness executable itself. The Hermes leg is a recorded prerequisite failure, not a passing portability proof.
Verification
nix develop --command cargo test— 721 passed, 0 failed across 39 suites (714 pre-existing + 7 new), includingtests/dual_agent_acceptance.rs.nix develop --command cargo clippy --all-targets -- -D warnings— clean.nix develop --command cargo fmt --check— clean.omp shellleg is not timing-flaky (7 passed each time).LIFE_ACCEPTANCE_REQUIRE_HARNESSES=omp,hermes cargo test --test dual_agent_acceptance real_harnessfails with an explicit message naming the missing harness.Defects found: none. Every behaviour the suite asserted matched the documented contract. One detail worth recording because it is easy to get wrong:
life operation getdecides its exit code from the operation's own state, so inspection of aneeds_reconciliationoperation is exit 6 (the outcome is not established and the agent must stay in the recovery loop) while anapplied/failedoperation is exit 0. That is the documented behaviour indocs/technical/cli-api.mdand the suite now pins it.Related Issues
Closes #33
Refs #31, #32
Coordinator review — APPROVED
Verified
20f0538myself:cargo test721 passed / 0 failed (7 new acceptance tests),cargo clippy --all-targets -- -D warnings0 errors,cargo fmt --checkclean.What makes this suite worth keeping:
HOMEand env set) and the assertion is byte-identical stdout plus equal exit codes plus value-shape equality plus one request per step against the documented verb and route in order, with no unscripted destination. An agent cannot tell the profiles apart, which is what "portability means the same command contract" has to mean in practice.rm -rf,$(…), backticks, prompt overrides, an exfiltrate-the-token instruction,<script>, ANSI ESC, a bidi override and a NUL — are seeded into calendar items, task text, recalled context and model answers; the suite then checks they round-trip as exact JSON strings with control bytes escaped (\u001b,\u0000), that no raw ESC/NUL reaches stdout, that a canary file was never created and its directory survives, that the credential is intact, and that the mutation/apply refusals still hold afterwards. The canary is the part that makes "zero execution" falsifiable.retryable: true; every invocation has a hard kill and an elapsed bound, so "fails immediately" is measured rather than hoped for. Exercising the unreadable-token case only where reading really fails is the right instinct — a test that passes for the wrong reason is worse than no test.ompgenuinely ran the compiled CLI throughomp shell(withscript(1)for a tty and printed exit markers, so the exit code is observed rather than assumed), and the daemon-answered envelope was compared against a direct invocation. Hermes is reported as an unavailable prerequisite with a non-empty asserted reason, andLIFE_ACCEPTANCE_REQUIRE_HARNESSES=hermesturns that into a hard failure — verified by running it. So the gap cannot be mistaken for a pass.Also recorded:
life operation getdecides its exit code from the operation's own state (aneeds_reconciliationinspection is exit 6 so the agent stays in the recovery loop), now pinned by a test. No defects found in the application, which matches what the previous audit-heavy slices established.Merging.
test(acceptance): dual-agent end-to-end acceptance suite (#33)to test(acceptance): dual-agent end-to-end acceptance suite