Skip to content

fix(#844): plumb LSP_PILOT_ENABLED env + decouple capture from LSP wiring so the pilot A/B runs in CI #1031

Description

@don-petry

Epic: #839 · Story: #844 · Builds on: #961 (capture/emit) + #952 (extractor/harness)

Context

PR #961 added the pilot capture/emit logic to scripts/engine.sh + scripts/review-one-pr.sh (gated on the env LSP_PILOT_ENABLED), but only touched the scripts — not .github/workflows/pr-review.yml. Two gaps leave the feature inert / incomplete in real CI. This issue closes both so a production pr-review can emit a comparable lsp-off (A) and lsp-on (B) lsp_pilot_run record pair.

Gap 1 — the capture env var is never plumbed

_lsp_pilot_active() (engine.sh) and the trap in review-one-pr.sh gate on the env LSP_PILOT_ENABLED=true, but pr-review.yml only references the repo variable vars.LSP_PILOT_ENABLED (to gate the setup-lsp-pilot step, lines 378/387). vars.* are not automatically env vars, and neither the job env: block nor setup-lsp-pilot.sh exports LSP_PILOT_ENABLED to GITHUB_ENV. Result: with the repo var on, the LSP gets wired but no transcript is captured and no record is emitted (the unit tests pass only because they set the env directly).

Gap 2 — capture and LSP wiring can't be decoupled

Both the capture and the setup-lsp-pilot step key off the same vars.LSP_PILOT_ENABLED, and lpe_variant() returns lsp-on whenever REVIEW_MCP_CONFIG is wired. So a production run can only ever produce an lsp-on (B) record — there is no way to produce the lsp-off (A) control leg (capture on, LSP wiring off). The comparison needs both legs from the same pipeline.

Acceptance criteria

  1. Plumb the capture gate. The review job in pr-review.yml must export LSP_PILOT_ENABLED as an env var to the step(s) that run the engine / review-one-pr.sh, so _lsp_pilot_active() actually sees it. When capture is enabled and a review runs, a kind:"lsp_pilot_run" record is emitted to TOKEN_LOG_FILE (already uploaded as the token-usage-<run_id> artifact).
  2. Decouple capture from LSP wiring. Add an independent control so a run can enable capture/emit WITHOUT wiring the LSP MCP (→ lsp-off A leg) and another that enables capture WITH LSP wiring (→ lsp-on B leg). Suggested shape: a workflow_dispatch input (with a matching repo-var default), e.g. lsp_pilot_variant: off | on | none — on runs setup-lsp-pilot (wires REVIEW_MCP_CONFIG) + capture; off runs capture only (skips setup-lsp-pilot, no REVIEW_MCP_CONFIG); none/unset = today's behaviour. Preserve the existing vars.LSP_PILOT_ENABLED meaning for anyone already using it.
  3. Both legs join. Dispatching the same PR twice (variant off, then on) must yield two lsp_pilot_run records with the same pr key and variants lsp-off / lsp-on, that scripts/lsp_pilot_compare.sh renders as an off-vs-on table.
  4. Off-pilot unchanged. With neither the variable nor the input set, pr-review.yml and the engine behave byte-for-byte as before — no stream capture, no records, no extra flags. The 5 consumer repos must be unaffected.
  5. Thin-caller forwarding. If a new dispatch input is added, forward it through pr-review-trigger.yml (the ring-0 trigger stub) within its allowed-input contract so the A/B can be driven on this repo's own PRs. Respect the thin-caller rules in AGENTS.md.
  6. Tests + hygiene. Coverage for the new plumbing/decoupling; shellcheck --severity=warning -x scripts/*.sh clean; pr-review.yml validates as YAML; existing test_engine_lsp_pilot / test_lsp_pilot_emit / test_lsp_pilot_measure suites stay green. Preserve all action/SHA pinning.

Out of scope

Done when

Dispatching the ring-0 pr-review on one PR with the pilot variant off then on drops two joinable lsp_pilot_run records (lsp-off + lsp-on) into their token-usage artifacts, and scripts/lsp_pilot_compare.sh renders a real off-vs-on table — no synthetic data and no manual env hacks.

Activity

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

    dev-leadFor dev-lead agent pickupenhancementFeature requests

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions