Skip to content

[P1] [SPX-AI-017] Deliver a source-defined live repair agent through a supported bounded CLI workflow #116

Closed as not planned

Description

@wsdt

SPX-AI-017 — Deliver a source-defined live repair agent through a supported bounded CLI workflow

Priority: P1 | Workstream: agent-runtime | Import action: New implementation issue
Planning baseline: wavect/semaprax@ae25c6a49dc09ec4613c7a6f52a27daa69dcd3f3 (11 September 2026).
Implementation prerequisites: SPX-AI-013, SPX-AI-014, SPX-AI-015
Important: prerequisites mean the required implementation/evidence is accepted, not merely that its GitHub issue exists.

Outcome

Demonstrate the intended semantic loop end to end: a source-defined agent observes a real failed check/test, obtains a model repair proposal, previews a checked candidate, and produces reviewable evidence. The model must not publish its own change automatically.

Current evidence and distinction from existing work

The repository has source Agent declarations, typed iterative stages, semantic candidate/query/review APIs and explicit publication boundaries. SPX-AI-009–015 connect the missing live path. This issue assembles those components into a user-visible vertical slice, rather than another configuration-only demonstration.

Read these owners first

Directory pointers are navigation roots. Resolve current files with rg --files; proposed new files must follow the current module ownership. The referenced snapshot may be older than the implementing branch.

Bounded scope and non-goals

Use one synthetic repair task in a host-selected temporary project, one provider and bounded semantic tools. Source defines the roles and decision logic; the host supplies explicit provider and publication authority. Default mode stops at a reviewed candidate. Real provider execution and publication remain separately authorized.

Implementation steps

  1. Write the minimal .spx Agent using the existing source-owned roles and the new rich interaction profile. Keep prompts/schemas generated or selected from checked source facts, not duplicate host JSON files with independent semantics.
  2. Expose a narrow CLI/embedding route using the same live runtime entry point. Host-select the project, tools, provider and budget before processing model output. Print clear selected profile/version and prerequisites.
  3. Provide semantic inspection, candidate preview and explicit validation tools using existing owners. Return compact revision-bound feedback; the model cannot execute arbitrary shell commands, alter the oracle or select paths outside the project.
  4. Use a fixture provider to propose an initially incorrect candidate, consume the actual diagnostic and then produce a corrected one. Add a branch where the test result differs so the second request demonstrably uses feedback.
  5. Execute an explicit live smoke on the same task with operator-approved credentials/budget. Keep actual outcome and usage; failure is a valid recorded result, not a reason to substitute fixture evidence.
  6. Interrupt and resume the demonstration around at least one recorded model response and one effect observation. Show unchanged dispatch counts for replayed work and preserved budgets.
  7. Export source diff, semantic impact, validation results, blind spots and journal binding for review. Publish only through a new independently approved session bound to the exact candidate; default execution must make no canonical source/Git change.

Required tests and failure cases

  • The fixture agent repairs using actual feedback and fails when the required observation is withheld.
  • Live mode makes a real provider call and records its true success/failure; offline mode needs no credentials.
  • Malformed proposal, denied operation and failed test yield bounded feedback without unauthorized effects.
  • Interrupted/resumed operation preserves prior observations and produces no duplicate external work.
  • Default run leaves authoritative source untouched, and approval for candidate A cannot publish candidate B.

Test discovery and integration

Use rg --files src tests scripts and the owning harness command cargo test --locked -p semaprax --test <existing-harness> -- --list or its existing library selector. Replace <existing-harness> with the owner established from the references. Register new focused tests in that harness, prove they execute, then run the documented full profile. Do not copy a guessed selector into CI and accept a zero-test success.

Definition of done

  • A fresh operator can run the documented offline vertical slice and an opt-in live smoke.
  • Source Agent, runtime, semantic candidate and evidence refer to the same checked program/context.
  • The result is a real feedback workflow, not an embedded prerecorded response array.

Guardrails for the implementing agent

  • Read the current AGENTS.md, affected RFC/specification, completion rows and architecture owners before implementation. This pack is pinned planning input, not permission to ignore newer code or decisions.
  • Use a private worktree and a private CARGO_TARGET_DIR inside it. Do not use git stash, overwrite sibling worktrees, or share compiler/test scratch output. Add tests to the existing owning harness, not a new compiler-linking top-level test binary unless repository rules require it.
  • Preserve source/graph/schema compatibility where contracted, left-to-right evaluation, lazy operands, ownership transfer, canonical cleanup order and sticky failure. Do not weaken tests, diagnostics, range checks or authority checks to get green.
  • A proposed new shape/API below is a design target, not a claim that syntax or a command already exists. Run --help and discover exact test selectors. Zero selected tests, unavailable tools and skipped required rows are not execution evidence.
  • Keep model output as untrusted data; compiler facts and evidence never mint capabilities. Human support/publication decisions, paid model calls and real registry/Git writes require their own explicit authority.
  • Reuse implemented Agent v2, migrations, iterators, closures, semantic candidates, persistent HIR cache and hosted PG grammar/metadata work. If the requested slice already landed, verify its gate and close only the residual gap rather than building a competitor implementation inside this repo.

Evidence to attach before closing

For the implementation handoff, include: exact starting and finishing commit; changed files and their owning invariants; the pre-fix failure or negative-control result; exact commands, exit status and nonzero selected test counts; target/toolchain/provider identity; artifact/log locations; and remaining limitations. Run the repository's complete required quality profile (scripts/quality.sh full on supported Unix, or the documented platform equivalent) before merge. A local focused pass is not hosted evidence and a green framework is not a completed model experiment. For architecture/ABI/ownership changes, obtain independent semantic review before promotion. Do not mark an execution issue complete using authored tests or documentation alone.

Activity

  1. wsdt commented on Sep 12, 2026

    @wsdt
    MemberAuthor

    Audited, not implemented. HUMAN_BLOCKED — and the reasons are structural, not effort.

    Two of three prerequisites are open, not accepted. gh issue view shows #112 (SPX-AI-013, live provider adapter) OPEN and #113 (SPX-AI-014, live budget/cancellation enforcement) OPEN; only #114 is closed. This issue's own text defines a prerequisite as "implementation/evidence accepted", not merely filed. That condition is not met.

    No .spx source syntax reaches any of this. docs/LIVE-INVOCATION-CONTRACT-V1.md:528 states it plainly: "No parser/HIR/source syntax. model.invoke is not yet a declarable […]". Verified independently — rg -n "model.invoke" src/parser* src/lexer* finds nothing, and the only model keyword in the parser is an unrelated self.keyword("model")? in src/parser/agents.rs:113.

    src/agent_interaction_schema/live_bridge.rs did land since the audit baseline, binding the real compiled Agent Interaction Schema to live_invocation::model_invoke::ProposalDecoder. But its own doc comment says it does not edit src/live_invocation/ or src/agent_runtime_v2/, and it does not touch agent_lifecycle either — so a source-declared Agent still cannot reach a live model call through it.

    Both halves of the title are therefore blocked, and faking either is explicitly out of bounds. "Source-defined" cannot be faked with hand-authored host JSON — this issue's own non-goal forbids "duplicate host JSON files with independent semantics" in place of prompts and schemas generated from checked source facts. "Live" needs a real provider adapter that does not exist (#112 open), plus network egress and credentials this environment does not have.

    The remaining assembly — CLI entry point, semantic-candidate preview and diff export, interrupt/resume, publication-gate separation — sits behind all of that. Landing a partial version would mean bolting a host loop around the checked reducers and describing fixture wiring as more than it is. Nothing in src/agent_runtime_v2.rs, src/cli_driver.rs, src/semantic_service_mcp.rs, or src/project/candidate/** was touched.

    Related work that did land today: #111 is closed — the iterative driver now has a feedback-driven proposal source whose request carries the actual prior effect result, with a bounded decode-retry path and evidence-bearing budget exhaustion. That is the piece of #116's machinery that is reachable offline. What remains genuinely needs the live half.

    HUMAN_BLOCKED: needs #112 and #113 accepted, model.invoke source syntax (parser/HIR work), and an operator-approved live provider credential and budget.

  2. wsdt commented on Sep 13, 2026

    @wsdt
    MemberAuthor

    Accepted 70e3ce9 → bbf9a95 on main.

    Added a checked private-host offline repair loop and actual semaprax-full source-live offline-repair command. Two scripted model calls first produce a rejected candidate, then consume checked diagnostic feedback and produce a corrected ephemeral candidate. The report includes exact candidate review/delta/impact and the retained journal. Source bytes stay unchanged; terminal recovery starts no provider and dispatches no effect. The scalar feedback uses an SPX-G suffix or generic 583, not the full diagnostic namespace/message.

    Actual operator execution: .agent-logs/0913-final-private-cli.json, schema semaprax.private-offline-repair-demo.v1, 2 provider/model/effect dispatches, 1 rejection, 25 journal generations, source_mutation=false. Focused durable-replay regression .agent-logs/0913-final2-repair.log (1 pass).

    #116 stays open for a supported general bounded CLI workflow and real-provider repair evidence. This fixed checkout demo has no persistent CLI repair-resume interface or source publication authority; no full/hosted/live-provider claim.

  3. wsdt commented on Sep 17, 2026

    @wsdt
    MemberAuthor

    Progress — 1409bc7c — not closing, and three corrections to this issue's recorded state

    Verified against the tree before building. Three things this issue currently says are stale:

    1. Prerequisites are done. [P1] [SPX-AI-013] Add one explicitly configured live provider adapter and retain offline fixture transport #112 (live-provider adapter), [P1] [SPX-AI-014] Enforce nonrefundable live-model budgets, deadlines and cancellation at every attempt #113 (budget/cancellation) and [P1] [SPX-AI-015] Persist and recover live Agent conversations without redispatching recorded work #114 (persist/recover) are all closed. The standing "HUMAN_BLOCKED" comment predates that.
    2. The model.invoke blocker was resolved by design, not left as a gap. docs/LIVE-INVOCATION-CONTRACT-V1.md:19-24 already states a literal model.invoke source expression is not required; the propose-role source lowering plus typed live driver is the intended route.
    3. A general, persistent, resumable CLI already exists, and predates the last comment here: semaprax-full source-live run|resume|migrate (crates/semaprax-toolchain/src/source_live_cli/, landed in ea330594). It is project/agent/task-agnostic (arbitrary manifest/source_path/agent_id/step_id/task_path), checkpoint-backed with zero redispatch on resume, budget/pricing/IO-bounded, and drives a real live subprocess provider via ProcessOpenCodeRunner (free "contributor" tier, credential-free). The recorded residual "no supported general provider-repair workflow or persistent CLI repair-resume interface" conflated this with the separate fixed offline-repair demo.

    What was actually missing, and is now fixed

    The general route computed SourceLiveOutcome.checked_run (src/agent_lifecycle/iterative.rs:51) and then silently dropped it in the CLI's receipt(), so the compiled reducer's own evidence never reached the receipt a caller reads. receipt() now embeds iterative_evidence in all three receipt schemas: the semaprax.agent-iterative-evidence.v2 document (status, iteration and effect counts, per-stage rows, authorization bindings, terminal-value digest) on any dispatching attempt, and null on a pure terminal-checkpoint replay — so a replay cannot be misread as a run that dispatched.

    Evidence: cargo test --locked -p semaprax-toolchain --lib source_live_cli:: → 22 passed, 0 failed, including the new assertions.

    Precise residual scope

    Generalize the candidate-preview / source-diff / semantic-impact / blind-spots evidence that only the fixed offline-repair demo produces today (via agent_runtime_v2::OfflineRepairEnvelope / OfflineRepairHandler) so the general run/resume route can drive an arbitrary host-selected repair project through the same candidate-preview machinery. Plus an actual operator-approved live smoke run recorded against the real endpoint — explicitly outside this worker's authorization and not attempted.

    The owning files for that remaining work are src/agent_runtime_v2.rs and src/agent_lifecycle/iterative/source_live/**, not source_live_cli — a future worker should scope there.

  4. wsdt commented on Sep 18, 2026

    @wsdt
    MemberAuthor

    Closure audit @ e9ab9242 — NOT CLOSEABLE.

    Prerequisites are done and the general CLI exists, but candidate-preview/diff evidence has not been generalized to it, and the definition of done additionally requires an operator-approved live smoke run with real credentials.

    Two distinct gaps: one engineering (generalize the evidence path), one requiring an operator with credentials.

  5. wsdt commented on Sep 19, 2026

    @wsdt
    MemberAuthor

    The thread here is stale in a way worth correcting: the last comment (2026-09-18 11:48 UTC) says NOT CLOSEABLE over two gaps, and one of them was closed the same day.

    Gap 1 — "generalize candidate-preview/source-diff/impact evidence off the fixed demo onto the general route" — is already closed by 81031817 ("feat(cli): generalize candidate-preview repair evidence into a config-driven durable CLI route", Refs #116), which landed after that comment was written and was never reported back here. It adds crates/semaprax-toolchain/src/source_live_cli/repair.rs (788 lines), exposing semaprax-full source-live repair run|resume <config.json> <checkpoint-dir> — wired at source_live_cli.rs:47, catalogued in src/cli/help.rs:158. It reuses OfflineRepairEnvelope, OfflineRepairHandler and run_live_bound_model_durable from src/agent_runtime_v2.rs unchanged, driven off an arbitrary host-selected manifest/source/target/effect-contract JSON config rather than the one hardcoded demo.

    One required failure case was genuinely untested, and cf0967e0 closes it. This issue's list includes "The fixture agent repairs using actual feedback and fails when the required observation is withheld." FeedbackGuardedAdapter::start (repair.rs) is the sole production enforcement point, and only its success path was exercised — neither repair_tests.rs nor offline_repair_cli.rs covered the refusal.

    repair_run_fails_when_the_required_prior_feedback_observation_is_withheld flips requires_prior_feedback onto the first scripted turn, which runs before any effect has been dispatched, so the prompt the runtime really builds carries no prior observation. The guard must read the actual prompt bytes and refuse rather than let the agent proceed on a fabricated one. It drives the real run_live_bound_model_durable path rather than calling the adapter directly. Negative control: disabling the guard's condition makes the run succeed with a full candidate receipt and the test fail; repair.rs was restored byte-identical afterwards.

    Status of the scope, honestly:

    • Steps 1–4, 6 and 7 — source-defined Agent roles, the bounded CLI route, semantic inspection / candidate preview / validation, the fixture-provider wrong-then-corrected loop driven by real diagnostic feedback, interrupt/resume with unchanged dispatch counts, and review export with no source mutation — are implemented and covered by passing tests.
    • Step 5 — an explicit live smoke with operator-approved credentials and budget — is the sole remaining blocker and was not attempted. No provider credentials exist in this environment. Nothing in this session called a model, and no fixture output or CLI receipt (source_mutation: false, publication_authority: false) should be read as live-provider or production evidence.

    Verified: -p semaprax-toolchain --lib source_live_cli:: 28 passed, 0 failed. No hosted run has covered cf0967e0 yet.

  6. wsdt commented on Sep 19, 2026

    @wsdt
    MemberAuthor

    Progress pushed in 051682b (Refs #116).

    Added the explicit OpenCode Provider-Adapter repair route and additive V2 receipt while preserving the V1 receipt key set. Adversarial review led to three hardenings before push: V2 now uses restart-stable Unix epoch time instead of the fixture clock, the process timeout is bounded by remaining absolute-deadline time, and checkpoint model identity commits to the selected executable and canonical scratch path. The OpenCode route performs no candidate preview while preparing its durable handler.

    Verified locally: source_live_cli unit slice (29 passed), OpenCode repair-adapter slice (3 passed), cargo fmt, and diff checks. No live provider call or publication/test authority is claimed. Remaining: operator-approved live smoke, V2 settled-wire/resume hostile coverage, and the inherited V1 fixture pre-replay diagnostic derivation.

  7. wsdt commented on Sep 21, 2026

    @wsdt
    MemberAuthor

    Current-main reconciliation: 32ace2e already closed the advertised offline V2 hostile settled-wire/resume recovery cases and the V1 terminal pre-replay diagnostic refusal in crates/semaprax-toolchain/src/source_live_cli/repair_tests/recovery.rs. The remaining blocker is the authorized live-provider smoke/evidence route; this update does not claim that external run.

  8. wsdt commented on Sep 21, 2026

    @wsdt
    MemberAuthor

    Pushed f7014670 to main (Refs #116). The general durable repair route now binds its execution to the exact source bytes retained by the authenticated Project, with a bounded exact raw-path recheck before checkpoint/provider construction and again after provider execution. Source growth after authentication refuses before checkpoint creation; same-length substitution during the recorded two-turn provider flow refuses the receipt, preserves the external source edit, and retains the completed journal for review.

    An adversarial review found the first helper-only test did not prove production placement; it was replaced with two production-path mutation tests. Focused result: cargo test --locked -p semaprax-toolchain --lib source_changed -- --nocapture → 2 passed, 111 filtered. #116 remains open solely for the separately authorized real-provider smoke/evidence; no paid/live call was attempted.

  9. reopened this on Sep 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions