Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
17 changes: 9 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion docs/superpowers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ Master status index for all specs and implementation plans in this directory.
| Make `cargo semver-checks` blocking | It runs today but cannot fail a PR: `ci.yml:158` sets `continue-on-error: true`, and `auto-merge` `needs: [test, cargo-audit, secret-scan, snyk-scan, docs-lint, docs-build]` excludes it. The blocker is `enum_variant_added` — `CLAUDE.md` documents that every new action adds a public enum variant, so the check is permanently red by construction. Fix is `#[non_exhaustive]` on the action enum (which makes variant addition non-breaking), then remove `continue-on-error` and add the job to `auto-merge needs:`. Not a config toggle — the `#[non_exhaustive]` change is itself semver-breaking and needs its own cycle. |
| Close the `pre-push` Python trigger gap | `scripts/pre-push`'s pattern matches neither `scripts/*.py`, `tests/*.py`, `ruff.toml`, `Makefile`, nor `requirements-ci-test.txt`, so every Python-only or toolchain-only change skips the local hook and is gated on the CI side alone. Pre-existing (already noted in `CLAUDE.md`), but the pytest migration and the vendored rendering both widened what lands on the CI-only side. Fix is one regex in the hook plus a test that a Python-only staged change actually triggers it. |
| Property tests for the roundtrip paths | `tdd.md:72` requires a property test for every invertible or idempotent operation. **1 of 5 `Cargo.toml` declares `proptest` and 1 `.rs` file uses `proptest!`**, against math's 11 of 11 and 12 files. etch-cli has qualifying roundtrips: manifest YAML/TOML deserialization, the state manifest's serialize/deserialize path, and `etch rollback`'s `restore(stash(x)) == x`. Wants its own cycle with real properties, not a trivial one added to satisfy a count. |
| Bump `gix` in `fuzz/Cargo.lock` | `fuzz/` is `exclude`d from the workspace and carries its **own** lockfile, still resolving gix 0.80.0. It accounts for **10 of the 14** Dependabot alerts remaining after #128. Not reachable from the workspace bump — needs `cargo update` run inside `fuzz/`. Worth noting the gap it exposed: nothing in this repo's gates looks at that lockfile at all, and the post-merge alert count was predicted at ~5 because the prediction counted alerts by package without checking `manifest_path`. |
| Bump `fuzz/Cargo.lock` | `fuzz/` is `exclude`d from the workspace and carries its **own** lockfile, still resolving gix 0.80.0. It accounts for **10 of the 14** Dependabot alerts remaining after #128, and it still pins rustls 0.23.40 — RUSTSEC-2026-0285, the advisory the workspace lockfile was bumped for. Not reachable from the workspace bump — needs `cargo update` run inside `fuzz/`, which re-resolves ~566 lines because the file has not moved since 2026-05-24, so it wants its own change rather than riding along with a targeted fix. Worth noting the gap it exposed: nothing in this repo's gates looks at that lockfile at all, and the post-merge alert count was predicted at ~5 because the prediction counted alerts by package without checking `manifest_path`. |
| Renovate has never run in this repo | Zero Renovate PRs, all time. `renovate.json` extends `github>brujack/ai-config//renovate-presets/default.json`; **ai-config is private and etch-cli is public**, and Renovate resolves `extends` at `initRepo` *before* dependency extraction, so an unfetchable preset abandons the whole repository. Config has been correct and inert since 2026-05-24. Perfect split fleet-wide: the three private repos got PRs, the three public ones got none. Fix is to inline the 14-line preset (`config:recommended` + schedule/labels/packageRules); ai-config and state-ledger have done so. Until then `pinDigests: true` cannot converge anything. |
| `cargo deny` and Dependabot read different advisory corpora | `cargo deny check advisories` reads **RustSec**; Dependabot reads the **GitHub Advisory Database**. Verified: `GHSA-fr8x-3vfx-f45h` and `GHSA-pg4w-g64p-qwhj` carry **no RUSTSEC ID**, so the `cargo-audit` CI job — which is in `auto-merge`'s `needs:` and therefore blocking — reports `advisories ok` on a tree with 23 open high alerts. The gate is sound about RustSec and silent about GHSA. Fleet-wide: every Rust repo gated only on cargo-deny has this blind spot. Cross-cutting, so `rust.md`'s Security Scanning section is the likely destination. |

Expand Down
38 changes: 15 additions & 23 deletions tests/test_requirements_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,33 +262,25 @@ def test_rust_coverage_floor_matches_every_documented_figure(self):
f"ci.yml gates Rust coverage at {gate[0]}% but CLAUDE.md claims {flat}.",
)

def test_ci_python_version_matches_the_platform_invariance_argument(self):
"""CLAUDE.md justifies a locally-measured coverage floor on the grounds
that the suite's only conditional skip is gated to 3.14+ and CI pins
3.13, so it skips identically in both places. Bump CI to 3.14 and that
justification is silently false: the skipped test starts running and the
measured figure moves. The argument depends on a value in another file,
so the dependency is asserted rather than assumed.
def test_ci_python_pin_keeps_the_zstd_test_skipped(self):
"""The Python coverage floor was measured with the suite's only
conditional skip (the compression.zstd test, 3.14+) not running. That
holds only while CI pins below 3.14; bump the pin and the skipped test
starts running and the measured figure moves. The reasoning lives in
ai-config's etch-cli-ci-python-tooling knowledge file, so the invariant
is asserted here against ci.yml directly rather than against prose.
"""
pinned = re.findall(r'python-version:\s*"([\d.]+)"', self.ci)
pinned = re.findall(r'python-version:\s*"(\d+)\.(\d+)(?:\.\d+)?"', self.ci)
self.assertEqual(
len(pinned), 1, f"expected one python-version pin, found {pinned}"
)
claimed = re.findall(
r"CI pins\s*\n?Python ([\d.]+)|Python ([\d.]+), so that test skips",
self.claude_md,
)
flat = sorted({v for pair in claimed for v in pair if v})
self.assertTrue(
flat,
"CLAUDE.md's platform-invariance argument names no Python version; if that "
"reasoning was removed, remove this assertion with it.",
)
self.assertEqual(
flat,
[pinned[0]],
f"ci.yml pins Python {pinned[0]} but CLAUDE.md's coverage-floor justification "
f"depends on {flat}. That justification is now false.",
version = tuple(int(part) for part in pinned[0])
self.assertLess(
version,
(3, 14),
f"ci.yml pins Python {version[0]}.{version[1]}; the compression.zstd "
"test now runs in CI, so re-derive the Python coverage floor from CI "
"output before raising this bound.",
)


Expand Down
Loading