All notable changes to this project will be documented in this file.
All 10 pi- provider prompts rewritten around three system-wide contracts: a one-shot turn contract (state assumptions instead of asking — headless CLI calls have no second round), per-skill output budgets, and a text-based severity/verdict format replacing emoji + 1-10 scores.* The execution layers (dispatch rules, timeouts, fallbacks) are untouched; this release changes only what travels to Codex/Gemini and the few presentation-layer lines that consume it.
- One-shot turn contract — every provider prompt now opens with "You get exactly one turn: do not ask clarifying questions; state your assumptions and answer anyway", with per-skill adaptations (pi-fact-check: state your reading of an ambiguous claim and check that reading; pi-ui-design: mark design assumptions as
<!-- ASSUMPTION: ... -->HTML comments that Claude's post-processing audits back to the user) - Text severity tags + verdict replace emoji + 1-10 score — review prompts (pi-code-review / pi-multi-review / pi-ui-review) request
[CRITICAL|MEDIUM|SUGGESTION]line prefixes and a closingVERDICT:line (safe | needs-fixes | do-not-merge; pi-ui-review usesready | needs-fixes | not-readysince it reviews files, not merges). Emoji rendering moves to Claude's presentation layer (CRITICAL→🔴 etc.), so user-facing output is unchanged; the insights-log severity mapping becomes a direct text-tag pass-through. The 1-10 overall score is removed — it had no downstream consumer in single-provider reviews, and cross-model score comparison was false precision. pi-multi-review's Score Comparison table becomes Verdict Comparison, with a verdict split called out as a real signal - Structured finding blocks — the finding-bar questions become output fields (Failure scenario / Impact / Fix — pi-ui-review: User impact / Standard / Fix), capped at 8 findings per provider with an anti-padding rule ("say VERDICT: safe directly — do not invent findings to seem thorough")
- Per-skill length budgets — pi-askall and pi-plan capped at ~800 words with strongest-points-first guidance; search-class prompts get density rules instead of hard caps
- Uniform stdin transport — pi-code-review / pi-ui-review / pi-research / pi-ui-design switch from arg-embedded prompts (with a >3000-char stdin escape hatch) to the temp-file + stdin shape already used by pi-askall / pi-plan / pi-multi-review; the CLI argument is now always a short label. Closes the remaining ARG_MAX exposure — guideline blocks (
CLAUDE.md) expanded into argv unboundedly
- pi-ask-codex / pi-ask-gemini — raw
$ARGUMENTSforwarding replaced with a thin framing: one-shot contract + "lead with your answer, then reasoning; be concise by default". No role-play, no format demands — user-authored prompts pass through unpolluted - pi-askall — framing gains a clear-position requirement ("if your answer is 'it depends', name the deciding factors and commit to a recommendation") so synthesis has real divergence to compare instead of two hedges
- pi-plan — architect prompt restructured under fixed headings (Assumptions / Challenges / Recommendation / Rejected alternative / Risks / Complexity) so the two providers' answers align for synthesis; "at least one rejected alternative" upgraded to "the strongest alternative you rejected" with an honest exit ("if no serious alternative exists, say so") — anti-strawman; risks must name the concrete scenario in which they bite; a >1-step complexity split between providers is now a documented synthesis signal, recorded in the plan file's new Metadata Complexity line
- pi-multi-review — Gemini's attack surface is domain-aware:
backenddiffs (per Step 2.5 detection) drop the accessibility/responsive item instead of inviting forced findings; both prompts gain "skip attack surfaces that do not apply to this diff" - pi-ui-review — WCAG 2.1 → 2.2 AA; the prompt now explicitly requests specific success-criterion citations (e.g., WCAG 2.4.7), aligning the upstream ask with the downstream +20 confidence factor that already scored them; decorative emoji dropped from the focus list
- pi-fact-check — Step 2's existing impact assessment now travels:
[HIGH-IMPACT]claim markers direct deeper multi-angle search before settling on UNVERIFIABLE; key findings quote the source's own sentence where possible (strengthens Step 4.5 content-match validation);Today is <date>injected (agy date awareness not guaranteed); batch=2 annotated as pre-agy tuning pending re-measurement - pi-research — new strict anti-hallucination block: never construct/complete/guess URLs; claims from training data must be marked
[KNOWLEDGE]; version/release-date/breaking-change claims must quote the exact source sentence or be marked[LOW-CONFIDENCE](a fabricated quote+URL pair is far harder to produce than a plausible paraphrase). New Step 4.5 source validation ported from pi-fact-check: up to 5 Gemini-sourced URLs WebFetch-verified before synthesis, quote-existence checked, >50% failure poisons all unsampled Gemini URLs to(unverified). Multi-angle search directive replaces bare "in-depth research"; solution-comparison framing relaxed for non-selection topics; date injection - pi-ui-design — Tailwind CSS v3 Play CDN (
cdn.tailwindcss.com) → v4 browser CDN (cdn.jsdelivr.net/npm/@tailwindcss/browser@4) with@themeCSS-first config written into the prompt (v4 has no JS config object — the old<script>extend block was v3-only); WCAG 2.2 AA baseline requirements (alt text, form labels, focus states, contrast); viewport meta made explicit; output-purity rule (HTML only, starting at<!DOCTYPE html>, no fences); Claude post-processing extended to v3-era class renames and the ASSUMPTION-comment audit; spec-generation prompt capped at one page
- README.md + README.zh-TW.md — FAQ format-fallback answer updated from emoji/score to severity-tag/verdict wording; pi-ui-design description notes Tailwind v4
- checksums.sha256 — regenerated for all 10 command files
scripts/call-gemini.sh— prompt delivery migrated from stdin pipe to-parg — agy 1.1.2 changed-psemantics: the flag value is now treated as the prompt directly and stdin is ignored. Prompt delivery changed fromprintf '%s' "$PROMPT" | agy -p " "toagy -p "$PROMPT" < /dev/null. The< /dev/nullisolates stdin so agy does not hang on inherited non-EOF file descriptors from Claude Code subshells.call-codex.shis unaffected (codex usesprintf | codex exec ... -stdin pipe)README.md+README.zh-TW.md— model examples updated to agy display-name format — agy 1.1.2 model catalog uses display names with spaces and parentheses (e.g.Gemini 3.5 Flash (Medium)) instead of slugs (gemini-3-flash-preview). Environment variable table, shell profile examples, FAQ, and per-invocation-mexamples all updated;agy models/codex doctorhints addedscripts/call-gemini.sh+scripts/call-codex.sh— "Keep in sync" annotations updated — exec block comments now document the prompt delivery divergence (gemini:-parg; codex: stdin pipe) while noting that remaining blocks (timeout/heartbeat/first-byte/OUT_TMP) still mirror
scripts/call-gemini.sh— ARG_MAX 120KB size guard —-p "$PROMPT"is subject to OSexecvelimits (macOS ~1MB, Linux ~128KB per-arg). Guard at 120,000 bytes fires before exec with structuredPROMPT_TOO_LARGEerror + log. No workaround until agy adds--prompt-fileor stdin mode.call-codex.shunaffected (stdin pipe has no ARG_MAX limit)
The Gemini provider's call-gemini.sh now drives agy (Antigravity CLI) over Google AI Pro OAuth, shipped on the June 18, 2026 @google/gemini-cli sunset date. The wrapper keeps its filename and [gemini] log tag for log-contract continuity, and adds rc=0 content classification to catch agy's silent network/auth failures (empirically verified against agy 1.0.6–1.0.9). This release also wires the full 62-scenario smoke suite into CI behind a tag/package.json version-sync gate, and bundles the pi-plan synthesis checkpoint + conflict-resolution mechanisms adapted from compound-engineering's ce-plan.
scripts/call-gemini.shmigrated from Gemini CLI to agy (Antigravity CLI) (1617e14) — ahead of the 2026-06-18@google/gemini-clisunset. Binary resolveagy+AGY_BINenv (GEMINI_BINhonored as deprecated fallback with WARN); model flag-m→--modelpassthrough;--print-timeout TIMEOUT_S+30skeeps the wrapper soft-timeout firing first. New rc=0 content classification: agy 1.0.6/1.0.7 swallow network failures (rc=0, empty output) and auth failures (rc=0, OAuth prompt on stdout) — classified asEMPTY_OUTPUT/AUTH_ERRORfrom output content (empirically verified 2026-06-10). Smoke E1-E7 all pass on agy 1.0.7. Filename and[gemini]log tag kept for log-contract continuityREADME.md+README.zh-TW.mdsynced to the completed agy migration — Prerequisites table now installs Antigravity CLI (curl -fsSL https://antigravity.google/cli/install.sh | bash) instead of the sunset@google/gemini-cli; the two pre-migration notice blocks (2026-03-25 routing update, 2026-05-19 "migration under evaluation" transition notice) replaced by a single completed-migration block stating what stays (script name,[gemini]log tag,GEMINI_MODEL) and what changed (OAuth-only auth,AGY_BINwithGEMINI_BINas deprecated alias). Environment-variable table dropsGEMINI_API_KEY(no longer read by the wrapper) and documentsAGY_BIN/ deprecatedGEMINI_BIN; FAQ slow-response entry now covers agy's rc=0 empty-output auth symptom; architecture diagram, Tech Stack, and Project Structure labels updated from "Gemini CLI" to "agy (Antigravity CLI)"
.github/workflows/smoke-test.yml— new workflow running the fulltests/smoke-test.shsuite (62 scenarios) on every PR and push tomain. The suite was CI-ready by design (wrapper logic tests inject fake binaries viaCODEX_BIN/AGY_BIN; CLI availability checks degrade to SKIP — verified 58 pass / 0 fail / 3 skip in a clean no-CLI environment) but had never been wired into CI:release.yml's "smoke test" step was a file-existence loop only, so logic regressions (timeout layers, log rotation, classifiers) could reach a release undetectedrelease.yml— real smoke tests + tag/package.json version sync gate — the file-existence loop is replaced by./tests/smoke-test.sh(file presence remains covered by the checksum verify + tarball steps), and a new step fails the release when the pushed tag does not matchpackage.jsonversion, closing the third same-shape manual-sync gap (after the two checksum regeneration misses)
commands/pi-plan.md— synthesis checkpoint + conflict resolution (a650072) — three mechanisms adapted from compound-engineering's ce-plan, scoped to pi-plan's cost structure (external provider calls run 1–9 minutes, so misread tasks are expensive):- Step 3.5 synthesis checkpoint — Stated / Inferred / Out-of-scope bucketing before provider dispatch; pauses for user confirmation only when an Inferred assumption would change the prompt's direction (max 3 call-outs, each judgeable without reading code)
- Architect prompt requires a rejected alternative with reasoning — synthesis can tell genuine agreement from coincidence; providers that omit it count as unreasoned agreement (weaker signal)
- Step 6 conflict resolution principles — repo-grounded beats generic, official docs beat speculation, agreement must be reasoned. Plan template gains an as-needed Out of Scope section
commands/pi-research.md— divergence ruling in merge rules (a650072) — official sources beat secondary commentary; version / breaking-change / API-stability claims require cross-verification against an official source before being reported as fact, else marked (unverified)
- EMPTY_OUTPUT classifier alignment across docs (
a528d5a) — the agy migration addedEMPTY_OUTPUTtocall-gemini.shbut onlypi-ask-gemini.mdmentioned it. Aligned the remaining six command docs (pi-plan / pi-askall / pi-multi-review / pi-research / pi-ui-review / pi-ui-design) and the README graceful-degradation lists;checksums.sha256regenerated. Codex-only lists untouched (call-codex.shhas noEMPTY_OUTPUT)
Tri-state first_byte_method field (measured / fallback / na) shipped to forensic log lines, letting downstream consumers mechanically filter race-fallback samples before treating first_byte_ms as a latency signal. Bundled with the supply-chain hardening that landed on main between releases (third-party GitHub Actions immutable-SHA-pinned + Dependabot enabled), a per-skill timeout calibrator (scripts/calibrate-timeout.sh), and an Antigravity CLI transition notice pre-disclosed in Prerequisites ahead of the June 18, 2026 Gemini CLI cutoff.
scripts/call-codex.sh+scripts/call-gemini.sh— per-invocation detector subshell polls$OUT_TMPand writes the unix-ts to a marker file on first non-empty observation. Main shell reads the marker afterwaitto computefirst_byte_msand emit a three-statefirst_byte_methodfield in bothsuccessandsoft_timeoutend-log lines:measured— detector observed the first byte mid-stream;first_byte_msis the true upstream first-byte arrival timefallback— wrapper finished too fast for the 1s detector poll (race fallback);first_byte_mscarries an end-time approximation, not first-byte time. Downstream stats consumers must filter these out before computing latency percentilesna— output never arrived (pure stall / Mode A);first_byte_msisNA
_first_byte_meta()helper — dual-global assignment (FIRST_BYTE_MS+FIRST_BYTE_METHOD) on every codepath, no fallthrough. Detector subshell + helper both gate on[[ -f && -s ]](different times, different invariants — load-bearing semantic duplication)- Security hardening (OWASP A08 + AI-vuln #13, Medium) — TOCTOU symlink race between
mktempreturn and detector's first write closed. Bash>callsopen(2)withoutO_NOFOLLOW, so a swap-by-symlink in a world-writable TMPDIR would redirect writes to an attacker-chosen path. Mitigated by replacing per-filemktemp ... claude-prism-first-byte.XXXXXXwith per-dirmktemp -d ... claude-prism-fb.XXXXXX(mode 0700) + fixed/tsinside. Sticky-bit/tmp+ 0700 dir blocks other-user unlink, and the marker file does not exist until the detector writes it (no pre-existing file to swap)
- Per-skill timeout calibrator — reads
~/.claude/logs/multi-ai-YYYY-MM.log(cross-month, excludes symlink / archive), computes per-skill p99 / median / suggested timeout with class-aware clamping. Class mapping frozen from v0.14.4 + commit71f997d: heavy class (pi-askall,pi-fact-check,pi-plan,pi-multi-review,pi-code-review) floor 480s / ceiling 540s; small class (pi-ask-codex,pi-ask-gemini,pi-research,pi-ui-design,pi-ui-review) floor 240s / ceiling 300s - Formula:
clamp(floor, ceiling, ceil(p99 × 1.15 / 10) × 10).N<5sticks with current (low-confidence guard); ERROR pids excluded - Default reports only;
--applyupdatescommands/pi-*.mdTIMEOUTin place. Uses only macOS built-ins (grep/awk/sort/mktemp/shopt) — nojq/python
- All
.github/workflows/*.yml(PR #4bf9843e) — third-party actions migrated from mutable tags (@v5,@2.0.0) to immutable 40-char SHA pin formatowner/action@<sha> # vX.Y.Z(SHA is the source of truth; version comment is for humans). Affected:actions/checkout(4 workflows),actions/setup-node(1 workflow),ludeeus/action-shellcheck(1 workflow). Mitigates supply-chain risks like the Mini Shai-Hulud-class mutable-tag retag attacks .github/dependabot.yml(PR #4) — new file enabling Dependabot version updates for thegithub-actionsecosystem, weekly schedule, root directory. PR-based human review remains the merge gateactions/checkoutv5.0.1 → v6.0.2(PR #5fe3539e, Dependabot-generated) — 4 workflow files. v6 breaking change: persist-credentials store path moved to$RUNNER_TEMP. Prism workflows do not perform post-checkout credential operations, so no breaking impactactions/setup-nodev5.0.0 → v6.4.0(PR #672aedd5, Dependabot-generated) —release.ymlonly. v6 breaking change:devEngines.runtimenow preferred overengines.nodefornode-version-file. Prism uses explicitnode-version: '24', so no breaking impact
README.md+README.zh-TW.md— Antigravity CLI transition notice block in Quick Start → Prerequisites, immediately following the existing March 25, 2026 Gemini CLI service update warning. Discloses: (a) Gemini CLI cutoff date 2026-06-18 for AI Pro / Ultra / free Code Assist users (Enterprise license unaffected); (b) claude-prism wrappers remain functional through the cutoff; (c) Antigravity CLI (agy) ships as a TUI — currentcall-gemini.shstdin-pipe + stdout-capture pattern is not compatible; (d) migration paths under evaluation (wait foragyheadless flag / switch to Gemini API HTTP / deprecate gemini provider), evaluation kicks off the week of 2026-05-25. Sources: Google Developers Blog transition post + Antigravity CLI repo- Pattern rationale: surfaces the change inline where users actually look for Gemini CLI install instructions, not buried in a separate migration doc
- ShellCheck SC2206 in
scripts/calibrate-timeout.sh(8d05960) —LOG_FILES=( $LOG_GLOB )pattern intentionally relies on word splitting + globbing (guarded byshopt -s nullglob). Marked with# shellcheck disable=SC2206 # intentional glob expansion; nullglob handles no-match caseso CI stops flagging - Dead
FIRST_BYTE_MS=""/FIRST_BYTE_METHOD=""pre-assignments before_first_byte_meta()(013ac19) — helper assigns both globals unconditionally on every codepath, so the paranoia init was dead writes. Cleaned up across both wrappers - Smoke
T14.3regex tighten (013ac19) —first_byte_ms=[A-Za-z0-9]+→first_byte_ms=(NA|[0-9]+). Old class silently passed drift values likeInf/null/aBc123; new pattern enforces the actual contract (numeric integer OR literalNA)
tests/smoke-test.sh— T14.3 + T14.4 upgraded to tri-state regex; T16.1-T16.7 added (short-success / long-success / pure stall / mid-stall / gemini mirror / marker cleanup contract / vocab strictness). 51 → 60 tests, all pass- ShellCheck CI green at
3f748fa(run26105637358, 17s)
- Phase A2 detector subshell is patch-isomorphic with the v0.14.0 six-layer soft-timeout defense (provider-string differences only between
call-codex.shandcall-gemini.sh). The byte-sync wrapper invariant from v0.14.x is preserved - Phase A3 deferred — race-fallback ms-precision improvements wait until real-CLI tri-state distribution data accumulates (
first_byte_method=measuredproportion vsfallbackvsna)
v0.14.5 (2026-05-11) — codex-cli 0.130.0 sandbox interface drift fix + small-skill timeout calibration
Resolves a 0-second failure in pi-* skills when invoked from non-git-repo working directories. codex-cli 0.130.0 dropped none from --sandbox <SANDBOX_MODE>'s [possible values] list and added an independent "trusted directory" check that refuses to run outside a git repo for any sandbox mode unless --skip-git-repo-check is passed. The wrapper's legacy read-only → none downgrade path produced invalid value 'none' for '--sandbox' and exited at argument validation — silently breaking pi-askall etc. when cwd was /tmp or any other non-repo directory. Bundled with three accumulated timeout calibration fixes since v0.14.4.
scripts/call-codex.sh— replace sandbox-value downgrade with--skip-git-repo-checkflag. IntroduceSKIP_GIT_CHECK=falsedefault; thegit_checkblock now setsSKIP_GIT_CHECK=true(instead of mutatingSANDBOX), and the codexexeccommand conditionally appends the flag. Sandbox staysread-only(preserves Q&A intent — no writes); the new flag solves the trusted-directory check independently--sandboxvalidator + diag — valid-list realigned to codex 0.130.0 (read-only | workspace-write | danger-full-access). Previousread-only | sandbox | nonehad all three values drifted from the actual CLI surface.SANDBOXerror diagnostic now suggests--sandbox workspace-write for Q&Ainstead of the invalidnone- Log schema —
invokeline gainsskip_git_check=$SKIP_GIT_CHECKfield for forensic attribution of which path the wrapper took per call
CLAUDE_PRISM_CALLERexport across all 13 wrapper invocations (commit71f997d) — v0.14.4 added wrapper-side read but skill-side export was missed; 3-day log analysis (35 invokes, 100%caller="unknown", 4 soft_timeout) surfaced the gap. Future grep can now partition per-skill p99- Per-skill
CLAUDE_PRISM_TIMEOUTsplit (commit71f997d) — empirical p99=255s on 44 v0.14.4-onward successes means ~36% of real invocations need >110s; all 4 observed soft_timeouts sat on small skills inheriting the 110s default. Split: 7 small-Q&A skills → 300s (p99=255s + 18% buffer); 3 heavy skills (pi-plan,pi-multi-review,pi-code-review) keep 540s pi-askall+pi-fact-checkpromoted 300s → 540s (commit6de0666) — both run multi-batch / multi-provider workloads where individual calls already approach 300s on real traffic. Aligned with the three heavy skillspi-research+pi-fact-checkBash tool timeout aligned to 600000ms (commit0b95f7a) — body text had drifted to obsolete 90s/90000ms, shorter than the innerCLAUDE_PRISM_TIMEOUT(300/540), which would hard-kill before the wrapper soft-timeout could fire a structured error
tests/smoke-test.shTest 11 rewritten — drift-proof. The prior assertion greppedsandbox downgraded to 'none'in dry-run output, treating the wrapper-internal string as spec while silently masking the actual bug (codex CLI rejectingnone). New form asserts (a)--skip-git-repo-checkappears in dry-run output, and (b) wrapper's--sandbox <value>is incodex exec --help's[possible values: ...]list. The (b) assertion catches future codex CLI rename / removal of sandbox modes that would otherwise reproduce this class of silent breakage- All 53 smoke tests pass; shellcheck clean on wrappers
- End-to-end verified:
cd /tmp && call-codex.sh "..."now returns real codex response (previously 0-secondinvalid value 'none'exit at arg validation)
- Root cause + L4 reflection stored to ccRecall (#117, discovery) — wrapper-layer hardcode of external CLI sub-parameter values (vs flag names) is a structural drift risk.
call-gemini.shescaped only because Gemini has no equivalent sub-mode concept. Future wrappers that hardcode external CLI sub-values must pair a drift-proof smoke check - No new feature: patch release. The four bundled fixes are all bug-class — sandbox interface drift, missing caller export, undersized small-skill timeout, drifted Bash-tool timeout
Forensic-level observability for silent-kill diagnosis, automatic monthly log rotation, and a CLAUDE_PRISM_TIMEOUT=540 default for review/plan sub-agent skills. Solves the "wrapper SIGKILL leaves no trace" blindness from the Claude Code 2026-04+ auto-background regression by recording per-invocation cwd / caller / cc_ver plus 30-second heartbeats so the last alive line approximates the death moment when the EXIT trap can't run.
scripts/call-codex.sh/scripts/call-gemini.sh—invokeline gainscaller="..."(envCLAUDE_PRISM_CALLER),cwd="..."(sanitized viatr -d '\n"'to defend against log injection / quote escape), andcc_ver="..."(read from harness-providedAI_AGENTenv-var;unknownoutside Claude Code) fields. Enables per-project / per-session attribution that the previous single-lineinvoke ppid=N stage=entrycouldn't provide- 30s heartbeat subshell writes
[DEBUG] [pid=N] alive elapsed_s=N bytes=Nlines while the wrapper pipeline runs. Two diagnostic purposes:- Stall onset detection —
bytescount per heartbeat reveals where the upstream froze (e.g. bytes stuck at N for 60s = stalled at second 30) - Silent-kill death-time estimate — when Claude Code SIGKILLs the wrapper (uncatchable, EXIT trap doesn't run, no
success/soft_timeout/ signal log), the last heartbeat ≈ death moment within ±30s
- Stall onset detection —
- DEBUG level keeps heartbeat out of default
grep -E '\[(INFO|WARN|ERROR)\]'view; forensic queries usegrep 'pid=N' multi-ai*.logfor full timeline - EXIT trap kills the heartbeat subshell PID (no orphan process; ad-hoc verified post-timeout)
success/soft_timeoutERROR end lines gainelapsed_s=N+first_byte_ms=NAplaceholder. Realfirst_byte_mstracking deferred to Phase A2 (requires watcher refactor for byte-level stream sampling)
scripts/call-codex.sh/scripts/call-gemini.sh— write tomulti-ai-YYYY-MM.log(UTC month) instead of singlemulti-ai.log. Year-scale storage scaling: 472KB / 2 months → ~10-15 MB/year split across 12 filesmulti-ai.logbecomes a symlink to current month soanalyze-log.sh/usage-summary.sh/ external greppers see "latest view" transparently with no tool changes- One-time migration on first run: pre-rotation regular file archives as
multi-ai-archive-pre-rotation.logviamv -n(BSD-safe; concurrent wrappers race-losing see no-op since source already moved). Symlink atomic vialn -sf(POSIX rename). Production migration verified during dev cycle: 485KB pre-rotation log preserved intact, no data loss - Historical query:
grep ... ~/.claude/logs/multi-ai-*.logglob
commands/pi-plan.md/pi-multi-review.md/pi-code-review.md— sub-agent / direct call gainsCLAUDE_PRISM_TIMEOUT=540env-var prefix on~/.claude/scripts/call-codex.shinvocation. 60s buffer below the documented Bash tool 600s ceiling so wrapper soft-timeout fires first (preserving structuredrc=124+ sentinel +soft_timeoutlog event) before the harness force-kills. Real-world trigger: pi-plan elapsed 6m 2s (362s, > previous 110s wrapper default) on 2026-04-29 confirmed the 110s default was systematically too tight for adversarial review / architectural plan workloads- Inline rationale comment above each invocation explaining
540 vs 600semantics +Keep in sync: pi-plan.md, pi-multi-review.md, pi-code-review.mdmarker (mirrors v0.12.6 wrapper byte-sync convention so future maintainers can't drift one file independently) - Not changed:
pi-askall.md(Q&A simple-query workload dominant; 110s default appropriate; sync marker explicitly excludes per design decision).pi-research.mdhas a separate Bash-tool-sidetimeout=90000conflict (90s outer < 110s inner) — left for a separate fix
scripts/usage-summary.sh—set -e + pipefailwas killing the sum pipeline whenLINESlacked a provider tag (firstgrep '\[gemini\]'rc=1 on no match → pipefail propagates →set -eexits with no output). Disabled pipefail in the sum section;awk's END always prints0so missing matches naturally yield 0. Latent bug since pipefail was added; revealed byT6LOG_DIR isolation refactor (rotation made the prod log a symlink to a fresh empty month file, exposing the[gemini]-absent code path)
- Smoke 43 → 51 (+8 cases):
T14.1-T14.4(Phase A1 observability): codex/gemini invoke fields + success-lineelapsed_s+first_byte_msend fields + soft_timeout ERRORfirst_byte_msT15.1-T15.4(Phase B rotation): fresh-dir creation, archive migration of pre-existing regular file, re-run idempotency (no double-archive), gemini wrapper mirrors codexT6refactor: isolated LOG_DIR + fake-fast CLI to make usage-summary deterministic post-rotation
- All 51 pass; shellcheck clean on all wrappers
- /gogo quality pipeline ran clean before tag (Step 1 codex review: 1 finding, score 100, fixed; Step 2 simplify: 1 item, fixed; Step 3 security: 0 ≥Medium; Step 4 final verify: PASS)
- Caller env-var contract:
CLAUDE_PRISM_CALLERis optional; sub-agent skills should set it tosub-agent(or descriptive label) so log forensics can distinguish direct main-conversation Bash vs sub-agent fan-out paths. Current sub-agent templates do not yet propagate this — future enhancement - Migration is idempotent: re-running wrappers after upgrade leaves the archive file untouched (
mv -nno-ops once source is gone) and keeps refreshing the symlink to current month. Cross-month transitions (e.g. May 1) automatically create the new month file and update the symlink
Resolves v0.14.2 Known Limitation for sub-agent fan-out skills. Callers (skill layer) pre-allocate a mktemp path via CLAUDE_PRISM_OUT_TMP env-var; the wrapper writes directly to that path and the shared pi-{codex,gemini}-last.out symlink is not updated (legacy-mode only). Skill-side fallback now reads the caller-owned path — no cross-session race. Known Limitation partially preserved: the 7 direct skills (pi-ask-codex, pi-ask-gemini, pi-code-review, pi-fact-check, pi-research, pi-ui-design, pi-ui-review) keep the shared-symlink legacy fallback in their narrative instructions. Low-frequency silent-hallucination risk (no cross-provider verification safety net in direct skills) — not rewritten because the 7-skill narrative-update cost was disproportionate to an unobserved-in-production risk.
scripts/call-codex.sh/scripts/call-gemini.sh—OUT_TMPacceptsCLAUDE_PRISM_OUT_TMPenv-var override (defaults tomktempinLOG_DIRif unset). Symlink update wrapped inif [ -z "${CLAUDE_PRISM_OUT_TMP:-}" ]: legacy mode preserves v0.14.2 behavior; env-var mode skips symlink since the caller owns the path. Byte-sync contract between the two scripts preservedcommands/pi-askall.md/pi-plan.md/pi-multi-review.md— sub-agent Bash template creates per-invocationOUT_PATH=$(mktemp "${TMPDIR:-/tmp}/prism-{codex,gemini}-out-XXXXXX")and prefixes wrapper call withCLAUDE_PRISM_OUT_TMP="$OUT_PATH". Fallbackcatreads$OUT_PATH, not the shared symlink. Gemini substitution list gains a new rule: replaceprism-codex-out→prism-gemini-outin themktemptemplate- Explicit
/separator in${TMPDIR:-/tmp}/prism-...— mirrors wrapper's${TMPDIR:-/tmp}/claude-prism-timeout.XXXXXXpattern. Avoids malformed paths on systems where$TMPDIRhas no trailing/
- Eliminates cross-session same-provider fallback wrong-file selection for sub-agent fan-out skills. v0.14.2 behavior: concurrent same-provider invocations each own a
mktempfile but share one symlink; if Claude Code auto-bg silences stdout and a skill falls back tocat-ing the symlink, it may read another session's output. Now: sub-agent skills pass their ownmktemppath via env-var; wrapper writes there directly; skill reads its own file - Preserved Known Limitation — direct skills' narrative fallback ("If Bash returns empty, read
pi-{codex,gemini}-last.out") still uses the shared symlink. Two concurrent Claude Code sessions using the same direct skill on the same provider can theoretically cross-read. Low-frequency (requires auto-bg + empty-stdout + same-provider + time overlap); unlikepi-multi-review, direct skills have no cross-provider verification (references_exist_in_codebase-50pt signal) to catch hallucinated references from wrong-file content
scripts/call-codex.sh/scripts/call-gemini.sh— soft-timeoutERRORlog line gains anoutput_bytes=Nfield.0distinguishes upstream stall (no byte received before kill) from>0slow-but-progressing — enables triage between transient codex/OpenAI/network stall and structural latency issues without re-running the same prompt. Computed aswc -c < "$OUT_TMP"guarded by[ -f ](rejects FIFO / device / blocking-symlink paths that a Phase 2 env-var caller could supply, which would otherwise re-hang the wrapper at the diagnostic step).tr -d ' \n'sanitization closes OWASP A09 log-injection vector (BSDwcmay emit leading\n; matches existingerr_text_safeprior art elsewhere in the same file)
internal/experiments/phase2-cross-session-race/run.sh— fake-CLI harness (fake-codex,fake-gemini) + 2 race scenarios (same-session concurrent + cross-session concurrent) × 2 providers × 2 Bash versions (5.3.9 Homebrew + 3.2.57 macOS system). All 32 assertions pass:OUT_AandOUT_Bget separate non-empty distinct content; shared symlink is not created in env-var mode ([ -z ... ]gate honored)- Smoke suite unchanged at 43/43 passing;
scripts/call-{codex,gemini}.shshellcheck clean - Observability patch validation: FIFO smoke (caller supplies
mkfifopath → wrapper completes in 2.5s, log writesoutput_bytes=0, no read-block) + full /gogo quality pipeline (codex review → simplify → security lint → final verify) ran clean before tag
- Release policy exception: shipped 2026-04-28 instead of the originally communicated ≥ 2026-05-01 target. Bundled with
output_bytesobservability patch (single soak window covers both) - BSD
mktemp -tquirk discovered in precheck:mktemp -t <prefix>on BSD leavesXXXXXXas literal, not a placeholder (producesprism-test-XXXXXX.RANDOM). Sibling skills (pre-Phase 2) use this form with literalXXXXXXin filenames as a known quirk; Phase 2 sidesteps this withmktemp "${TMPDIR:-/tmp}/prefix-XXXXXX"absolute-template form (XXXXXX replaced correctly) - Not changed: wrapper's EXIT trap (still doesn't
rm "$OUT_TMP"— contract strengthens in env-var mode since the path is caller-owned). Legacy-mode symlink behavior unchanged when env-var unset
Wrapper: per-invocation OUT_TMP + atomic symlink. Eliminates byte-level tee interleaving on the safety-net log file (pre-existing MEDIUM-severity finding). When two sub-agents or two Claude Code sessions invoke the same provider simultaneously, each gets its own mktemp-named output file; pi-{codex,gemini}-last.out becomes an atomic symlink to the latest invocation. The 10 pi-* skills are unchanged — the symlink is transparent to cat. Known limitation: this fix closes byte-level corruption; it does not solve fallback file-selection under concurrent same-provider invocation — the shared pi-*-last.out symlink still points to the last writer, so a skill that falls back to cat it may read another concurrent invocation's response. See Notes for the deferred env-var OUT_TMP contract that resolves this.
scripts/call-codex.sh/scripts/call-gemini.sh—OUT_TMPnow points to a per-invocationmktemp "${LOG_DIR}/pi-{codex,gemini}-last-XXXXXX"file. Afterwait "$LAST"completes,ln -sf "$(basename "$OUT_TMP")" "${LOG_DIR}/pi-{codex,gemini}-last.out"atomically updates the stable path to the newest file. Theln -sfruns afterwait(so the target is fully written) and is not conditioned onrc— partial output from soft-timeout or error paths still reaches the skill diagnostic fallback. Byte-sync mirror between the two scripts preserved; Keep-in-sync comment extended to cover the new block
- Eliminates byte-level
teeinterleaving (MEDIUM-severity finding). Prior behavior: concurrent writers to the fixed path~/.claude/logs/pi-{codex,gemini}-last.outinterleaved at the byte level insidetee, corrupting any skill fallback that reads the file after the wrapper exits. The race was latent under v0.12.x because main-conversation Bash is a structural FIFO (empirically N=7, ratio 1.00, zero variance). v0.13.0 sub-agent fan-out introduced genuine parallelism (N=13, median dispatch delta 2.8s), activating the race pathway. After this change, each concurrent invocation owns its ownmktempfile; byte-level interleaving is impossible - Remaining exposure — cross-session same-provider fallback file-selection: the
pi-{codex,gemini}-last.outsymlink is a single stable pointer, "lastln -sfwins". If two Claude Code sessions on the same machine both invoke the same provider and one of them triggers the empty-stdout fallback, it maycatthe symlink and read the other session's response. Frequency is low (requires cross-session + same-provider + empty-stdout concurrently) but non-zero. Mitigation before env-var contract ships: avoid running two Claude Code instances that concurrently use the same provider for unrelated tasks, or rely on sub-agent output fields rather than re-reading the symlink
- Race-regression test — two parallel invocations under controlled fake-CLI fixtures on both Bash 5.3.9 (Homebrew) and Bash 3.2.57 (macOS system), both scripts. All four combinations verified to produce uncorrupted per-file output (exactly one BEGIN/END marker per file) with symlink pointing to a complete file. Test script resides under developer
/tmp/(not shipped — requires fake-CLI injection and a throwaway log dir) - Existing smoke suite unchanged at 43/43 passing. Test 13 soft-timeout regression (6 cases) verified to still pass —
ln -sfis placed afterwaitand before classification, so timeout path still writes the symlink before exiting 124
- Backward-compatible: the 10
pi-*skill fallback reads (cat ~/.claude/logs/pi-{codex,gemini}-last.out) transparently follow the symlink. No skill markdown files changed - Not addressed (deferred): same-provider 3+ fan-out within a single skill. The symlink-points-to-latest model is non-deterministic under 3+ concurrent same-provider invocations. Today's pi-* skills all use 1 Codex + 1 Gemini pairs; when a real 3+ fan-out pattern emerges, migration is an env-var
OUT_TMPpath-return contract (caller setsOUT_TMP, wrapper respects it, skill reads that specific path). Out of scope for this release - BSD
mktemptemplate:XXXXXXat end of template, no suffix. Matches the pre-existing verified pattern forTIMEOUT_MARKERincall-*.sh - Cleanup of stale
pi-*-last-*files is deferred — text logs are ~1–100 KB each; 50 calls/day = ~5 MB/day is not a storage problem. If needed later, cleanup will anchor toinstall.shupgrade rather than a hot-pathfindon every wrapper invocation
Documentation restructure. Split the 798-line README into a leaner 550-line entry point plus a docs/ tree for deep-dive topics, and surface the empirical research behind the sub-agent fan-out design.
## Empirical Foundationsection in both README variants (~80 lines). Summarizes the N=36+ controlled experiments that identified Claude Code's main-conversation Bash tool as a structural FIFO queue (delta/first_exec = 1.00across 7 runs in two capacity windows) while sub-agent Bash is genuinely parallel (median dispatch delta 2.8s, N=13). Includes a MECE layer behavior matrix and a sequenceDiagram contrasting the anti-pattern vs the sub-agent fan-out designdocs/research/bash-tool-parallelism.md(English, 102-line research summary). Publishes the experiment groups (A/B/C/F/D), the resulting layered conclusions, and the product decisions traced back to the data (sub-agent fan-out, asymmetric commit, rejection of fire-and-forget + polling, v0.14.0 soft-timeout as the next hardening step). Full per-run data and methodology deferred to a separate long-form write-updocs/tree with six deep-dive topics (bilingual):observability,ci-cd,cost,supply-chain-security,privacy,reflections. Each exists in native English and Traditional Chinese variants per the bilingual convention — not machine translations
- README.md / README.zh-TW.md both reduced from 798 → 550 lines (-31%). Six heavy chapters (Observability / CI/CD Integration / Cost Estimation / Supply Chain Security / Privacy & Data Flow / Reflections) moved to
docs/. The README now focuses on 30-second pitch + 10-minute onboarding; anything beyond that points intodocs/ - New
## Documentationindex section at the end of both README variants lists alldocs/entries with bilingual links
- Runtime behavior, scripts, commands, and
checksums.sha256are unchanged.docs/is not in the npmfiles:list, so this release is documentation-only for npm consumers - Internal experiment scaffold (prompts, runner scripts, raw jsonl) remains in the gitignored
internal/directory. Future publication as a reproducible scaffold is deferred
Soft-timeout wall-clock guard for call-*.sh. Bounds provider-CLI execution to a configurable wall-clock limit so the script exits with a structured marker before the ~130s Claude Code harness watchdog SIGKILLs it silently. Addresses the F-group silent-death signature (N=1/7, evening-bad) identified in the 2026-04-20→21 bg-regression experiments.
CLAUDE_PRISM_TIMEOUTenvironment variable (integer seconds, range 1..3600; default 110). Invalid values (non-integer, zero, negative, or above 3600) fall back to 110 with aWARNlog entry. The upper bound prevents values that macOS BSDsleeprejects, which would otherwise kill the watcher subshell underset -eand silently disable the timeout guard entirely. Power users can widen per-invocation for known-long runs:CLAUDE_PRISM_TIMEOUT=180 ./call-codex.sh "40KB review prompt"- Soft-timeout mechanism in both
scripts/call-codex.shandscripts/call-gemini.sh: background pipeline + watcher subshell + per-invocation marker file. On timeout, the watcher first confirms the pipeline is still alive (kill -0 "$LAST"gate, avoids boundary-race log pollution), then writes the marker, emits asoft_timeout stage=exec elapsed_s=Nevent to the shared log, and issuespkill -TERM -P $$to terminate all pipeline members (pipeline members are direct children of the parent shell in Bash's pipeline semantics). Parent'sEXITtrap handles KILL-escalation plus marker/temp cleanup. Classification usesrc in {143,137} && [[ -s "$TIMEOUT_MARKER" ]]— the marker ismktemp-unique per invocation, eliminating PID-reuse false positives. Exit code 124 (GNUtimeoutconvention) for external consumers; stderr sentinel[CLAUDE-PRISM: soft-timeout at STAGE=exec after ${TIMEOUT_S}s]for human-readable diagnosis SOFT_TIMEOUToutcome inscripts/analyze-log.sh— log-event-driven classification viamsg ~ /^soft_timeout /match, prioritized over subsequentERROR/SIGNALevents from the same pid (both of whichcall-*.shalso emits during teardown). Summary now showsTO Soft-timeout: Nalongside the existingOK / ER / SG / !!counters
- Strict ISO-8601 timestamp validation in
analyze-log.sh:to_epoch(OWASP A03). Theawkfunction previously interpolated$ts(first whitespace-delimited field of each matching log line) into a shell command viacmd | getline. Legitimate log entries produced by_logare always well-formed, but if the log file were externally tampered — e.g. by a local attacker with write access to~/.claude/logs/, or by a future log writer accepting user-controlled content in field$1— a crafted "timestamp" like$(touch /tmp/pwned)would execute. Added a strict regex gate (^[0-9]{4}-...Z$) before shell interpolation. Zero false negatives for legitimate entries; adversarial fixtures verified blocked
- Added Test 13 (6 regression cases) to
tests/smoke-test.shusing injected fake CLI binaries viaCODEX_BIN/GEMINI_BINenv vars — no real API calls, no credentials required. T13.1 codex normal completion (rc=0, no sentinel, and nosoft_timeoutevent in log — the absence-assertion is the boundary-race regression guard); T13.2 codex timeout fires (rc=124 + sentinel + log event); T13.3 customCLAUDE_PRISM_TIMEOUT=5honoured within ±2s tolerance; T13.4 no orphanfake-slow-cliprocesses after timeout fires (process-leak regression guard); T13.5 gemini mirror fires identically to codex (byte-sync contract verification); T13.6 overflowCLAUDE_PRISM_TIMEOUT=9999999999falls back to 110 with WARN log (macOS BSDsleepbypass regression guard). smoke-test total: 37 → 43
Three provider-proposed mechanisms were refuted by local POC during plan revision:
- SIGALRM-to-parent trap does not interrupt foreground pipelines. Bash queues the signal until the shell regains control, so
trap '...' ALRMonly fires after the pipeline completes naturally — timeout effectively useless. Verified on Bash 5.3.9 + 3.2.57. Fix: background the pipeline with&sowaitis interruptible; use a watcher subshell instead of parent trap - rc=124 cannot drive analyzer classification because
analyze-log.shdoesn't inspect exit codes — it matches log message patterns. SOFT_TIMEOUT is therefore log-event-driven (cleaner — no cross-layer exit-code leak) while still exiting 124 for external consumers - Killing pipeline middle-stage via
$!alone is insufficient.$!captures the last pipeline member (tee), and SIGPIPE does not propagate to middle-stage CLIs that don't write stdout.pkill -TERM -P $$targets all parent's direct children, which includes every pipeline member
- Mechanism B (Gemini service-side tail event → harness drops output silently) is NOT addressed by this change — that requires skill-layer log fallback, deferred
- Byte-sync between
call-codex.shandcall-gemini.shenforced byKeep in synccomment header; future CI lint check to be added (deferred, not v0.14.0 scope)
Skill layer hardening — sub-agent fan-out + GEMINI_MODEL passthrough. Two related policy changes to the pi-* command surface, both prompted by bg-regression experiment data (N=36+ runs) showing the prior prescription did not deliver its stated guarantee.
- Sub-agent fan-out replaces main-conversation parallel Bash for
pi-askall,pi-plan, andpi-multi-review. Main-conversation Bash is a structural FIFO queue — the second parallel Bash waits for the first to finish (delta ≈ first_execprecisely, N=7 across two capacity slots). The v0.12.3 prescription "send two Bash tool calls in a single response" was therefore semantically a no-op: provider calls ran sequentially, not concurrently. v0.13.0 dispatches via two parallelAgenttool calls (subagent_type: "general-purpose"), each invoking its CLI wrapper inside the sub-agent's own Bash — sub-agent Bash dispatches in parallel (median delta 2.8s, N=13). Live POC captured during this release confirms the pattern works. This is primarily a correctness fix (restore parallel semantics); for long provider calls it also saves wall-clock (pi-plan baseline ~156s via fan-out vs ~218s hypothetical FIFO = 28% saved) - Skills no longer set
GEMINI_MODEL— the user's shell environment passes through to the sub-agent's Bash, thencall-gemini.sh, then the Gemini CLI, with no skill-side override. Previouslypi-plan,pi-multi-review,pi-fact-check, andpi-researchall wrapped their Gemini call withGEMINI_MODEL="${GEMINI_MODEL_DEEP:-${GEMINI_MODEL:-}}", which gaveGEMINI_MODEL_DEEPpriority over the user's explicitGEMINI_MODELchoice. The layering looked user-respectful but silently promoted the deep tier wheneverGEMINI_MODEL_DEEPwas set. If a call fails withRATE_LIMIT/ capacity, the skill surfaces the error and leaves the tier decision to the user
- Dispatch rules preamble in
pi-askall,pi-plan, andpi-multi-reviewreplaces the v0.12.3 "Bash invocation rules" notice. Explains why main-conversation parallel Bash fails (FIFO), how sub-agent fan-out differs (separate dispatch layer), and whenrun_in_background: truestill applies (unchanged escape hatch for genuinely-long calls) GEMINI_MODELpassthrough note inpi-askallspells out the policy so future skill authors don't reintroduce layering
GEMINI_MODEL_DEEPis no longer read by any skill. Users who setGEMINI_MODEL_DEEPto force the deep tier forpi-plan/pi-multi-review/pi-fact-check/pi-researchwill, after upgrade, fall through to whateverGEMINI_MODELis set to (or the CLI's own default if unset). Migration: if you previously setGEMINI_MODEL_DEEP=gemini-3-pro-previewto keep the deep tier for reviews while running Flash for general Q&A, either (a) setGEMINI_MODEL=gemini-3-pro-previewglobally and accept the deep tier everywhere, (b) launch Claude Code with the env var set for that session only, e.g.GEMINI_MODEL=gemini-3-pro-preview claude, or (c) leave it unset and let the CLI default apply- Downstream skill authors extending
pi-askall/pi-plan/pi-multi-reviewverbatim must follow the new sub-agent fan-out pattern — the old "two parallel Bash tool calls" prescription is gone
- For end-users who did NOT set
GEMINI_MODEL_DEEP, the only behaviour change is "parallel now actually parallel" pi-fact-checkandpi-researchmake one Gemini Bash call + NWebSearchcalls. They don't trigger the two-Bash FIFO, so sub-agent fan-out is not applied there — only theGEMINI_MODELpassthrough change affects them. The Bash + WebSearch queue interaction is untested; a future investigation tied to thecall-*.shsoft-timeout work may surface additional changes
Regression test hardening — lock in the v0.12.3→v0.12.5 stdin fixes with six dedicated test cases so future edits to the stdin block in call-codex.sh / call-gemini.sh fail fast instead of silently regressing.
- Added six stdin regression scenarios to
tests/smoke-test.sh(pipe / file redirect /</dev/null× 2 wrappers). Uses exact prompt-length assertions so silent truncation or drop cannot pass the test — the prior> 1form would have accepted partial-byte loss. Inherited non-EOF fd case intentionally excluded and documented in-line (FIFO is not a valid proxy for the v0.12.3 anonymous-pipe bug shape, and macOS lackstimeout). smoke-test total: 31 → 37 - Added
# Keep in sync with scripts/call-<other>.shcomments above the shared stdin block in both wrappers, aligning with the existinginstall.sh/uninstall.shmirror convention so manual edits carry a visible sync signal
- EXIT trap for temp dir cleanup in smoke-test.sh regression block — the new Test 12 section created two temp dirs (
mktemp -dfor fixture + git repo) but relied on a trailingrm -rffor cleanup. Underset -euo pipefail, any error betweenmktempand the final cleanup would leak the dirs (including an initialized git repo). Register anEXITtrap immediately after bothmktemp -dcalls so cleanup runs on success, error, and signal paths alike. OWASP A10 Mishandling of Exceptional Conditions
Hardening pass on top of v0.12.4 — adversarial review (Codex) and security lint surfaced two issues that complete the stdin attack surface fix.
- Silent drop of
< file.txtredirect input — v0.12.4's stdin guard[[ ! -t 0 && -p /dev/stdin ]]correctly stopped thecatdeadlock but narrowed too far: a regular-file redirect (call-codex.sh "..." < diff.txt) is not a FIFO under bash, so the redirected payload was discarded without warning. Broaden the guard to[[ ! -t 0 && ( -p /dev/stdin || -f /dev/stdin ) ]]so any finite EOF-reaching source is consumed; non-EOF inherited fds still skip (preserving the v0.12.4 fix). Verified across pipe / file redirect /</dev/null/ no-redirect inheritance - Log injection via unsanitized CLI stderr —
_log ERROR "... $err_text"in both wrappers wrote raw subprocess stderr to~/.claude/logs/multi-ai.log, which lets a crafted prompt fragment echoed back by Codex/Gemini forge log entries (e.g.\n2026-04-20T00:00:00Z [codex] [INFO] [pid=1] fake success). The v0.12.4 stdin guard widening enlarged the attacker-controlled payload surface (file redirect now consumed too), so harden the sink. Strip newlines viatr '\n' ' 'before the_logcall. The user-facingDetails:stderr echo keeps the raw text — that path is for terminal display, not structured log parsing. OWASP A09 Logging & Monitoring Failures
Fix stdin pipe deadlock — call-codex.sh / call-gemini.sh no longer hang on cat when invoked without an upstream pipe.
- stdin pipe deadlock when no pipe present —
call-codex.sh/call-gemini.shpreviously hung oncatwhen invoked without a pipe but with an inherited non-TTY stdin (a Claude Code v0.12.3+ subshell behavior surfaced after the auto-background bypass landed). Affected 6 commands across 8 call sites:pi-plan,pi-multi-review,pi-code-review(main path),pi-ui-design(spec-generation step),pi-ask-codex(no-context path), andpi-ask-gemini(no-context path). The fix narrows the stdin guard from[[ ! -t 0 ]]to[[ ! -t 0 && -p /dev/stdin ]]so the script only reads when there's an actual FIFO with a writer that will close. The 8 pipe-based call sites (pi-research,pi-askall,pi-fact-check,pi-ui-review,pi-ui-designHTML generation,pi-code-reviewlong-input mode,pi-ask-{codex,gemini}with-context path) are unaffected.
- Added "Cache TTL Behavior" section under Observability in both
README.mdandREADME.zh-TW.md. Documents Claude Code's current 5-minute prompt cache TTL (applying to all subscribers regardless of Pro or Max tier), the 2026-03-08 Claude Code-wide shift from a 1-hour default back to 5 minutes (see GitHub issue #46829), and clarifies that "Max subscribers automatically receive a 1-hour TTL" is an unverified community claim — Anthropic's official prompt caching documentation does not gate TTL by subscription tier. Non-alarmist informational framing; no preamble, command, or script changes - Sharpened review-insights wording in both
README.mdandREADME.zh-TW.mdto accurately reflect that Claude (the AI) participates in both writing and reading sides of the JSONL log: at write time Claude interprets Codex/Gemini output (emoji→severity mapping, source inference, ≥80 confidence filter) before appending; at read timereview-insights.shonly computes raw counts viajq, with deeper interpretation (trends, root causes) handled by Claude. Replaced passive voice / "automatically records" phrasing across 4 spots — How It Works step 7, the Review Insights section, the bash comment annotation, and the Privacy "What Stays Local" note — so readers don't mistake the pipeline for pure script automation
Bypass Claude Code auto-background regression — commands and scripts harden against the 2026-04+ regression where Claude Code's auto-background path silently kills child processes (output file stays 0 bytes, ps shows no trace).
Claude Code 2026-04+ versions (observed on v2.1.114) changed the auto-background lifecycle: when the runtime decides to background a Bash tool invocation, the child process gets killed instead of detached — the task dir gets a "running" entry but ps aux shows nothing, and output files stay empty because the process never reached the tee write. Explicit run_in_background: true uses a different (working) lifecycle, and foreground synchronous calls are unaffected.
- All 10
pi-*commands now include a "Bash invocation rules" preamble directing Claude to callcall-codex.sh/call-gemini.shin foreground synchronous mode with an explicittimeout: 600000(10-minute ceiling). Explicit&,run_in_background: true, andnohupare forbidden — any path that lets Claude Code decide to background triggers the regression.run_in_background: trueremains as an escape hatch for commands genuinely expected to exceed 10 minutes - Parallel provider calls (
pi-askall,pi-multi-review,pi-plan) achieve concurrency by sending two Bash tool calls in a single response, each foreground-synchronous, instead of relying on shell-level&
- Lifecycle logging —
call-codex.shandcall-gemini.shgainINVOKE(entry),STAGE(tracksentry→parse_flags→stdin_read→git_check→binary_resolve→exec→done), andSIGNAL(HUP/INT/TERM traps) log events. Every log line now carries a[pid=N]prefix to group events by invocation.SIGKILLis uncatchable, so the absence of aSUCCESS/ERROR/SIGNALevent after anINVOKEis the signature of an auto-background kill - SIGHUP trap replaces silent ignore — the previous
trap '' HUPis replaced withtrap '_log_signal HUP' HUP. Behavior is unchanged (HUP still doesn't terminate the script), but now the event is recorded scripts/analyze-log.sh— new utility that readsmulti-ai.log, groups entries by pid, and reports each invocation's outcome (Success / Error / Signal / Silent death). Silent deaths point to suspected Claude Code auto-background SIGKILLs. Pre-v0.12.3 log entries (no pid prefix) are skipped
- Removed "Changing the output language" section from both
README.mdandREADME.zh-TW.md. The original guidance had two problems: it biased the example toward a specific language (a public open-source package shouldn't assume its readers' preferred language), and it pointed users atcommands/*.mdfiles that./install.shoverwrites on every upgrade — so the customization wouldn't persist anyway. A proper mechanism (likely an env var) is deferred to a future release - Added "Invocation Diagnostics" section under Observability in both README variants, documenting
analyze-log.shusage, the four outcome categories (SUCCESS / ERROR / SIGNAL / SILENT), and how SILENT deaths signal Claude Code auto-background SIGKILL events
Background fallback — all 10 commands now recover from Bash tool backgrounding.
- Fallback read instructions — every
pi-*command prompt now includes a fallback directive: if the Bash tool was backgrounded or returned empty output, Claude reads the result from~/.claude/logs/pi-{codex,gemini}-last.out(persisted by the script'steesafety net since v0.11.4/v0.12.0) - Completes the three-layer defense against background output loss: script-level
teestreaming (v0.11.4) → file persistence (v0.12.0) → command-level fallback read (v0.12.2)
Community — added contributing guide and code of conduct.
- CONTRIBUTING.md — development setup, code standards (Bash 3.2+, ShellCheck), testing, commit convention, PR process, and contribution boundaries (what we accept / don't accept)
- CODE_OF_CONDUCT.md — Contributor Covenant 2.1
- README updates — added Contributor Covenant badge and Contributing section to both
README.mdandREADME.zh-TW.md
Adversarial review upgrade — review prompts redesigned from neutral "Senior Reviewer" to adversarial stance with divided attack surfaces, inspired by codex-plugin-cc concepts (Apache 2.0).
- pi-code-review — Codex prompt upgraded to adversarial stance: "break confidence in the change, not validate it." 9-category attack surface (auth, data loss, race conditions, rollback safety, edge cases, schema drift, observability, annotation compliance, guideline compliance), finding bar (every finding must answer what/why/impact/fix), calibration rules ("prefer one strong finding over several weak ones"), and final self-check
- pi-multi-review — both provider prompts upgraded to adversarial with divided attack surfaces: Codex attacks security & data integrity (7 categories), Gemini attacks design, UX & maintainability (7 categories). Aligns with existing domain-aware weighting (Codex → backend authority, Gemini → frontend authority)
- Consistent filtering — "DO NOT flag" criteria unified across all three prompts (including lint-ignore/noqa/@ts-ignore exclusion)
- Last-run output files —
call-codex.shandcall-gemini.shnow persist output to~/.claude/logs/pi-codex-last.outandpi-gemini-last.out(fixed paths, not temp files). Files survive script exit as a fallback if stdout is lost during background execution - Builds on v0.11.4's
teestreaming fix — stdout remains the primary output channel; file persistence is the safety net
Fix: streaming CLI output to prevent background execution data loss
RESULT=$(...)→teestreaming —call-codex.shandcall-gemini.shno longer buffer the entire CLI response in a shell variable. Output now streams directly to stdout viatee, so callers that background the script (e.g. Claude Code Bash tool auto-backgrounding) can capture output in real time instead of seeing 0 bytes- SIGHUP survival — added
trap '' HUPto both wrapper scripts so they survive terminal detach when backgrounded, preventing silent process death - bash 3.2 compat (error path) —
${err_text,,}in installed scripts now usesprintf | tr(matching the v0.11.3 repo fix that hadn't been re-installed)
Fix: macOS bash 3.2 compatibility — error classification no longer breaks on stock macOS bash.
${var,,}→trreplacement —call-codex.shandcall-gemini.sherror classification used bash 4+ lowercase syntax (${err_text,,}), which causesbad substitutionon macOS built-in bash 3.2. Replaced with POSIX-compatibleprintf | tr '[:upper:]' '[:lower:]'- Only affects the error path (CLI call failure); normal execution was never impacted
Fix: pi-ui-review stdin pipe — large code reviews no longer silently fail.
/pi-ui-reviewstdin pipe — code content moved from shell argument to stdin pipe, matching the v0.9.6 standard used by all other commands. Previously, large frontend code reviews causedcall-gemini.shto return 0 bytes silently due to ARG_MAX limits and shell metacharacter expansion inrun_in_backgroundmode- Historical review comments via stdin — Step 1.7 PR comment context also routed through stdin to avoid argument overflow on repos with extensive review history
Model Tier Override — two-tier model setup for heavy-reasoning commands.
GEMINI_MODEL_DEEPenv var — new environment variable for selecting a higher-tier Gemini model on heavy-reasoning commands. Falls back toGEMINI_MODEL, then CLI default — zero behavioral change for existing setups- Four commands upgraded —
/pi-fact-check,/pi-research,/pi-multi-review, and/pi-plannow useGEMINI_MODEL_DEEPwhen set, automatically routing to Gemini Pro for deep reasoning while keeping Flash as the fast default for other commands - Nounset-safe — parameter expansion uses
${GEMINI_MODEL_DEEP:-${GEMINI_MODEL:-}}to avoidset -ubreakage in strict shell environments
Provider Resilience — dual-track research, structured error diagnostics, and graceful degradation across all commands.
Driven by Gemini CLI service degradation (Discussion #22970: paid users hitting 429 errors, 7–10 min latency, 24hr+ outages post-March 25 update), this release hardens every command against provider instability.
/pi-researchupgraded to dual-track — now launches Gemini (search grounding) and WebSearch simultaneously, same architecture proven in/pi-fact-check. If Gemini times out or returns 429, WebSearch results cover the gap. Claude synthesizes all available sources with URL attribution- Source URLs in research reports — Gemini prompted to return source URLs; WebSearch URLs included in final report. Claims without sources marked as (unverified)
- Provider Status table — research reports now begin with a track status table (Gemini ✅/
⚠️ , WebSearch ✅/⚠️ , Claude ✅ always)
- Error classification in shell scripts —
call-gemini.shandcall-codex.shnow classify errors into 7 categories:TIMEOUT,RATE_LIMIT,AUTH_ERROR,PERMISSION,SANDBOX(Codex only),NETWORK,CLI_ERROR, plusCLI_NOT_FOUNDfor missing binaries - Bash regex over grep — error classification uses
[[ "$err_lower" =~ pattern ]]instead ofecho | grep -qi, eliminating subshell forks on the error path and avoiding aset -euo pipefailedge case. Lowercase conversion updated toprintf | trfor macOS bash 3.2 compatibility in v0.11.3 - PERMISSION class — new error category for filesystem permission denied (previously misclassified as AUTH_ERROR in both scripts).
call-codex.shreordered: SANDBOX now matches before AUTH_ERROR, preventing "permission denied" from triggering wrong recovery guidance - CLI_NOT_FOUND class — binary resolution failures now emit the same structured
Error: CLI_NOT_FOUND:prefix as runtime errors, so downstream commands can parse failure reason consistently
All 10 commands updated with consistent failure handling:
- Specific failure reasons — every failure message now includes the error classification from stderr (e.g., "
⚠️ Gemini unavailable (RATE_LIMIT) — ...") instead of generic "unavailable" - Alternative command suggestions — when a provider fails, the message suggests a relevant alternative:
/pi-ask-codex//pi-ask-gemini→ suggest/pi-askall/pi-code-review→ suggest/pi-multi-review/pi-ui-review→ suggest/pi-multi-review
- Full error category lists — all command docs now list the complete set of error categories (no more "etc." shortcuts), matching the actual script output. Gemini commands include PERMISSION; Codex commands include SANDBOX
- Never abort — consistent across all commands: always produce output, even if all providers fail
- Gemini CLI log analysis (628 log entries, Feb 24 – Mar 27): average latency increased ~30% post-March 25 service update, 6 timeout incidents concentrated on API deployment dates (Mar 18: 60% failure rate, Mar 25: 22% failure rate)
/pi-researchand/pi-fact-checkconfirmed as architecturally distinct (exploratory vs verification) — not merged, but/pi-researchelevated to the same resilience tier
Fact-Check Dual-Track — Gemini + WebSearch race eliminates dead-wait time.
- Dual-track search architecture —
/pi-fact-checknow launches Gemini (search grounding) and WebSearch simultaneously instead of sequential fallback. Whichever returns first is usable immediately; both results merge for stronger source convergence - Batch size optimization — Gemini batches reduced from 5 to 2 claims each (search grounding serializes internally; smaller batches complete within timeout)
- Timeout fix — replaced
perl alarmwith Bash tool timeout parameter (fixes orphan process on macOS, removes permission allowlist dependency) - Convergence-based confidence — new report format with source convergence scoring (🟢 High/🟡 Medium/🟠 Single/🔴 Conflicting) and 6-tier source ranking (L1 official records through L6 community)
- URL validation — Step 4.5 verifies Gemini-sourced URLs via WebFetch, downgrades verdict on hallucinated/fabricated sources, triggers full WebSearch fallback if >50% fail
- Editorial chain dedup — same-origin sources (e.g., AP wire republished by 5 outlets) collapsed to 1 independent source for accurate convergence counting
- README updates — bilingual documentation updated to reflect dual-track architecture, cost estimation, and degradation path
Score Transparency & README Rewrite — show your work, sharpen claims.
- Score transparency (Show Your Work) — all 3 review commands (
/pi-code-review,/pi-multi-review,/pi-ui-review) now end with ashow scoresaffordance. Users can request a full factor breakdown for every finding, showing exactly how each confidence score was calculated (base 40, applicable factors, arithmetic) - README rewrite — "The Problem" / "The Solution" sections rewritten with clearer narrative: F1 noise → cross-provider triangulation → evidence-based scoring → local-first. New "Why Trust the Findings?" section explains the difference between LLM self-assessment and deterministic evidence-based scoring
- Accuracy fixes — F1-to-false-positive claim corrected (removed unsupported ratio), Anthropic plugin comparison softened to factual statement, determinism claims qualified to "core formula" per spec §2.2
- Bilingual affordance — score transparency hint line now bilingual (EN/zh-TW) for international users
- Gemini CLI service update notice — added Prerequisites notice about Google's March 25, 2026 changes (free accounts limited to Flash models)
- Acknowledgments section — added to both READMEs, crediting newtype-os/super-fact-checker
Fact-Check Rewrite — original methodology, unified English.
- Rewritten
/pi-fact-checkprompt — replaced external methodology with original cross-provider approach: natural language claim extraction, source preference ordering, 4 verdicts (Verified / Imprecise / Incorrect / Unverifiable), 5 cross-verification dimensions - Adversarial evidence — new verification dimension: court filings, regulatory actions, and competitor analyses that implicitly confirm facts carry highest confidence (survived hostile scrutiny)
- Unified English — all prompt content now in English, consistent with other commands
- Simplified — 186 → 121 lines without losing functionality
New Command: Fact-Check
- New
/pi-fact-checkcommand — cross-provider fact verification using Gemini (Google search) for source discovery and Claude for cross-verification. Two providers, two roles: Gemini finds evidence, Claude judges it - Gemini-only — no Codex. Fact-checking is an evidence-based task; Codex has no web search and would not add verification value
- Graceful degradation — Gemini timeout (90s) → WebSearch fallback → Claude training data. Never aborts
- Save results — optional save to
.claude/pi-fact-check/<slug>.md
New Command & Trigger Refinement
- New
/pi-askallcommand — ask Codex and Gemini the same question in parallel, then Claude synthesizes all three perspectives. Works with any topic (code, architecture, strategy, writing, decisions) — not limited to code review - Narrowed
/pi-plantrigger scope — now triggers only for architectural decisions, tech stack selection, and tasks with multiple viable approaches. Simple task breakdown is left to Claude Code's built-in plan mode
Review Quality Improvements — three new review dimensions inspired by analysis of Anthropic's official code-review plugin.
- Historical PR comments — review commands and
ci-review.shnow query review comments from recent merged PRs that touched the same files, surfacing recurring issues as high-confidence context. CI uses a single GraphQL query; slash commands useghCLI interactively - Inline annotation compliance — all review commands now check if changes violate nearby code comments (
IMPORTANT,WARNING,FIXME,TODO,NOTEannotations) - Diff scope constraint — provider prompts now explicitly constrain reviewers to focus on the diff, reducing hallucination and out-of-scope noise
- Removed
/pi-exec— Claude Code is already a powerful agentic executor with built-in task tracking (TodoWrite) and cross-session resume (RESUME.md)./pi-execduplicated these native capabilities without adding cross-provider value - Repositioned core narrative — added "Why claude-prism?" comparison table contrasting cross-provider review with single-provider multi-agent approaches
- Diff hunk validation for inline suggestions —
ci-review.shnow validates that suggestion line numbers fall within actual diff hunks before posting via the GitHub Reviews API
GitHub Suggestion Blocks — review commands now output one-click fixable code suggestions.
- Suggestion block output —
/pi-code-review,/pi-multi-review,/pi-ui-reviewnow include GitHubsuggestionblocks for issues with concrete, unambiguous code fixes - Inline PR review comments —
ci-review.shparses suggestion blocks and posts them as inline review comments via the GitHub Reviews API, enabling one-click "Apply suggestion" in PRs - Graceful fallback — if the Reviews API fails or no suggestions are found, falls back to regular PR comment (fully backward-compatible)
Prompt Quality & Consistency — multi-provider review of all 9 command prompts, with fixes.
- Confidence scoring implemented — evidence extraction, hallucination verification, and
--verboseflag applied to all 3 review commands (/pi-code-review,/pi-multi-review,/pi-ui-review), aligned with spec v1.0 - Fix: pi-exec resume bug — plan step checkbox syntax (
1. [ ]vs- [ ]) mismatch between/pi-planand/pi-execcaused resume detection to fail - Fix: pi-ask-gemini "review" prefix — code context invocation hardcoded
"review"as the prompt, biasing Gemini's response - Standardized stdin pipe invocation — all commands with code context now use
echo "context" | call-xxx.sh "$ARGUMENTS"pattern consistently (avoids ARG_MAX limits) /pi-researchenhanced — added project context awareness, optional save-to-file (.claude/pi-research/), and improved Claude supplement wording/pi-ui-designfixed — resolved undefined variables ($DESIGN_SPEC_CONTENT,$USER_INPUT), standardized to$ARGUMENTSand stdin pipe- Context budget — all commands with code/context injection now enforce a 4000 char limit with summarization guidance
- Internationalization — removed hardcoded Chinese text from command prompts; output language now follows user's own Claude Code language settings
- Failure message consistency — standardized format across all commands:
"[Provider] unavailable — [action] by Claude only."
Supply Chain Security — improve socket.dev score and npm packaging.
- npm
filesprecision — excluded CI-only scripts (ci-review.sh,review-insights.sh,usage-summary.sh) from npm package; only runtime scripts shipped bugsfield — addedbugs.urltopackage.jsonfor npm metadata completeness- npm OIDC Trusted Publishing — CI uses Node 24 + OIDC for npm publish with provenance (no
NPM_TOKENsecret needed)
Security & Bug Fixes — audit-driven hardening across all scripts.
- Prompt injection defense —
ci-review.shnow wraps both GUIDELINES and DIFF blocks with explicit data boundary markers to prevent LLM instruction injection - stderr/stdout separation —
call-gemini.shandcall-codex.shno longer mix stderr into AI responses; errors are logged and forwarded to stderr separately ghCLI dependency check —ci-review.sh --prmode now validatesghavailability before attempting to fetch PR diff--sandboxwhitelist —call-codex.shvalidates sandbox mode against allowed values (read-only,sandbox,none)review-insights.shrewrite — switched from fragile sed/grep JSON parsing tojq; addedjqdependency check; fixed unquoted variable references- Schema consistency —
pi-code-review.mdlogging schema now includesdomainfield (matchingpi-multi-review.md) - Domain detection tests — 6 new test cases for
detect-domain.sh(smoke test: 26 → 32) - Docs — added CLI version compatibility table and checksums trust model explanation to README
Confidence Scoring & Guideline Compliance — evidence-based noise filtering and project rule enforcement across all review commands.
- Confidence scoring — every review issue scored 0–100 on evidence quality (line numbers, cited rules, reproducibility, consensus). Only issues ≥ 80 shown. Scoring is evidence-based, not opinion-based — Claude cannot veto cross-provider findings with strong evidence
- Guideline compliance — auto-discovers
CLAUDE.mdandAgents.mdin the project, checks code against project-specific rules. Ready for the emergingAgents.mdstandard - False positive filtering — explicit exclusion rules in all review prompts: no pre-existing issues, no linter-detectable problems, no pedantic nitpicks, no lint-ignore lines
- Applied to:
/pi-code-review,/pi-multi-review,/pi-ui-review,ci-review.sh - Review insights enhanced — JSON schema adds
confidencescore andguidelinecategory
Distribution — added npx and Homebrew install support.
npx claud-prism-aireviewfor one-command installbrew tap tznthou/claude-prism && brew install claud-prism-aireviewfor macOS- Added GitHub Release workflow for automated npm publishing
- Legacy command cleanup in install/uninstall scripts
Smart Routing, Plan/Execute & Command Namespace — domain-aware review weighting, persistent planning, and pi- prefix for all commands.
All 9 commands are now prefixed with pi- (e.g., /code-review → /pi-code-review, /research → /pi-research).
Why? Claude Code has a built-in /plan command (enters plan mode). Our new /plan command for persistent planning would collide with it. Rather than only prefixing the conflicting commands, we chose to prefix all commands uniformly for namespace safety and brand identity. The pi- prefix (from Prism Initial) is short enough to type quickly while making it clear which commands belong to claude-prism.
Migration: After updating, re-run ./install.sh. The installer will overwrite the old command files. To clean up old (unprefixed) commands manually:
cd ~/.claude/commands
rm -f ask-codex.md ask-gemini.md code-review.md multi-review.md \
research.md ui-design.md ui-review.md plan.md execute.md/pi-multi-review now auto-detects the domain of the code changes (frontend / backend / fullstack) and adjusts provider weight during synthesis.
How it works:
- File paths from the review scope are piped to
detect-domain.sh - The script classifies each file by extension and path:
- Frontend signals:
.css,.tsx,.jsx,.vue,.svelte,.html,.svg/components/,pages/,styles/,ui/ - Backend signals:
.go,.py,.rs,.java,.sql,.proto/api/,controllers/,models/,middleware/,migrations/ - Neutral (not counted):
.ts,.js,.json,.yaml,.md,.sh
- Frontend signals:
- If ≥ 70% of classifiable files lean one way → that domain; otherwise →
fullstack
During synthesis:
| Domain | Gemini weight | Codex weight | Rationale |
|---|---|---|---|
| frontend | Higher | Standard | Gemini excels at UI/UX, accessibility, design patterns |
| backend | Standard | Higher | Codex excels at algorithms, security, API design |
| fullstack | Equal | Equal | No domain advantage |
Design philosophy: "weight, don't route." Both providers are always called. The domain only affects how Claude resolves disagreements — if both providers agree on an issue, it's reported regardless of weighting. This preserves graceful degradation: if one provider is down, the other still covers the full review.
Two new commands for persistent, cross-session task planning:
/pi-plan <task description> — Analyze the codebase and generate a structured plan file:
- Optionally consults Codex and Gemini in parallel for independent technical analysis
- Detects domain via
detect-domain.shto contextualize recommendations - Outputs a markdown plan to
.claude/pi-plans/<slug>.mdwith: context, multi-provider analysis, step-by-step implementation (with checkboxes), key files, risks, and verification criteria - Does not auto-execute — the plan is a proposal for the user to review
/pi-exec <plan-file> — Execute a plan step by step:
- Reads the plan, validates status (draft / approved / in-progress / completed)
- Executes each step sequentially, updating
- [ ]→- [x]as it goes - If a step fails, stops and asks the user how to proceed
- Resume support: If a session ends mid-execution, running
/pi-execon the same file resumes from the first unchecked step — no progress is lost
Why not SESSION_ID? Some planning tools use session IDs and a separate binary to track state. We use markdown checkboxes instead — the plan file itself is the state. This keeps the mechanism simple (no external dependencies), human-readable (you can edit the plan in any editor), and consistent with our zero-compile-dependency principle.
- Review insights enhanced —
review-insights.jsonlnow includes adomainfield for domain-aware trend analysis detect-domain.sh— new standalone utility script (can be used outside of multi-review; reads file paths from stdin)
Security Hardening — security audit and fixes across all shell scripts:
- Temp file safety —
review-insights.shnow usesmktempinstead of a predictable/tmppath (symlink attack prevention) - Input validation —
ci-review.shvalidates--prargument as a positive integer - Process visibility —
call-codex.shandcall-gemini.shnow always pipe prompts via stdin (prevents exposure inpsoutput) - Install integrity —
install.shverifies SHA256 checksums before installing (newchecksums.sha256file) - ShellCheck CI — new GitHub Actions workflow for static analysis on all shell scripts
- ShellCheck fixes — removed unused variables, fixed invalid
>=operator, quoted command substitutions
CI/CD Integration — automated multi-provider PR review via GitHub Actions:
ci-review.sh— CI/CD review orchestrator that calls Gemini API + OpenAI API in parallel, with optional Claude synthesis. Uses REST APIs directly (no CLI installation needed)- GitHub Actions workflow (
ai-review.yml) — label-triggered or auto-triggered PR review with concurrency control - Graceful degradation in CI — works with any combination of API keys (1-3 providers)
- Large diff handling — auto-truncation at 32K chars (configurable via
MAX_DIFF_CHARS) - Smoke test expanded to 24 tests (from 20)
Reliability & Observability — graceful degradation, usage tracking, and review insights:
- Graceful degradation across all 7 commands — if a provider fails, Claude continues with remaining providers instead of aborting. Non-conforming output (no emoji, no score) is handled via semantic extraction
usage-summary.sh— per-provider call stats, success/error breakdown, estimated token consumption (--week,--all,--date)review-insights.sh— analyze recurring patterns from review history (category/severity distribution, consensus vs. single-provider findings, most frequent issues)- Review insights auto-recording —
/code-reviewand/multi-reviewappend structured JSONL after each review for trend analysis - Smoke test expanded to 20 tests (from 14)
/ui-designredesigned — now generates a previewable HTML mockup (Tailwind CDN) from design spec files- Workflow: design spec → HTML mockup → browser preview → confirm → Claude Code implements
- Text input (no spec file) triggers a two-step flow: generate spec → generate mockup
- Next steps presented as choices (adjust, implement, or
/ui-review)
- New command:
/ui-design— UI/UX design spec generation via Gemini (information architecture, wireframes, component breakdown, visual direction) - Optional
--htmlflag generates a self-contained HTML prototype with Tailwind CDN - Auto-detects project tech stack to inform design suggestions
Script hardening — fixes identified via /multi-review (Codex + Gemini + Claude triple-provider review):
-mflag guard:-mwithout a value now shows a clear error instead of crashing with "unbound variable" (set -u)- Deduplicate execution logic: merged identical error handling from the if/else branches into a single
|| { ... }block - Sanitize error logs: error log entries no longer include response content (which could contain source code or tokens); only exit code is logged
- Initial public release
- 6 slash commands:
/ask-codex,/ask-gemini,/code-review,/ui-review,/research,/multi-review - Model defaults deferred to CLI built-in (no hardcoded versions)
- Dry-run exits before binary check (works without CLI installed)