Register the Hermes YAML manifest alongside the existing JSON manifests. Route manifest reads and writes by extension through jq or Mike Farah yq v4, with field names and values passed as data.
Preflight every present manifest before the mutating bump loop so a deterministic YAML read failure cannot leave earlier JSON manifests partially updated. Cover check, audit, bump, registry wiring, and byte-for-byte no-partial-write behavior with one focused fixture test.
Record Drew's approved reduced design after the second staff review. Limit preflight to the mutating bump path, cover audit's independent read path, and require byte-for-byte proof that deterministic YAML failures cannot partially update earlier JSON manifests.
Provide one TDD implementation task for the Hermes registry entry, jq/yq dispatch, focused preflight, and three behavioral checks. Explicitly defer rollback, audit-status changes, nested YAML, runtime changes, and broader release-tool refactoring.
Incorporate the adversarial design review without turning the Hermes wiring follow-up into a general release-script refactor. Keep the existing jq path, add Mike Farah yq v4 only for .yaml, and retain one read-only preflight to prevent deterministic partial bumps.\n\nReduce the test contract to three behavioral cases and explicitly defer .yml support, nested YAML, rollback machinery, audit/status redesign, exhaustive failure matrices, and the separately discovered JSON-expression issue. This follows Drew's direction to avoid ceremony and overengineering.
Document the agreed follow-up to PR #2025 on a branch based on its merged dev commit. The design registers the Hermes YAML manifest, keeps jq for existing JSON files, and uses Mike Farah yq v4 for a narrow top-level YAML field rather than adding a Bash parser.\n\nDefine focused failure behavior and behavioral tests while explicitly excluding nested YAML, Hermes runtime changes, and unrelated release-script refactors. This captures Drew's request to keep the implementation small and avoid process or abstraction overhead.
`git status --porcelain` collapses a wholly-untracked directory to a single
`?? docs/` line. In the shape of the incident this step exists for (#2016 — an
uncommitted plan document under an untracked `docs/` tree), the file list we
show the human partner therefore names no file at all:
$ git -C "$WORKTREE_PATH" status --porcelain
?? docs/
$ git -C "$WORKTREE_PATH" status --porcelain -uall
?? docs/superpowers/plans/2026-08-04-csv-export-rollout.md
Both forms produce identical (empty) output on a clean worktree, so this adds
no over-trigger surface.
Found while running this PR's behavioral micro-tests. Every treatment agent
dug past `?? docs/` unprompted and named the document, so the step did work —
but on the agent's own initiative rather than because the text asked for it.
That initiative is not reliable one tier down: Claude Haiku 4.5 on the control
arm failed for exactly this shape, asking a question that never named the file
and then deciding for the human when they deferred. Nothing in the prior
wording stopped a treatment agent from relaying `?? docs/` verbatim and
satisfying the letter of the instruction.
Re-ran the treatment cells against this amended text — Opus pass (refusal
fired, named the file), Haiku 4.5 pass (named the file) — no regression.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Update the Hermes plugin manifest from 6.1.1 to 6.2.0 so PR #2025 matches the current release version at the tip of origin/dev.\n\nThis intentionally does not change the version bump tooling. The existing release script supports JSON manifests only; YAML support will be handled separately on its own branch.
Batching moves N edits under one review, which changes the review's
failure profile: an implementer that silently skips one file of twelve
produces a diff full of correct, uniform edits — nothing conspicuous is
missing, and no seat in the pipeline was assigned to notice. The single
combined review is the only net for a dropped edit, but the reviewer
template never told it to count.
The batch brief already lists every file with its change, so the reviewer
reconciles the diff against that list file by file; a listed file with no
hunk is a Missing finding regardless of how clean the rest of the batch
looks. Conditional on a multi-file brief, so single-task reviews are
unchanged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Both PRs rewrote the same preflight paragraph. Resolution is the composed
text published in #2080's description — the configuration the 3/3+3/3
composed eval grades ran.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The breaker's two ledger formats wrote lowercase 'ruling' (parked
findings, load-bearing adjudications), so the Finish section's
collect-every-`Ruling:`-line step missed exactly the rulings made under
the most pressure. Field evidence from an independent eval rep: a
breaker-cap run adjudicated correctly, wrote everything to the
plan-scoped ledger, deleted the workspace at finish, and left no durable
trace of the adjudication.
Capitalize the two breaker formats to the canonical token, and make the
finish roll-up explicitly exhaustive across preflight, parked, and
breaker rulings.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
hooks/session-start-codex has had no caller since "Remove Codex hooks"
(#1845) deleted hooks-codex.json and its manifest registration; the
Codex manifest now declares an empty hooks object so Codex registers no
session-start hook at all. The script is Codex-specific dead code —
nothing executes it on Codex or any other harness.
- Delete hooks/session-start-codex.
- tests/hooks/test-session-start.sh: drop the two Codex cases that are
redundant with the generic session-start tests (nested-format and the
legacy-warning omission are already covered by the Claude Code cases).
Re-point the "wrapper dispatches" case to the live `session-start`
script so run-hook.cmd dispatch coverage — used by Claude Code and
Cursor in production — is preserved rather than lost.
- docs/porting-to-a-new-harness.md: Codex is no longer a Shape A
(shell-hook) harness, so re-anchor that worked example to Cursor (a
live shell-hook harness that demonstrates the same per-harness field,
schema, and matcher variance) and mark Codex as native skill discovery
with no session-start hook. Clears the references to the deleted
hooks-codex.json.
- docs/windows/polyglot-hooks.md: the "check hooks-codex.json" pointer
referenced a file deleted in #1845; re-point to hooks-cursor.json.
RELEASE-NOTES.md keeps its historical mention of hooks-codex.json (it
accurately records what that release did). The tests/codex-plugin-sync
fixtures build their own synthetic session-start-codex and test the sync
mechanism generically, so they are intentionally left as-is.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Codex auto-discovers a plugin's hooks/hooks.json whenever the Codex
manifest has no `hooks` field: load_plugin_hooks falls back to a
hardcoded DEFAULT_HOOKS_CONFIG_FILE = "hooks/hooks.json" and registers
it. hooks/hooks.json is the Claude Code SessionStart hook, it is tracked
in this repo, and the Codex marketplace installs the whole repo root
(source url "./"), so the fallback re-registered the SessionStart hook
and its install-time trust prompt on Codex.
Removing the Codex hook file and the manifest `hooks` pointer (commit
"Remove Codex hooks") did not disable the hook on Codex — it removed the
explicit declaration that was overriding the fallback, so the fallback
took over and found the Claude hooks/hooks.json.
Declare an empty inline hooks object ({}) in .codex-plugin/plugin.json.
It parses as an empty inline hook set and stops Codex reaching the
auto-discovery fallback. An absent field, an empty array ([]), and an
empty inline list all collapse back to the fallback, so the value must
be exactly {}.
Update the test to assert the manifest declares hooks: {} (and that
hooks/hooks.json exists, which is what makes the declaration necessary),
replacing the prior assertion that the field was absent — which passed
while the hook was still being auto-discovered.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
hooks/session-start-codex has had no caller since "Remove Codex hooks"
(#1845) deleted hooks-codex.json and its manifest registration; the
Codex manifest now declares an empty hooks object so Codex registers no
session-start hook at all. The script is Codex-specific dead code —
nothing executes it on Codex or any other harness.
- Delete hooks/session-start-codex.
- tests/hooks/test-session-start.sh: drop the two Codex cases that are
redundant with the generic session-start tests (nested-format and the
legacy-warning omission are already covered by the Claude Code cases).
Re-point the "wrapper dispatches" case to the live `session-start`
script so run-hook.cmd dispatch coverage — used by Claude Code and
Cursor in production — is preserved rather than lost.
- docs/porting-to-a-new-harness.md: Codex is no longer a Shape A
(shell-hook) harness, so re-anchor that worked example to Cursor (a
live shell-hook harness that demonstrates the same per-harness field,
schema, and matcher variance) and mark Codex as native skill discovery
with no session-start hook. Clears the references to the deleted
hooks-codex.json.
- docs/windows/polyglot-hooks.md: the "check hooks-codex.json" pointer
referenced a file deleted in #1845; re-point to hooks-cursor.json.
RELEASE-NOTES.md keeps its historical mention of hooks-codex.json (it
accurately records what that release did). The tests/codex-plugin-sync
fixtures build their own synthetic session-start-codex and test the sync
mechanism generically, so they are intentionally left as-is.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Codex auto-discovers a plugin's hooks/hooks.json whenever the Codex
manifest has no `hooks` field: load_plugin_hooks falls back to a
hardcoded DEFAULT_HOOKS_CONFIG_FILE = "hooks/hooks.json" and registers
it. hooks/hooks.json is the Claude Code SessionStart hook, it is tracked
in this repo, and the Codex marketplace installs the whole repo root
(source url "./"), so the fallback re-registered the SessionStart hook
and its install-time trust prompt on Codex.
Removing the Codex hook file and the manifest `hooks` pointer (commit
"Remove Codex hooks") did not disable the hook on Codex — it removed the
explicit declaration that was overriding the fallback, so the fallback
took over and found the Claude hooks/hooks.json.
Declare an empty inline hooks object ({}) in .codex-plugin/plugin.json.
It parses as an empty inline hook set and stops Codex reaching the
auto-discovery fallback. An absent field, an empty array ([]), and an
empty inline list all collapse back to the fallback, so the value must
be exactly {}.
Update the test to assert the manifest declares hooks: {} (and that
hooks/hooks.json exists, which is what makes the declaration necessary),
replacing the prior assertion that the field was absent — which passed
while the hook was still being auto-discovered.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bumps evals 7f8e80c -> db37d5f (superpowers-evals#16): the claude launcher now
sets CLAUDE_CODE_FORCE_SESSION_PERSISTENCE=1 so nested interactive claude
(>=2.1.176) persists its transcript — restoring claude capture (verdicts +
cost/token data) on the latest CLI (2.1.177) with no version pin. Also folds in
the audit_liveness ruff/ty cleanup and the B1 audit-doc correction.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds `run-all --scenarios` for resuming a scenario subset across the Code
Assist rate-limit windows. Follows the agy rate-limit fix (79f9963).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Serialize antigravity against the Gemini Code Assist rate limit
(max_concurrency=1), diagnose 429/RESOURCE_EXHAUSTED honestly instead of as
auth, fail-fast on a latched window, and tolerant preflight OK match.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rsync exclude patterns without a leading "/" match any directory of
the given name at any depth. The previous "scripts/" pattern was
meant to exclude upstream's top-level scripts/ dir (which contains
sync-to-codex-plugin.sh itself, bump-version.sh, etc.) but also
incorrectly excluded skills/brainstorming/scripts/ — a legitimate
skill-adjacent dir with 5 files (frame-template.html, helper.js,
server.cjs, start-server.sh, stop-server.sh).
Found during a determinism check: comparing the hand-crafted
add-superpowers-plugin bootstrap PR against an automated bootstrap
PR produced a diff showing those 5 files were missing from the
automated version.
Fix: anchor every top-level-only exclude with a leading "/".
.DS_Store stays unanchored because Finder creates them anywhere.
This also prevents future drift if anyone adds a tests/, hooks/,
docs/, lib/, etc. subdir inside a skill.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Two coupled changes:
1. Add assets/ to EXCLUDES. A normal sync run was deleting
plugins/superpowers/assets/ via --delete because the corresponding
directory doesn't exist upstream. Confirmed via dry-run that the
previous version would wipe both brand asset files on next sync.
2. Add --bootstrap and --assets-src flags to support creating the
initial plugin PR from scratch. Bootstrap mode skips the
"plugin must exist on base" preflight, creates the plugin
directory, rsyncs upstream content, then copies
PrimeRadiant_Favicon.{svg,png} from --assets-src into
plugins/superpowers/assets/ as superpowers-small.svg and
app-icon.png. Run once by one team member to open the initial
PR; every subsequent run is a normal (non-bootstrap) sync.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The live .codex-plugin/plugin.json in the downstream fork was cleaned up
(websiteURL, privacyPolicyURL, termsOfServiceURL, and defaultPrompt
removed) and icon fields were added (composerIcon, logo pointing at
assets/superpowers-small.svg and assets/app-icon.png). Update the
heredoc to produce the same shape so future sync runs don't wipe the
icon fields or reintroduce the removed URL fields.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove CODE_OF_CONDUCT.md from EXCLUDES so it syncs from upstream
(per PR #1165 review feedback on the exclude list)
- Remove the agents/openai.yaml overlay generator and its exclude entry
— the file duplicates fields already in .codex-plugin/plugin.json and
only 6 of 28 upstream plugins ship one, so we match the 22-plugin
majority shape
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The previous version was a local rsync helper that required a hand-maintained
destination path. This rewrite makes it path/user-agnostic and gives every team
member the same flow:
- Clones prime-radiant-inc/openai-codex-plugins fresh into a temp dir per run
(trap EXIT cleans up)
- Auto-detects upstream from the script's own location
- Preflight: rsync, git, gh auth, python3, upstream package.json
- Reads upstream version from package.json and bakes it into the regenerated
.codex-plugin/plugin.json, so version bumps flow through
- Regenerates both overlay files (.codex-plugin/plugin.json and
agents/openai.yaml) inline via heredoc — single source of truth
- Pushes a sync/superpowers-<sha>-<UTC-timestamp> branch and opens a PR via
gh pr create; prints PR URL and /files diff URL on completion
- --dry-run, --yes, --base BRANCH, --local PATH flags for all the usual modes
- Deterministic: two runs against the same upstream SHA produce PRs with
identical diffs, so the tool itself can be sanity-checked by running twice
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>