Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
2520f0e
spec(zai): design for a headless GLM worker backend (PR 1 of 3)
yury-procoders Jul 31, 2026
fa7ec53
spec(zai): rewrite after three pre-flights; add the audits
yury-procoders Jul 31, 2026
62de08f
plan(zai): 11-task implementation plan for the GLM worker backend
yury-procoders Jul 31, 2026
1c232fd
feat(zai): register the backend and its GLM tier map in the resolver
yury-procoders Jul 31, 2026
0efbeed
feat(zai): validate the backend — worktree-mandatory, never a reviewer
yury-procoders Jul 31, 2026
e9f0276
feat(zai): classify z.ai's documented 429 codes; never fall through t…
yury-procoders Jul 31, 2026
f20b1ae
fix(zai): add a fallback entry so a z.ai quota wall reroutes instead …
yury-procoders Jul 31, 2026
b19429c
feat(zai): extract real token counts; drop the CLI's Anthropic-priced…
yury-procoders Jul 31, 2026
8ba7de1
feat(zai): the headless worker, with a scrubbed env and a GLM-respons…
yury-procoders Jul 31, 2026
2cbfb81
test(zai): assert the tool set that reaches the wire, not just the argv
yury-procoders Jul 31, 2026
ed309ad
docs(zai): adapter runbook plus every backend enumeration
yury-procoders Jul 31, 2026
afaa66a
ci: lint scripts/*.sh and run the bash test suites
yury-procoders Jul 31, 2026
de78826
release: v2.18.0 — zai backend
yury-procoders Jul 31, 2026
20315b1
fix(ci): rewrite three A && B || C guards as explicit if-statements
yury-procoders Aug 1, 2026
a017aec
spec(pool): tier model pools — spread a tier's jobs across providers …
yury-procoders Aug 1, 2026
9ca9059
fix(pool): drop a cross-branch link that fails the dead-link gate
yury-procoders Aug 1, 2026
e452d00
spec(pool): rewrite after three pre-flights
yury-procoders Aug 1, 2026
4d8c116
docs(pool): final audit revisions after the 1A/1C cross-check
yury-procoders Aug 1, 2026
ae65149
plan(pool): tier model pool implementation
yury-procoders Aug 1, 2026
9ecccdc
feat(pool): resolve and freeze weighted tier assignments
yury-procoders Aug 1, 2026
253cd35
feat(pool): enforce pooled manifest safety invariants
yury-procoders Aug 1, 2026
aca90e0
feat(pool): reroute exhausted assignments within their pool
yury-procoders Aug 1, 2026
cbe6bb6
docs(pool): freeze dispatch assignments across resume
yury-procoders Aug 1, 2026
098159e
docs(pool): publish tier pool configuration and routing contract
yury-procoders Aug 1, 2026
8eec6fc
docs(pool): record deterministic tier model pools
yury-procoders Aug 1, 2026
ca034ef
fix(pool): close adversarial routing and state gaps
yury-procoders Aug 1, 2026
8e2c5ad
docs(pool): align safety bounds and breaker contracts
yury-procoders Aug 1, 2026
3ccb26f
docs(pool): handoff brief for an adversarial review of PR 6
yury-procoders Aug 1, 2026
4d0db65
fix(zai): stop the worker rewriting its own scope-gate allow-list
yury-procoders Aug 1, 2026
7f42432
chore(pr3): integrate stacked PR prerequisites
yury-procoders Aug 1, 2026
92d6585
spec(routing): design provider cooldown failover
yury-procoders Aug 1, 2026
042688e
docs(routing): revise cooldown design after preflights
yury-procoders Aug 1, 2026
b2874a3
plan(routing): partition provider cooldown implementation
yury-procoders Aug 1, 2026
c2142ed
feat(routing): define strict provider failure timing contract
yury-procoders Aug 1, 2026
98bba87
fix(routing): enforce failure evidence omission
yury-procoders Aug 1, 2026
199e794
fix(pool): close the review's Blocking/Important/Minor findings
yury-procoders Aug 1, 2026
098bc8e
docs(pool): record the adversarial review and its fix handoff
yury-procoders Aug 1, 2026
d913cac
feat(routing): normalize provider cooldown and network evidence
yury-procoders Aug 1, 2026
aa5c462
fix(routing): match official provider failures
yury-procoders Aug 1, 2026
1f81141
feat(routing): decide bounded retry and cooldown transitions
yury-procoders Aug 1, 2026
42aba6a
fix(routing): preserve cooldown timing at retry limits
yury-procoders Aug 1, 2026
7b3c9a2
feat(routing): persist cooldown probes and network pause state
yury-procoders Aug 1, 2026
3fe9e21
fix(routing): bind provider health to persisted attempts
yury-procoders Aug 1, 2026
7440b83
feat(routing): integrate resumable cooldown dispatch
yury-procoders Aug 1, 2026
2bbc75a
fix(routing): validate provider status state
yury-procoders Aug 1, 2026
dce0a85
fix(routing): persist launch result bindings
yury-procoders Aug 1, 2026
f902dca
docs(routing): explain three-provider cooldown recovery
yury-procoders Aug 1, 2026
6a0c204
fix(routing): align cooldown recovery runbooks
yury-procoders Aug 1, 2026
c614b67
fix(routing): document live network success veto
yury-procoders Aug 1, 2026
0701ce7
fix(routing): keep resume replacement contract in lockstep
yury-procoders Aug 1, 2026
f047d79
fix(routing): normalize failure transition intent
yury-procoders Aug 1, 2026
855f00b
fix(routing): charge retry budget atomically
yury-procoders Aug 1, 2026
3106321
fix(routing): migrate legacy retry budgets
yury-procoders Aug 1, 2026
79a89b8
fix(routing): enforce terminal scope and transition causality
yury-procoders Aug 1, 2026
4257c4d
fix(routing): validate historical health generations
yury-procoders Aug 1, 2026
73c3075
fix(routing): require current health batch identity
yury-procoders Aug 1, 2026
37f4d61
chore(routing): drop unrelated worker scope changes
yury-procoders Aug 1, 2026
04d4f7c
test(routing): keep dashboard health fixture causal
yury-procoders Aug 1, 2026
d5b30c5
fix(routing): close fallback recovery edge cases
yury-procoders Aug 1, 2026
339710d
fix(pool): normalize backend check in validate_state, document review…
yury-procoders Aug 4, 2026
2583279
Merge fork/feat/tier-model-pool into feat/rate-limit-rerouting
yury-procoders Aug 4, 2026
1b00fe3
fix(routing): merge residue cleanup + two real gaps from a Codex spec…
yury-procoders Aug 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
{
"name": "superpowers-v",
"description": "Compound V for Superpowers: triple parallel pre-flight (code archaeology + domain-expert + Context7 library validator), disjoint partitioning, manifest-driven multi-backend dispatch (Claude + Codex + Antigravity + Cursor), git-diff scope enforcement, crash-resumable runs, adaptive tier-based routing, epic mode, research-grounded brainstorming (gated pre-brainstorm recon + batched elicitation), V-memory local-first semantic+lexical recall over docs/superpowers (opt-in pure-python embeddings + a deterministic recall→action bridge), and batched parallel dispatch (Opus default, narrow Sonnet exception)",
"version": "2.17.0",
"version": "2.18.0",
"source": "./",
"author": {
"name": "Oleg",
Expand Down
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "superpowers-v",
"description": "Compound V for Superpowers: triple parallel pre-flight (code archaeology + domain-expert advisor + library/doc validator via Context7), disjoint file partitioning, manifest-driven multi-backend dispatch (Claude + headless Codex + Antigravity + Cursor workers), git-diff scope enforcement, crash-resumable runs, adaptive tier-based routing, epic mode for multi-feature builds, V-memory local-first semantic+lexical recall over docs/superpowers (opt-in pure-python embeddings + a deterministic recall\u2192action bridge), and batched parallel dispatch (Opus default, Sonnet for narrow junior-task carve-out), plus /v:onboard — a project-onboarding command that builds a citation-verified knowledge base + AGENTS.md/CLAUDE.md bridge behind a human gate. Auto-intercepts four transitions: pre-brainstorm recon \u2192 brainstorming \u2192 writing-plans \u2192 execution.",
"version": "2.17.0",
"version": "2.18.0",
"author": {
"name": "Oleg",
"email": "copeus@gmail.com"
Expand Down
24 changes: 22 additions & 2 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,13 @@ jobs:
# The deterministic manifest validator is the partition gate. A missing
# validator is a HARD failure (a rename must never silently drop the gate).
test -f scripts/compound-v-validate-manifest.py || { echo "❌ scripts/compound-v-validate-manifest.py is missing — the partition gate would silently vanish"; exit 1; }
python3 scripts/compound-v-validate-manifest.py examples/manifest.example.yaml
# examples/compound-v.example.json seeds a pools.balanced.light entry
# (codex + cursor — neither needs a secret/env var to resolve) so
# task-3-docs's `backend: pool` job exercises the real pool
# validation path in CI, not only the script's own --selftest
# fixtures. Scoped to this one file via --config; every other
# tracked manifest below is validated with no config, unaffected.
python3 scripts/compound-v-validate-manifest.py --config examples/compound-v.example.json examples/manifest.example.yaml
echo "✅ example manifest passes the invariant gate"
# Also validate every tracked run-manifest — exercise the gate on real data,
# not just one curated fixture.
Expand Down Expand Up @@ -193,10 +199,24 @@ jobs:
echo "✅ $hook is executable"
done

- name: Lint hook scripts with shellcheck
- name: Lint hook and worker scripts with shellcheck
run: |
sudo apt-get install -y shellcheck
shellcheck hooks/*.sh
# scripts/*.sh was NEVER linted before v2.18 — the worker scripts and their test
# harnesses, the largest shell surface in the repo, had no static analysis at all.
shellcheck scripts/*.sh

- name: Run bash test suites
run: |
# No CI step ran any scripts/test-*.sh before v2.18: the selftest sweep below covers
# scripts/*.py only, so every bash-level proof in this repo was manual-only.
# Tests that need a CLI this runner does not have exit 0 with SKIP.
set -e
for t in scripts/test-*.sh; do
echo "--- $t"
bash "$t"
done

# FINAL step — run the repo-wide dead-link scan only after every file exists,
# so cross-refs to files authored by later batches resolve at integration time.
Expand Down
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ node_modules/
.env.local
docs/superpowers/_runs/

# Python bytecode cache. Committed __pycache__/*.pyc (added incidentally by a CI commit)
# spuriously BLOCKs any job whose acceptance runs a Python selftest: a fresh worktree's
# tracked bytecode gets rewritten by the interpreter, and the scope gate treats those
# rewrites as out-of-scope changes.
__pycache__/
*.pyc

# Compound V orchestrator run artifacts.
# Worktrees live under $TMPDIR/compound-v/<run-id>/<job-id> (outside the repo) by
# design; these guards catch any that accidentally land in-tree, plus the codex
Expand Down
76 changes: 76 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,82 @@ All notable changes to **superpowers-v (Compound V)** are documented here.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project uses semantic versioning.

## [Unreleased]

### Added — three-provider cooldown recovery

Pool dispatch now persists backend cooldowns, exact-model exclusions, correlated no-response network
pauses, leased recovery probes, and attempt-specific launch bindings across Codex, Claude, and z.ai.
Provider waits above 60 seconds reroute or halt resumably; only the exact leased attempt's completed
normalized success clears health state.

Cooldowns are deliberately backend-wide because CLI output does not expose limiter identity. This
may temporarily sideline a healthy model or credential, but prevents retry herds. It is not quota
balancing: Compound V does not poll balances, infer percentages, or dynamically adjust pool weights.

### Added — deterministic weighted tier model pools

A manifest job may now route through `backend: pool` for `standard` or `light` work. Pools are configured per stance and tier, rotate by manifest-order job ordinal, support positive integer weights, and resolve every member through the existing tier model map. The eligible weighted ring and each concrete backend/model assignment are frozen into `state.json`, so dispatch timing, config edits, and `/v:resume` cannot silently move an in-flight job.

Pool routing remains inside the existing safety boundary: pooled jobs require worktree isolation; reviewers, deep-tier work, sensitive surfaces, `xhigh`, explicit manifest models, and `advisor_backend: pool` are rejected. The dispatcher passes only the resolved concrete backend/model to adapters, failure classification, usage, memory, scorecards, and status. As refined by the cooldown recovery entry above, the first short throttle/overload preserves the assignment; subsequent or explicitly timed transient failures may cooldown and advance through the validated transition, while confirmed permanent exhaustion opens its circuit. Canonical health state and resume assignments are validated fail-closed.

`claude` is not included in the shipped pool example because its usage limit is shared with the operator's interactive Claude/Claude Code session; adding it is an explicit opt-in. This change is merge-dependent on the z.ai backend in PR #5, but does not claim that PR is already merged.

#### What this does not show

Weighted rotation distributes **job counts**, not tokens, credits, messages, wall-clock time, quota burn, savings, or provider capacity. Those meters are heterogeneous and are not visible through Compound V's CLI-process transport; no balance percentage or improvement metric is produced. z.ai's credit multiplier also varies by time of day, so equal job counts can consume unequal credits even on the same provider.

## [2.18.0] - 2026-08-01

### Added — `zai`, a headless GLM worker backend (lower-trust, opt-in, WORKER-ONLY)

A sixth dispatch backend, so codex, claude and z.ai can run jobs concurrently on separate
quotas. It is a Bash-spawned `claude -p` process pointed at z.ai's Anthropic-compatible
endpoint, in its own git worktree, under the process-group supervisor, with the dispatcher's
provider credentials scrubbed by `env -i` and `HOME`/`CLAUDE_CONFIG_DIR` redirected to a
scratch directory. z.ai ships no headless CLI of its own; Claude Code is a tier-1 officially
supported tool for the GLM Coding Plan, so driving the genuine binary is the compliant path.

Enforcement is unchanged — the existing git-derived scope gate. **There is no kernel
write-confinement**: the worktree plus `git diff` detects an in-worktree scope leak but cannot
prevent an out-of-worktree side effect, the same trust tier as antigravity and cursor. `zai`
is worker-only: never a reviewer (rejected by the manifest validator) and never an arbiter
seat (`model_family()` carries no `glm` needle, so a GLM ballot would bucket as `unknown`).

- `scripts/compound-v-run-zai-worker.sh`, `skills/backend-launcher/adapter-zai.md`.
- Tier map `deep`/`standard` → `glm-5.2`, `light` → `glm-5-turbo`. `light` is chosen on a
head-to-head measurement, not the multiplier table: turbo is 16% faster and glm-4.7 only 7%
cheaper in practice, because glm-4.7 emits ~60% more output.
- `job_result.usage` carries **real** token counts from z.ai's own response (`measured: true`).
The CLI's `total_cost_usd` is never carried — it is computed from Anthropic's price table for
a model that never ran.
- Failure classification uses z.ai's **published** 429 codes (`1113, 1302, 1305, 1308, 1310,
1311, 1316, 1317`). No `Retry-After` header exists, and enforcement throttling is
indistinguishable on the wire from ordinary rate limiting, so the retry ceiling stays low and
the breaker opens early.
- Default `max_parallel` for zai is 4. Six concurrent jobs measured clean, but z.ai publishes
no concurrency limit and adjusts it by plan tier.

### Fixed

- **A z.ai quota wall no longer halts a run.** `FALLBACK` in `compound-v-failure-policy.py`
had no `zai` key; a missing key reads as `None`, which the policy turns into `halt`. (`devin`
and `opencode` are still absent from that table — pre-existing, untouched here.)
- **`compound-v-usage-extract.py` now parses `--output-format json` as a JSON document.**
Line-wise parsing silently yielded nothing the moment the document was pretty-printed.

### CI

Two gates that did not exist are now enforced: `shellcheck` over `scripts/*.sh` (it covered
only `hooks/*.sh`, leaving every worker script unlinted) and a step that runs the
`scripts/test-*.sh` suites (nothing ran them; the sweep covered `scripts/*.py` only).

A new `scripts/test-zai-wire-smoke.sh` runs the **real** `claude` binary against a local stub
HTTP server — no network, no key, no quota — and asserts the tool set that actually reaches
the wire. That check exists because argv assertions cannot catch this class of defect:
`--allowedTools` decides which tools run unprompted, `--tools` decides which tools exist, and
an earlier draft of this backend pinned only the former and shipped a worker with `Bash` it
meant to withhold and no `Write` at all.
## [2.17.0] - 2026-07-26

### Added — Co-change advisory (ordered, git-derived) + failure-prioritized evidence packing
Expand Down
Loading
Loading