## Why
`install.sh` line 100 used `command -v claude || command -v codex` —
failing only when ZERO runtimes are present. Single-runtime users got
the warning skipped, then ran straight at the README mixed-model example
and hit failures. Council non-negotiable #3 + GOALS.md North Star line
13 ("install to first validated flow in under 5 minutes") both name
this. Codex auth model-mismatch (gpt-5.2-codex unsupported by ChatGPT
account) hit it for real earlier this session.
## What
Replace the single-line OR-detect with per-runtime detection:
```text
Detected Claude Code: yes/no. Detected Codex CLI: yes/no.
AgentOps will use [mixed-model | single-runtime] mode.
To unlock mixed-model judging, install [other]: [link]
```
Four cases handled:
- both present → mixed-model mode
- Claude only → single-runtime mode + Codex install link
- Codex only → single-runtime mode + Claude install link
- neither → existing warning preserved + both links
Total diff: 20 lines added, 5 changed in `scripts/install.sh`.
## Test
5 bats tests, all passing. Cover each runtime combination by stubbing
`claude` / `codex` / `curl` on PATH; assert detection lines + mode line
+ correct install link. Stub `curl` exits 1 so script bails at the
network step after the detection block runs, capturing the output we
want without touching the network.
Self-dogfood: re-run install.sh from this worktree → "Detected Claude
Code: yes. Detected Codex CLI: yes. AgentOps will use mixed-model mode."
## Acceptance
Per bead BDD: "Given a user with Claude Code installed but not Codex
CLI, When install.sh runs, Then output reads runtime-by-runtime
detection + mode + install-the-other one-liner. Install completes
without bouncing." ✓ (covered by test 2).
Closes-scenario: soc-vuu6.31#install-single-runtime
Bounded-context: BC5-Runtime
Evidence: scripts/install.sh
Evidence: tests/scripts/install-sh-runtime-detection.bats
Co-authored-by: Codex <codex@example.invalid>
## Summary
**Unblocks PRs #320 + #358 (and all future PRs)** by retiring the
now-meaningless `pre-push-gate-wired` CI check that PR #357 (soc-g2r9)
left dangling.
PR #357 removed the gate invocation from `.githooks/pre-push`, but I
missed that the matching CI check `pre-push-gate-wired` was still
asserting that invocation existed. Every PR since #357 fails on this
check. Caught by the cron-loop after observing both #320 and #358 fail
with identical FAILURE on `pre-push-gate-wired`.
This is exactly the kind of regression the soc-eqjd CI-side AP#7
enforcement (PR #358) would catch in the future — but soc-eqjd is itself
one of the blocked PRs, so we need this unblock first.
Closes: (partial — `soc-bbvw` kept open for remainder; this is the
minimum-CI-unblock subset)
## Fitness delta
- PRs blocked on `pre-push-gate-wired` regression: **2 (#320, #358) →
0** (target post-merge)
- CI jobs total: **66 → 65** (manifest + workflow + summary needs +
summary echo + AGENTS render all in lockstep)
- Lines deleted: **236** (199-line orphan script + 14-line orphan bats +
23 misc)
## What changes
| File | Change |
|---|---|
| `.github/workflows/validate.yml` | Remove `pre-push-gate-wired` job
block (13 lines); remove from `summary.needs`; remove summary echo |
| `docs/contracts/ci-jobs.yaml` | Remove `pre-push-gate-wired` manifest
entry |
| `AGENTS.md` | Auto-regen (65 → 64 rows) |
| `scripts/check-pre-push-gate-wired.sh` | **DELETE** (199 lines;
verified the now-removed gate chain) |
| `tests/scripts/check-pre-push-gate-wired.bats` | **DELETE** (14 lines;
tested the deleted script) |
| `scripts/install.sh` | Remove "Step 3/3: Verifying pre-push gate
wiring"; renumber to Step 1/2 + 2/2 |
## What's NOT in this PR (Wave 1 remainder)
Intentionally narrow scope. The following stay for a follow-up PR under
`soc-bbvw`:
- `scripts/pre-push-gate.sh` (2200+ lines; the gate body itself)
- `tests/scripts/pre-push-gate.bats` (55-test suite)
- The ~12 other gate-only `scripts/check-*.sh` helpers (need per-file
caller audit)
- `scripts/check-test-fixture-parity.sh` (asserts helper-stubs; needs
disposition decision)
Reason for splitting: those 14+ files have N callers each that need
audit. Three hours of risk vs. five minutes of unblock. Cheap fix first;
heavy sweep next.
## Sibling pattern
Job removal mirrors `scripts/add-validate-job.sh`'s 5-touchpoint
additive shape, run backwards: yaml manifest entry + validate.yml block
+ summary needs + summary echo + AGENTS render — all in lockstep.
## Verification
- `python3 -c "yaml.safe_load(...)"` on both yaml files: parses cleanly
- `scripts/generate-ci-jobs-table.sh --check`: PASS (64 rows)
- `shellcheck scripts/install.sh`: clean
- No remaining `check-pre-push-gate-wired` references outside this PR's
diff (grep audit)
## Why this PR fires the cron-loop's value
This is the second self-correction PR I've shipped in this session — the
first (PR #356, soc-o5kq) added AP#7 as documentation; this one fixes a
regression I introduced one PR ago. The mechanical AP#7 check landing in
PR #358 will catch this exact failure mode going forward. Until then,
the human-in-the-loop (operator's cron-loop nudging me to check PR
status) caught it.
Discovered-from: soc-g2r9
Bounded-context: BC0-foundations (CI gate retirement, Wave 1 minimum
subset)
Evidence: shellcheck
Co-authored-by: Codex <codex@example.invalid>
The install script was copying skills to ~/.claude/skills/ which is wrong.
Claude Code users get skills through the plugin system. This script
should only install the Codex plugin.