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
6 changes: 5 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
# merge-base. ~50 commits, so the full history costs nothing here.
fetch-depth: 0

# The hook, the two checkers, the three Python reports and their six suites are
# The hook, the two checkers, the four Python reports and their seven suites are
# the only executables here,
# so lint plus those suites are the only mechanical gates we have. Everything else
# here is a prompt, and prompts have no typechecker (see README, "Contributing").
Expand Down Expand Up @@ -82,6 +82,9 @@ jobs:
# The loop-usefulness suite (vision step 2c, part 2), linted the same way.
docker run --rm -v "$PWD:/mnt" -w /mnt koalaman/shellcheck:v0.11.0 \
--shell=sh --exclude=SC2015 scripts/loop-usefulness.test.sh
# The spec-delta suite (vision step 2c, part 3), linted the same way.
docker run --rm -v "$PWD:/mnt" -w /mnt koalaman/shellcheck:v0.11.0 \
--shell=sh --exclude=SC2015 scripts/spec-delta.test.sh

# Two runs, because the hook has to be correct under both shells and the runner's
# /bin/sh is dash while a contributor's may be bash. HOOK_SH selects the shell the
Expand Down Expand Up @@ -110,6 +113,7 @@ jobs:
sh scripts/ledger-metrics.test.sh
sh scripts/run-analytics.test.sh
sh scripts/loop-usefulness.test.sh
sh scripts/spec-delta.test.sh

# Invariant 12 itself needs a base to diff against, so it runs only on pull
# requests — a push to main has no PR base, and diffing the push range would just
Expand Down
17 changes: 10 additions & 7 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ scripts/run-analytics.py # gate-call effort from local logs (vision ste
scripts/run-analytics.test.sh # its regression suite — fixture home + repos, expected text
scripts/loop-usefulness.py # warning light over recorded review cycles (vision step 2c, part 2)
scripts/loop-usefulness.test.sh # its regression suite — fixture repo + store, expected text
scripts/spec-delta.py # spec/plan change since a given baseline, for Gate B (vision step 2c, part 3)
scripts/spec-delta.test.sh # its regression suite — fixture repo, expected text
plugins/dev-workflow/
.claude-plugin/plugin.json # metadata only — no component keys (invariant 6)
CHANGELOG.md # every manifest version, newest first
Expand All @@ -68,8 +70,9 @@ source-files/ # the extraction seed this repo was built from
**Boundaries.** `skills/`, `commands/`, `agents/` and `hooks/hooks.json` are loaded by convention
from their paths. The executable artifacts are the hook and its test, plus the two
repo-local CI checkers and their tests (`scripts/check-invariants.{sh,test.sh}` and
`scripts/check-version-bump.{sh,test.sh}`), plus three Python reports with their suites:
`scripts/ledger-metrics.{py,test.sh}` and `scripts/loop-usefulness.{py,test.sh}` (read-only),
`scripts/check-version-bump.{sh,test.sh}`), plus four Python reports with their suites:
`scripts/ledger-metrics.{py,test.sh}`, `scripts/loop-usefulness.{py,test.sh}` and
`scripts/spec-delta.{py,test.sh}` (read-only),
and `scripts/run-analytics.{py,test.sh}` (writes only its own store under
`.context/telemetry/`) — the hook ships in the plugin, the checkers and the reports do not; everything else is text read by a model. `examples/` is reference material,
outside the loaded surface: never scaffolded or copied into a user's project, though it
Expand Down Expand Up @@ -261,9 +264,9 @@ Every command below was run in this session and observed to exit 0.

| Role | Command |
|---|---|
| quality (the whole battery — what CI runs) | `shellcheck --shell=sh plugins/dev-workflow/hooks/codex-gate.sh && shellcheck --shell=sh --exclude=SC2015 plugins/dev-workflow/hooks/codex-gate.test.sh && shellcheck --shell=sh scripts/check-invariants.sh && shellcheck --shell=sh --exclude=SC2015 scripts/check-invariants.test.sh && shellcheck --shell=sh scripts/check-version-bump.sh && shellcheck --shell=sh scripts/check-version-bump.test.sh && shellcheck --shell=sh --exclude=SC2015 scripts/ledger-metrics.test.sh && shellcheck --shell=sh --exclude=SC2015 scripts/run-analytics.test.sh && shellcheck --shell=sh --exclude=SC2015 scripts/loop-usefulness.test.sh && HOOK_SH=sh sh plugins/dev-workflow/hooks/codex-gate.test.sh && HOOK_SH=dash dash plugins/dev-workflow/hooks/codex-gate.test.sh && sh scripts/check-invariants.test.sh && sh scripts/check-invariants.sh && sh scripts/check-version-bump.test.sh && sh scripts/check-version-bump.sh main && sh scripts/ledger-metrics.test.sh && sh scripts/run-analytics.test.sh && sh scripts/loop-usefulness.test.sh && claude plugin validate . --strict` |
| typecheck | n/a — no typed sources (shell, three untyped Python reports, markdown) |
| lint | `shellcheck --shell=sh plugins/dev-workflow/hooks/codex-gate.sh && shellcheck --shell=sh --exclude=SC2015 plugins/dev-workflow/hooks/codex-gate.test.sh && shellcheck --shell=sh scripts/check-invariants.sh && shellcheck --shell=sh --exclude=SC2015 scripts/check-invariants.test.sh && shellcheck --shell=sh scripts/check-version-bump.sh && shellcheck --shell=sh scripts/check-version-bump.test.sh && shellcheck --shell=sh --exclude=SC2015 scripts/ledger-metrics.test.sh && shellcheck --shell=sh --exclude=SC2015 scripts/run-analytics.test.sh && shellcheck --shell=sh --exclude=SC2015 scripts/loop-usefulness.test.sh` |
| quality (the whole battery — what CI runs) | `shellcheck --shell=sh plugins/dev-workflow/hooks/codex-gate.sh && shellcheck --shell=sh --exclude=SC2015 plugins/dev-workflow/hooks/codex-gate.test.sh && shellcheck --shell=sh scripts/check-invariants.sh && shellcheck --shell=sh --exclude=SC2015 scripts/check-invariants.test.sh && shellcheck --shell=sh scripts/check-version-bump.sh && shellcheck --shell=sh scripts/check-version-bump.test.sh && shellcheck --shell=sh --exclude=SC2015 scripts/ledger-metrics.test.sh && shellcheck --shell=sh --exclude=SC2015 scripts/run-analytics.test.sh && shellcheck --shell=sh --exclude=SC2015 scripts/loop-usefulness.test.sh && shellcheck --shell=sh --exclude=SC2015 scripts/spec-delta.test.sh && HOOK_SH=sh sh plugins/dev-workflow/hooks/codex-gate.test.sh && HOOK_SH=dash dash plugins/dev-workflow/hooks/codex-gate.test.sh && sh scripts/check-invariants.test.sh && sh scripts/check-invariants.sh && sh scripts/check-version-bump.test.sh && sh scripts/check-version-bump.sh main && sh scripts/ledger-metrics.test.sh && sh scripts/run-analytics.test.sh && sh scripts/loop-usefulness.test.sh && sh scripts/spec-delta.test.sh && claude plugin validate . --strict` |
| typecheck | n/a — no typed sources (shell, four untyped Python reports, markdown) |
| lint | `shellcheck --shell=sh plugins/dev-workflow/hooks/codex-gate.sh && shellcheck --shell=sh --exclude=SC2015 plugins/dev-workflow/hooks/codex-gate.test.sh && shellcheck --shell=sh scripts/check-invariants.sh && shellcheck --shell=sh --exclude=SC2015 scripts/check-invariants.test.sh && shellcheck --shell=sh scripts/check-version-bump.sh && shellcheck --shell=sh scripts/check-version-bump.test.sh && shellcheck --shell=sh --exclude=SC2015 scripts/ledger-metrics.test.sh && shellcheck --shell=sh --exclude=SC2015 scripts/run-analytics.test.sh && shellcheck --shell=sh --exclude=SC2015 scripts/loop-usefulness.test.sh && shellcheck --shell=sh --exclude=SC2015 scripts/spec-delta.test.sh` |
| test | `HOOK_SH=sh sh plugins/dev-workflow/hooks/codex-gate.test.sh && HOOK_SH=dash dash plugins/dev-workflow/hooks/codex-gate.test.sh` — two runs; `HOOK_SH` selects the shell the HOOK runs under, and without it a dash invocation only exercises the harness |
| invariant checks (5 pinning, 6 manifest, prompt conformance) | `sh scripts/check-invariants.test.sh && sh scripts/check-invariants.sh` |
| invariant check (12 version bump) | `sh scripts/check-version-bump.test.sh && sh scripts/check-version-bump.sh main` |
Expand All @@ -278,8 +281,8 @@ invariant 5; `dash` is addressed by name because it is the system shell, not a p
tool. Without it the second run cannot start, and dropping that run is what let a
`dash`-only defect ship once already. The metrics report's suite also needs
**`python3`** 3.8 or later, addressed by name for the same reason as `dash`: it is the
system interpreter, not a pinned tool. `scripts/run-analytics.py` and `scripts/loop-usefulness.py`
also need git 2.36 or later and check for it.
system interpreter, not a pinned tool. `scripts/run-analytics.py`, `scripts/loop-usefulness.py` and
`scripts/spec-delta.py` also need git 2.36 or later and check for it.

**The `--exclude=SC2015` on the test file** is a single-code exclusion, not a blanket
disable: every other shellcheck rule still applies to that file. Its hits are all
Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ CI ([`.github/workflows/ci.yml`](.github/workflows/ci.yml)) runs four checks on
PR and push to main: `shellcheck --shell=sh` over the three shell executables and every
shell test file, the hook's test suite,
[`scripts/check-invariants.sh`](scripts/check-invariants.sh) (invariants 5 and 6, plus three prompt-conformance checks) plus
both checkers' regression suites, the three reports' suites, and
both checkers' regression suites, the four reports' suites, and
`claude plugin validate . --strict`.

`python3 scripts/ledger-metrics.py` prints a read-only report over the hardening ledger
Expand All @@ -179,6 +179,12 @@ no warning where no threshold is reached, and not determinable where missing or
data leaves the state open. It does not say whether a loop was worth its effort, and it writes
nothing (`-B` keeps the interpreter from writing bytecode too).

`python3 -B scripts/spec-delta.py --base <baseSha> --baseline <commit>:<spec> … [<head>]` shows a
Gate-B reviewer how each relevant spec and plan changed since a baseline you name, usually the
commit that closed its Gate-A cycle. It quotes that commit's cycle records and names any
ambiguity. It does not claim the cycle reviewed exactly that file, and it informs without
obliging anything. It writes nothing.

A fifth check runs **on pull requests only**:
[`scripts/check-version-bump.sh`](scripts/check-version-bump.sh) (invariant 12), which
needs a base branch to diff against. Its *suite* runs unconditionally with the others;
Expand Down
Loading