| name | push |
| description | The authoritative pre-push procedure for the cgg repo. Run before every `git push` (and before opening a release). It defines how to refresh every autogenerated README component (mermaid graphs, self-stats, benchmark table, language count/table), how to keep the Limitations and Potential-future-improvements sections honest against the code, the rule that EVERY factual claim in README.md must be neurosymbolically validated — proven by a deterministic symbolic check (cgg itself, rg/grep, cargo test, docs-check.py, `cgg --help`), not asserted from memory — and how version numbers are incremented (Cargo.toml workspace + internal pins, Cargo.lock, CHANGELOG.md). Trigger when about to push, cut a release, or bump a version in the cgg repo. |
push — the cgg pre-push contract
A push is a publish. The README is cgg's public contract: agents read
it, users trust its numbers, and the autogenerated blocks are assumed
to match the binary that produced them. This skill is the gate that runs
before git push so nothing stale, unproven, or mis-versioned
leaves the repo.
It composes with two existing pieces and adds the parts they don't cover:
.githooks/pre-commit regenerates the two embedded mermaid blocks and
the self-stats line, runs the test suite, and runs docs-check.py.
- The
docs-sync skill is the per-edit drift checklist for prose/tables.
This skill is the whole-README, whole-repo final pass plus the
versioning procedure. Do all of it before pushing.
0. Preconditions
cargo build --release -p cgg
If the build fails, stop — every downstream number would be wrong.
1. Refresh every autogenerated README component
The README contains four machine-generated regions. Never hand-edit
them; regenerate from the freshly built binary so they describe the code
you are about to push.
| Region | Marker / location | Regenerate with |
|---|
| cgg-walk graph | <!-- cgg:begin:walk --> … :end:walk | cgg ./crates/cgg-walk -t mermaid -o walk.mmd then scripts/update-readme-graphs.py walk walk.mmd … |
| cgg-lang graph | <!-- cgg:begin:lang --> … :end:lang | cgg ./crates/cgg-lang/src/{detect,parser,lib}.rs -t mermaid -o lang.mmd then scripts/update-readme-graphs.py … lang lang.mmd |
| self-analysis stats | <!-- cgg:begin:self-stats --> … :end:self-stats | cgg ./crates --filter 'cgg::run$' -n 1 … piped to scripts/update-readme-stats.py |
| benchmark table | the per-language table under "## Self-analysis"/benchmark | scripts/benchmark.sh (clones repos; multi-minute) then scripts/update-readme-stats.sh / scripts/patch-readme-stats.py |
The first three are exactly what .githooks/pre-commit runs — so a
normal git commit already refreshes them. Verify, don't assume: the
graphs and self-stats can be stale on disk if a prior commit used
--no-verify or CGG_SKIP_PRECOMMIT=1. Run the regen and confirm
git diff README.md shows either nothing or only the expected
regenerated lines.
The benchmark table is NOT touched by the hook. If your change could
move per-language numbers (new language, resolver change, stdlib tuning,
perf work), re-run scripts/benchmark.sh and patch the table. If it
can't, say so explicitly in the push notes rather than shipping numbers
you didn't re-measure — silent staleness reads as "freshly measured."
2. Keep Limitations and Potential-future-improvements honest
These two prose sections rot silently because no generator owns them.
Before every push, re-derive each bullet from the code:
- Every "future improvement" must still be unimplemented. For each
bullet, find the symbolic proof that it has NOT happened (or has only
partially happened). If the code now does it, move it out of the
list — to the feature table, the CHANGELOG, or delete it. Partial
progress gets rewritten to name exactly what remains (e.g. "8 stdlib
lists remain: csharp, fortran, java, …"), never left as a blanket
claim.
- Every "limitation" must still be true. A limitation that the code
has since fixed is a lie in the contract. Prove each one still holds
(no watch mode → no
watch/notify in cli.rs; Tcl/Hack absent →
not in plugins.rs; macros not expanded → no preprocessor sim).
Validation patterns (these are the symbolic half of §3, applied to prose):
rg -n 'trait_impl_target' crates/cgg/src/main.rs
git log --oneline -- crates/cgg-core/src/stdlib/
rg -niE 'watch|daemon|notify' crates/cgg/src/cli.rs
rg -n 'register\(' crates/cgg-lang/src/plugins.rs
3. Neurosymbolic validation of ALL README claims (mandatory gate)
Rule: no claim ships unproven. Before push, every factual assertion
in README.md must be validated neurosymbolically — the neural half
(reading the prose, deciding what it asserts) is paired with a
symbolic half (a deterministic check that proves it against the
actual code or tooling). An assertion you can only support "from
memory" or "it was true last release" is not validated; soften it,
remove it, or go prove it.
Symbolic oracles available in this repo — prefer them in this order:
- cgg itself — the strongest oracle. Counts, edges, cross-file
numbers, "resolves method dispatch", "finds cross-file edges":
run cgg on a fixture/the repo and read the real numbers.
cgg --help — the source of truth for the CLI flag table. Every
row in "## CLI" must exist in --help; this is enforced by
docs-check.py and must pass.
cargo test --workspace — behavioral claims backed by tests
(detection rules, resolver behavior, format output).
rg/grep over crates/ — existence claims: a language is
supported, a flag exists, an FFI form is detected, a resolver phase
runs in a given order.
scripts/docs-check.py — the consistency invariants (plugin
count == README "(N)" heading == language-table rows == benchmark
REPOS count; every README flag exists in --help). Must exit 0.
scripts/benchmark.sh — the only oracle for the benchmark
numbers. If you didn't run it, you didn't validate them.
Claim classes and their required proof:
| Claim in README | Symbolic proof required |
|---|
| "Supports N languages" / language table | rg -c 'register\(' plugins.rs, registry test, docs-check.py |
| Any CLI flag / default | appears in cgg --help |
| Counts in self-stats / benchmark | regenerated by the binary / benchmark.sh |
| "resolves X" / "links cross-file" / FFI | a cgg run that produces the edge, or a passing test |
| Pipeline phase order | matches cgg::run in crates/cgg/src/main.rs |
| A limitation / future gap | the absence proof from §2 |
If a claim has no available oracle, it does not belong in the README as
a fact — rephrase it as clearly-marked intent or cut it.
4. Version increment policy
cgg is pre-1.0 and follows a loose SemVer (see CHANGELOG.md preamble:
the default graph only ever grows). Increment by the largest category
the change touches:
- PATCH (
0.2.0 → 0.2.1) — bug fixes, doc-only changes, stdlib list
tuning, internal refactors. No new user-visible surface.
- MINOR (
0.2.0 → 0.3.0) — additive contract surface: a new
language, a new flag, a new output format, a new resolver phase, new
audit fields. This is the common case for feature work.
- MAJOR (
→ 1.0.0) — reserved for the 1.0 stability commitment.
Pre-1.0, behavior changes that would otherwise be "breaking" ship as
MINOR with a ### Compatibility / migration note in the CHANGELOG;
the default graph must remain a superset of the prior release.
When you bump, change all of these in one commit, then validate:
Cargo.toml → [workspace.package] version (one line).
Cargo.toml → the five internal pins under [workspace.dependencies]
(cgg-core/cgg-lang/cgg-resolve/cgg-format/cgg-walk). They
must match the workspace version.
Cargo.lock → refresh by running cargo build (rewrites the six
cgg* entries). Stage the result; the pre-commit hook does not.
CHANGELOG.md → add ## [x.y.z] - YYYY-MM-DD (today's date) at the
top, with ### Added / ### Changed / ### Fixed / ### Compatibility
subsections as applicable. Match the existing entry's voice.
Symbolic check after bumping:
rg -n '0\.2\.0' Cargo.toml
cargo build --release -p cgg
cgg --version
5. Final push sequence
cargo test --workspace
scripts/docs-check.py
git add -A
git commit -m "…"
git push origin main
Let the pre-commit hook run — do not --no-verify a push. If the hook
restages README.md, that is the autogen blocks correcting themselves;
inspect the diff, it should be only generated regions.
What this skill does NOT do
- It does not replace
docs-sync (the per-edit drift checklist) — it
assumes that ran and does the final whole-repo sweep.
- It does not auto-bump the version — versioning is a judgment call
(§4); decide the category, then apply it everywhere at once.
- It does not invent benchmark numbers — unmeasured numbers are not
shipped; either re-run
benchmark.sh or state that they were not
re-measured.