Repository navigation
Excavator: TEMPORARY headless Argon path via agy CLI (follow-up to #173) - #174
Conversation
Follow-up to #173 (owner decision). Native Excavator stays disabled (subagent: false): AGY 1.3.6+ native pro/flash both run gemini-3.8-flash-tiered. Bulldozer instead invokes the retained Excavator contract headlessly through scripts/excavator-agy.mjs on the exact policy-resolved gemini-4-argon-high slug (same frozen ROLE_POLICY_TABLE resolution as Piledriver/Steamroller/Zen), inside the milestone workspace. - scripts/excavator-agy.mjs: ledger/file/stdin packet (read-only), stream-json agy call with --print-timeout + outer timeout, worker-result parsing in the shape Bulldozer expects, JSONL call telemetry in .ntg/excavator-agy-calls.jsonl, typed failures (AGY_MISSING, RATE_LIMITED, TIMEOUT, UNPARSEABLE_OUTPUT, INVALID_WORKER_RESULT, RECURSION_DETECTED, ...) that fall back to BLOCKED/NEEDS_DEEP. - bulldozer.md: hard-repair path routed to the script via run_command (single TEMPORARY shell exception); excavator stays not natively invocable; TEMPORARY notices across agents, rules, AGENTS.md and docs. - tests: new test_excavator_agy.mjs (31 tests, agy stubbed); role-guidance pins and Argon fail-closed list updated. Suite: 321 tests, 300 pass, 0 fail, 21 skipped; python guards 23 OK. - evidence: one bounded live Argon probe (READY, CONFIRMED root cause, fixture repaired, check exits 0) in .omo/evidence/174-*. Revert to a native Argon subagent once agy allows it.
Gate review 89e3080 requested changes; each fix is locked with a failing-first test. B1 (C1/C6): spine runMilestone rejected declared headless Excavator delegations for DONE, BLOCKED and NEEDS_DEEP. A delegation entry is now accepted only with the sanctioned transport marker (exported HEADLESS_EXCAVATOR_TRANSPORT = 'scripts/excavator-agy.mjs'); a bare excavator role still claims native spawning and stays rejected. BLOCKED/NEEDS_DEEP outcomes persist through the durable ledger path with their evidence; DONE enters independent review. bulldozer.md now instructs declaring the call with the marker; ntg-vnext's declared-delegation projection accepts the same marked entries. B2 (C5/C6): validateWorkerResult accepted READY with only STATUS and ROOT_CAUSE. It now enforces the full worker-result contract: array CHANGES (non-empty for READY), array VERIFICATION_EVIDENCE (non-empty for READY), non-empty RESIDUAL_RISK, and ROLLBACK required whenever persistent changes were made (non-empty CHANGES). The reviewer's exact incomplete input now returns INVALID_WORKER_RESULT. B3 (C7): call-log write failures were swallowed. recordTelemetry now reports logged/logError; a valid worker result whose required log write fails becomes an explicit unsuccessful outcome (ok:false, TELEMETRY_LOG_FAILED, exit 1) with the worker result preserved in worker_result; transport failures keep their primary error plus telemetry_logged:false and telemetry_error. The agy invocation itself is unchanged; the live probe was not repeated. Suite: 339 tests, 318 pass, 0 fail, 21 skipped; python guards 23 OK.
|
Gate fixes for the three blockers in the REQUEST_CHANGES review (reviewed head 89e3080), each locked with a failing-first test: B1 (C1/C6) — declared headless delegations rejected every status. B2 (C5/C6) — READY without material fields passed validation. B3 (C7) — call-log write failures were silent. The live probe is unchanged and not repeated: the agy invocation itself (args, model, prompt transport) is byte-identical; only output validation and telemetry reporting changed. The checked-in probe result carries all contract fields, so it remains valid under the stricter validator. Full suite after fixes: 348 tests, 327 pass, 0 fail, 21 skipped; python guards 23 OK. |
Summary
TEMPORARY alternative path for Excavator after #173 (owner decision). Native
Excavator stays disabled (
subagent: false,mainAgent: false): AGY 1.3.6+native subagent
model:only accepts inherit/flash_lite/flash/pro, and pro andflash both run gemini-3.8-flash-tiered. Bulldozer instead invokes Excavator
headlessly through the agy CLI on an exact policy-resolved Argon slug, with
loud fallbacks to the existing BLOCKED/NEEDS_DEEP path.
Design
scripts/excavator-agy.mjs— TEMPORARY headless runner. Bulldozer callsit via
run_commandfrom the milestone workspace:node <plugin-root>/scripts/excavator-agy.mjs --milestone <id> --blocker "<observed failure>".(
--ledger/NTG_SUPERVISOR_LEDGER+--milestone; the packet is builtwith the same accessors spine's
delegate()uses), or--packet <path|->for direct use. Never retyped by the caller, never written.resolveSlug("excavator")— a newexcavatorentry in the frozenROLE_POLICY_TABLE(family "Gemini 4 Argon", effort High), resolvedat runtime against
agy models, fail-closed on 0/ambiguous matches. Thisis exactly how the runner picks Argon for Piledriver/Steamroller and how
ntg-vnext picks Zen's exact slug. High matches Piledriver's
difficult-decision tier (Argon High); Excavator's difficult
broken-behavior diagnosis/repair is the same effort class.
excavatorisadded to
NATIVE_ROLE_BODY_ROLESonly:invoke()/composeBoundedPrompt()still reject it (it is not in
ROLE_BODY_ROLES), so this grants no runneror delegation authority.
agy --model <slug> --output-format stream-json --print-timeout <timeout-30>s --dangerously-skip-permissions -p "<excavator contract + packet + blocker>"with cwd = milestone workspace. The prompt is theshipped
agents/excavator.mdbody (frontmatter stripped) plus a machineinvocation assignment, mirroring ntg-vnext's
nativeZenshape. OuterspawnSync timeout kills anything agy's own print-timeout misses.
resultevent (deltas as fallback) andreturns Excavator's worker result in the shape Bulldozer's contract
already expects (
ROOT_CAUSElabeled CONFIRMED/LIKELY/SPECULATIVE,CHANGES,VERIFICATION_EVIDENCE,ROLLBACK,RESIDUAL_RISK,STATUSREADY|BLOCKED). Exit 0 = valid worker result; exit 1 = typedfailure.
<workspace>/.ntg/excavator-agy-calls.jsonlwith started_at/ended_at/duration/model/exit_status/ok/error/worker_status/milestone_id/usage.
agents/bulldozer.md— hard-repair path routes to the script viarun_command(the only shell exception, marked TEMPORARY) before fallingback to BLOCKED/NEEDS_DEEP. Bobcat keeps ordinary repairs.
run_commandadded to Bulldozer's frontmatter tools for native-path consistency.
AGY_MISSING(ENOENT),RATE_LIMITED(429/quota/resource-exhausted),TIMEOUT(ETIMEDOUT/outer bound),UNPARSEABLE_OUTPUT(no result event /no parseable worker JSON),
INVALID_WORKER_RESULT(contract shape),AGY_NON_SUCCESS,AGY_EXIT_NONZERO,UNRESOLVED_MODEL_SLUG(model absentfrom installed surface),
RECURSION_DETECTED(NTG_RUNNER_CHAIN guard, samemechanism as the runner). All exit non-zero → Bulldozer falls back to the
existing evidenced BLOCKED / NEEDS_DEEP path and cites the error code.
rules/orchestration.md, docs/internals.md, docs/status.md,
docs/ko/status.md, docs/model-profiles/gemini-4-argon.md and the vNext
architecture contract: revert to a native Argon subagent (and delete the
headless path + run_command exception) once agy allows native Argon
selection.
Evidence
.omo/evidence/174-excavator-headless-probe.md— one bounded live probe:a real
agy -pArgon call through the script on a tiny synthetic repair(
gemini-4-argon-high, brokenadd()fixture), with the worker result,call-log telemetry and post-repair check, paths redacted.
Tests
tests/test_excavator_agy.mjs(31 tests, agy fully stubbed): CLI argparsing incl. env overrides and mutual exclusion, packet validation,
ledger/file/stdin assignment loading, prompt composition, argv building
(stream-json, print-timeout,
-plast), stream-json parsing (result event,delta fallback, junk tolerance), worker-result extraction (bare/fenced/
wrapped; typed invalids), failure classification (ENOENT/ETIMEDOUT/429
variants/plain exits), end-to-end success + BLOCKED, all failure modes
with telemetry records, recursion guard, runner-chain propagation, CLI
exit codes.
tests/test_role_guidance.mjs(bulldozer/orchestration byte pins;bulldozer now must carry
run_commandscoped to the script, TEMPORARY) andtests/test_runner_spike.mjs(excavator joins the Argon fail-closed test).+31 = the new file). Python guards: 23 tests OK.
Not verified
ntg-vnext runmilestone (needs a full milestone with a genuinely hardrepair); the routing is contract text + tested script behavior, and the
Temporarily disable Excavator pending native Argon support #173 BLOCKED/NEEDS_DEEP path itself is already covered by
tests/test_ntg_vnext.mjs.patterns, not by exhausting the real quota.
NTG_EXCAVATOR=1marker contractinside a real repair is covered by the deterministic guard tests; the probe
fixture needed no privileged commands, so the guard did not fire in it.
Revert
Re-enable natively once a bounded native-subagent probe demonstrates Argon in
the child's actual model metadata, then in one change: set the verified native
tier +
subagent: true, restore Bulldozer's native routing and spineallowlists, and delete the headless script, its tests, the run_command
exception and the TEMPORARY notices.