Skip to content

docs(pins)!: report every pinned input's currency, and advance the charly and umbrella pins - #200

Merged
github-actions[bot] merged 1 commit into
mainfrom
feat/pin-currency-report-196
Oct 29, 2026
Merged

github-actions[bot] merged 1 commit into
mainfrom
feat/pin-currency-report-196

Conversation

@aitrawog

Copy link
Copy Markdown
Contributor

Closes #196

Summary

Head 4f824fca41725e9d133944ad9c4e67af61adf4dd — the commit this PR pushes: 133 files changed, 2782 insertions(+), 493 deletions(-) — 127 generated pages (50 added, 67 modified, 10 replaced by their newer version-stamped counterpart) and 6 control files (two new scripts, the two retired scripts deleted with them, the deploy workflow, and this repo's AGENTS.md).

The site stops trailing its producers, and nothing trails it silently any more. Two things land here, and they are the two halves of one question: is each pinned input the site is generated from current?

1 — the report. The site is generated from THREE pinned inputs: the guidance corpus (this repo's marketplace gitlink), the charly commit the deploy clones, and the umbrella commit the deploy clones. Every one of them is advanced by a MANUAL act after its producer lands, so the site trails its producers by however long nobody ran the regeneration PR — and the drift gate CANNOT see it, because the PINNED sources regenerate their own (old) pages perfectly. The drift gate answers "does the committed content match what the pinned inputs generate?" (yes, always); it never answers "is each pinned input itself current?".

.github/scripts/check_pin_currency.sh answers that second question for all three pins, and .github/scripts/check_corpus_currency.sh — which watched the corpus alone — is deleted in the same cutover (R5). The report speaks the pin contract's own vocabulary and its own states:

  • cur — at the producer's merged main. Obligates nothing.
  • behind — N commits behind the producer's merged main. An advance available NOW.
  • not-on-the-served-line — the pin is off the producer's main line. A squash-advance, whose one remedy is the same as behind's. NOT a divergence, and the report never calls it one.
  • undecidable — the producer's history is shallow and could not be deepened, so ancestry cannot be judged.
  • unreadable — the pin, or the producer's merged main, could not be read.

The answer is REPORTED, never failed. A pin that is behind is an advance available now — the same shape the pin contract calls behind: a reportable state, not a broken edge. A gate that FAILED on it would be red on every push until somebody ran the regeneration PR, and the remedy is that PR, not a gate. The report exits 0 in every state, and its fixtures assert that.

The judgment must be DECIDABLE before it is reported. merge-base --is-ancestor answers "not an ancestor" for a commit the clone does not have — indistinguishable from a real squash-advance. The corpus checkout in CI IS a depth-1 clone (actions/checkout runs git submodule update --init --force --depth=<fetch-depth> with its default fetch-depth: 1). A depth-1 history therefore cannot judge ancestry at all, and reporting from it would state a FALSE state — a divergence for a pin that is merely behind, with a wrong commit count. So a shallow history is DEEPENED first, and when the deepening cannot be done the report says undecidable and never guesses: a false state is worse than no report.

The pins are recorded ONCE. The two CI-time pins live in the workflow's own env: block, which the deploy's clone step consumes and this report reads — one record, one occurrence of each SHA in the whole repository, so a SHA can no longer be written in one place and forgotten in the other. The corpus pin is the committed gitlink, and it is read from the commit's TREE rather than from the checkout's HEAD: the checkout is a convenience, the tree entry is the pin.

2 — the two advances. charly moves bafd8dbc3110904872831998fb4caa701cc2990c → be7a505f476c1a5b0302d878e0b5686a2cde3e07 (97 commits behind, now cur), and the umbrella moves e631aacf32df4e26a66f2cb6a75fc9e85e212399 → 1c88fcf15f8fb9dd8b2814210472a63d3a79d0e2 (413 commits behind, now cur). Both were behind — valid states, both ancestors of their producer's merged main, neither a divergence. The pages each advance projects are regenerated in the same PR.

What the advance changes, measured. The umbrella's four root narratives — SOUL.md, VISION.md, GRIEVANCES.md, LIBERATION.md — are byte-identical across those 413 commits, so the umbrella's advance moves no narrative page; the charly advance moves the reference/** pages, which are the generator's output for the new tree.

What it found, and where it went. Two findings are separable from this change and are FILED, not folded in:

How tested

1 — the report's own fixtures, and the mutations that prove they can fail.

$ bash .github/scripts/test_check_pin_currency.sh | tail -1
test_check_pin_currency: OK (every state is reported, and none of them fails)
$ bash .github/scripts/test_check_pin_currency.sh | grep -c PASS
40
$ bash .github/scripts/test_check_pin_currency.sh | grep -c FAIL
0

Fourteen fixtures, forty assertions. Every state the report can name is built as a
fixture and asserted EXACTLY — cur, behind, not-on-the-served-line, unreadable
(in four distinct shapes), undecidable, the CI-time pins, and the all-three-pins
count. The last one is what keeps the report honest about its SCOPE: a change that
quietly stopped reporting one of the three would leave the site exactly as unobserved
as it was before the report existed, with every other fixture still green.

$ python3 /tmp/docs196/mutate-report.py
baseline: rc=0  (the unmutated suite must be green)
ok    mutA-no-deepening — the shallow-history deepening removed, so a depth-1 checkout
      at a behind pin is judged from a history that cannot answer — the suite turned
      RED (34 failing assertion(s))
ok    mutB-behind-as-cur — the behind state rewritten as cur, so a pin that IS behind is
      reported as current — the suite turned RED (3 failing assertion(s))
ok    mutC-one-pin-only — the umbrella dropped from the reported set, so a pinned input
      is silently unwatched — the suite turned RED (4 failing assertion(s))

test_check_pin_currency: OK (3 mutants; every one of them turns the suite red)
rc=0

The first mutant is the one that matters. With the deepening removed, the depth-1
fixture at a behind pin reports a FALSE state:

  FAIL  the corpus is a depth-1 checkout at a pin that is behind — the report does not
        name the expected state
        expected to contain: charly pin: 94bd2cd98cca04aafe635d4f566340fb025fe2a8 is cur
        — at charly's merged main (merged main: 94bd2cd98cca04aafe635d4f566340fb025fe2a8)

cur, with the pin's OWN sha as the "merged main" — a pin that is actually behind,
reported as current, with a wrong tip. That is the false state the deepening exists
to prevent, and the fixture catches it.

2 — the report, against this repo's own records, before the advance.

$ bash .github/scripts/check_pin_currency.sh .; echo "rc=$?"
corpus pin: 5feb9c8b8350849fd2d46d252b486844c18bd0a4 is cur — at the corpus's merged main (merged main: 5feb9c8b8350849fd2d46d252b486844c18bd0a4)
charly pin: bafd8dbc3110904872831998fb4caa701cc2990c is behind — 97 commit(s) behind charly's merged main; an advance available NOW (a pin-bump PR in this repo) (merged main: be7a505f476c1a5b0302d878e0b5686a2cde3e07)
umbrella pin: e631aacf32df4e26a66f2cb6a75fc9e85e212399 is behind — 413 commit(s) behind the umbrella's merged main; an advance available NOW (a pin-bump PR in this repo) (merged main: 1c88fcf15f8fb9dd8b2814210472a63d3a79d0e2)
rc=0

3 — the report, against the same records, after the advance — on the committed tree.

$ bash .github/scripts/check_pin_currency.sh .; echo "rc=$?"
corpus pin: 5feb9c8b8350849fd2d46d252b486844c18bd0a4 is cur — at the corpus's merged main (merged main: 5feb9c8b8350849fd2d46d252b486844c18bd0a4)
charly pin: be7a505f476c1a5b0302d878e0b5686a2cde3e07 is cur — at charly's merged main (merged main: be7a505f476c1a5b0302d878e0b5686a2cde3e07)
umbrella pin: 1c88fcf15f8fb9dd8b2814210472a63d3a79d0e2 is cur — at the umbrella's merged main (merged main: 1c88fcf15f8fb9dd8b2814210472a63d3a79d0e2)
rc=0

All three are cur, and the report still exits 0.

4 — the R5 sweep: the retired corpus-only report is gone, and nothing live names it.

$ git grep -n "check_corpus_currency\|corpus-currency\|test_check_corpus_currency" -- . ":(exclude)CHANGELOG"; echo "rc=$?"
rc=1

rc=1 — no hits. The only surviving mentions of the retired name are in
CHANGELOG/, which records history and is where history belongs:

$ git grep -c "check_corpus_currency\|corpus-currency" -- CHANGELOG
CHANGELOG/2026.296.0345.md:14
CHANGELOG/2026.296.0638.md:8
CHANGELOG/2026.296.0734.md:1
CHANGELOG/2026.296.1749.md:2
CHANGELOG/2026.298.0740.md:2
CHANGELOG/2026.299.0237.md:1
CHANGELOG/2026.301.0410.md:5
CHANGELOG/2026.302.0032.md:5

5 — the workflow's own gates, on the committed tree.

$ python3 .github/scripts/check_step_timeouts.py | tail -1; echo "rc=$?"
rc=0
$ python3 .github/scripts/test_check_step_timeouts.py | tail -1; echo "rc=$?"
test_check_step_timeouts: OK (5 mutants; every one of them turns the self-test red)
rc=0
$ python3 .github/scripts/check_dependency_advisories.py | tail -1; echo "rc=$?"
check-dependency-advisories: OK (no known advisory in the production tree or the dev tree)
rc=0
$ python3 .github/scripts/check_dependency_advisories.py --self-test | tail -1; echo "rc=$?"
check-dependency-advisories self-test: OK (a production finding, a dev finding and a clean tree are all told apart, and an unauditable tree is an error)
rc=0
$ python3 .github/scripts/test_check_dependency_advisories.py | tail -1; echo "rc=$?"
test_check_dependency_advisories: OK (5 mutants; every one of them turns the self-test red)
rc=0
$ python3 .github/docs-corpus/test_check_drift.py | tail -3; echo "rc=$?"
Ran 6 tests in 0.040s

OK
rc=0

6 — the regeneration, and the drift gate.

The regeneration is the workflow's own command, run against the workflow's own pinned
inputs: the charly clone at be7a505f with its box/* submodules, the umbrella at
1c88fcf1, the corpus at this repo's gitlink, and the plugin-docs CLI built from the
tag this repo pins (v2026.289.0814).

Before the commit, the drift gate was RED — the committed tree did not yet carry the
regenerated pages:

$ bash .github/docs-corpus/check_drift.sh > /tmp/docs196/drift-before.log 2>&1; echo "rc=$?"
rc=1
$ tail -2 /tmp/docs196/drift-before.log
?? src/content/docs/reference/plugin/github-com-opencharly-plugin-task-v2026-300-0951/plugin-task.md
DRIFT: the committed site does not match its pinned generation inputs.
Commit regenerated content together with the input pin changes.

After the commit, the regeneration was run again — over the committed tree, byte for
byte — and it changed NOTHING:

$ tail -2 /tmp/docs196/regen2.log
charly docs: 395 recipe pages, 196 plugin pages (205 provider words), 79 cli pages, 834 candy pages, 216 box pages (1726 generated pages cleared before regeneration)
REGEN_DONE 2026-10-29T03:20:38+01:00
$ git status --porcelain=v1 -uall -- src/content/docs | wc -l
0
$ bash .github/docs-corpus/check_drift.sh; echo "rc=$?"
content: committed tree matches the pinned inputs (regeneration is a no-op).
rc=0

A fresh generation over the committed tree leaves ZERO changes — not one page, not one
byte — and the drift gate is green.

For contrast, the SAME generator over the OLD pins produced 194 plugin pages, 801 candy
pages and 201 box pages; the advance is what brings the site to 196/834/216:

$ grep -m1 "recipe pages" /tmp/docs196/genA2.log
charly docs: 395 recipe pages, 194 plugin pages (205 provider words), 79 cli pages, 801 candy pages, 201 box pages (1676 generated pages cleared before regeneration)

7 — the site's own build, and the built site's content.

$ npm run build | tail -4
03:21:31 [starlight:pagefind] Found 1749 HTML files.
03:21:32 [starlight:pagefind] Finished building search index in 4.52s.
03:21:32 [build] 1749 page(s) built in 39.60s
03:21:32 [build] Complete!
$ find dist -name '*.html' | wc -l
1749
$ ls -l dist/index.html
-rw-r--r-- 1 atrawog atrawog 1134296 Oct 29 03:20 dist/index.html

The build carries no warning and no error, and the search index is built over the same
1749 pages.

Rulebook compliance

Change classification

  • Change class: a pin change (the two CI-time pins the deploy records) plus the generated pages those pins project, plus a control change (the currency report's scope widens from one pin to three, and the retired report is deleted with it). The pins carry CONTENT — the charly tree the site's reference/** projects — so this is not the documentation-only class, and the tier is a runtime tier.
  • Diffstat: 133 files changed, 2782 insertions(+), 493 deletions(-) — 127 generated pages (50 added, 67 modified, 10 replaced by their newer version-stamped counterpart; +2093 −101, net +1992) and 6 control files (two new scripts, the two retired scripts deleted with them, the deploy workflow, and this repo's AGENTS.md; +689 −392).
  • Gate run: this repo's own generation workflow on the committed tree — the regeneration, the drift check (content: committed tree matches the pinned inputs), the pin-currency report, the dependency-advisory gate, the step-deadline gate and the Astro build — every step, zero failures, zero warnings.
  • Attribution tier: fully tested and validated — the change-class gate passed on the final tree, and the changed path (the sources the site is generated from) was executed live, with the "before" retained.
  • No rebuild leg applies: this change touches no disposable: true target; the site is built by the real Astro build, pasted above.

Filed issues

  • the release-TAG class of pins (the generator's own tag and the 65 wiring-candy plugin tags) is unobserved: the generator is one release behind and 64 of 65 plugin pins name a tag older than their repo's newest #199 — the site's release-TAG class of pins is unobserved: the generator itself is pinned at v2026.289.0814 while opencharly/plugin-docs has published v2026.295.2045, and 64 of the 65 wiring-candy plugin pins in .github/docs-corpus/pins.tsv name a tag older than their repo's newest (the one current row, plugin-build v2026.296.1104, is current only because docs(corpus)!: advance the corpus and the plugin-build pin, and regenerate the site on --stage-parallelism #198 had to advance it for a content reason). The mechanism (a tag pin moves only when somebody rewrites it by hand, and nothing in this repo rewrites either class — pins.tsv is hand-maintained, the generator's tag is a literal in the workflow, and the corpus's own refresh-refs.sh refreshes a different file in a different repo), the missed control (the pin contract defines its states against a BRANCH's merged main, so a tag's currency question — "is there a newer RELEASE?" — has no state to answer in; the currency report names each pin's served commit and never says whether a TAG points at it — so a body can call a pin 'merged and tagged' with no gate disagreeing opencharly#793 is that gap, org-wide), the blast radius (the generated half: the generator decides how every page is rendered, and the 65 wiring pins decide which plugin versions the site's reference/plugin/** and reference/candy/** sections project) and the root fix (the org defines the tag state, then this repo reports its tag pins in it, then a wave advances them with the pages they project) are on that issue, with the measured evidence. Not blocking here: this change's claim is that the site's COMMIT pins are current and reported, and the tag class is a different pin class with a different remedy and a different set of pages — separable by construction. The report's own header states the scope explicitly, so the omission is a stated scope, not a silent gap.

  • every multi-owner command-word page counts pinned VERSIONS of one plugin as "plugin candies", and hardcodes "Both" plugin-docs#24 — the generator's multi-owner command-word sentence counts pinned VERSIONS of one plugin as "plugin candies" and hardcodes the quantifier "Both". Measured on the pages this PR regenerates: all 37 of the site's 79 multi-owner command-word pages carry a count that is not the number of distinct candies — 36 of them name ONE plugin repeated once per pinned version (alias.md reads "served by 2 plugin candies — plugin-alias and plugin-alias"), and only feature.md names two distinct candies while claiming three; five pages (the ones claiming three or four) additionally carry the wrong "Both are real invocations". The mechanism (the generator groups command: providers by word into an owner list of pinned version instances — byWord[word] = append(byWord[word], p) — then prints len(c.owners) as the number of "plugin candies" and joins the per-version names, with a Both literal written for the two-owner case; cliPageDescription repeats the same count in the frontmatter, so the wrong count is also the site's search-result text), the missed control (the only test of that sentence, TestGenerateCLIMultiOwnerPageNamesEveryOwner, uses two owners with two DIFFERENT names — the one shape in which the count, the name list and the literal all agree — so neither the count nor the quantifier is asserted anywhere), the blast radius (37 of the 79 command-word pages this repo publishes, plus their search-result text, and the defect grows with every corpus pin wave that adds a version) and the root fix (count the DISTINCT candy names, join the distinct names, derive the quantifier from that count, and add fixtures for a repeated owner name and for a count of three) are on that issue. Not blocking here: the defect pre-dates this change — the committed tree already carries all 37 pages in this shape — and the fix belongs to the generator, in another repo, with its own producer-first release. This PR changes exactly one of those pages, from "3" to "4", both of which are wrong in the same way; the finding is filed, not folded in.

Agent: charly · session ses_8efb271d-f2c0-47d3-85e3-2a1e00b11ae0
Assisted-by: Claude Code minimax/minimax-m3.1-flash:cloud (fully tested and validated)

…arly and umbrella pins

Refs #196

The site is generated from THREE pinned inputs — the guidance corpus (this repo's
`marketplace` gitlink), the `charly` commit the deploy clones, and the umbrella commit
the deploy clones — and every one of them is advanced by a MANUAL act after its
producer lands. The drift gate CANNOT see that: the PINNED sources regenerate their
own (old) pages perfectly, so a stale pin is invisible to it. The gate answers "does
the committed content match what the pinned inputs generate?" (yes, always); it never
answers "is each pinned input itself current?".

Measured before this change:

    charly pin: bafd8dbc3110904872831998fb4caa701cc2990c is behind — 97 commit(s)
    umbrella pin: e631aacf32df4e26a66f2cb6a75fc9e85e212399 is behind — 413 commit(s)

Both were valid `behind` states — both ancestors of their producer's merged main,
neither a divergence — and nothing in this repo said so. The report that watched the
corpus alone watched one of the three.

The corpus-only report is REPLACED, not extended beside itself: `.github/docs-corpus/
check_corpus_currency.sh` and its fixtures are deleted, and `.github/scripts/
check_pin_currency.sh` takes their place with the scope widened to every pinned input
the site consumes. The corpus's own line is worded byte for byte as it was, so a reader
who knows the old line reads the same words.

The report speaks the pin contract's own states — `cur`, `behind`,
`not-on-the-served-line` — plus two of its own for the cases it refuses to guess:
`undecidable` (the history could not be deepened, so ancestry cannot be judged) and
`unreadable` (the pin, or the producer's merged main, could not be read). It is
REPORTED and never failed: a pin that is behind is an advance available NOW, and the
remedy is a regeneration PR that bumps the pin, not a gate.

The judgment must be DECIDABLE before it is reported. `merge-base --is-ancestor`
answers "not an ancestor" for a commit the clone does not have — indistinguishable
from a real squash-advance — and the corpus checkout in CI IS a depth-1 clone
(actions/checkout runs `git submodule update --init --force --depth=<fetch-depth>`
with its default `fetch-depth: 1`). A depth-1 history therefore cannot judge ancestry
at all, and reporting from it would state a FALSE state: a divergence for a pin that
is merely behind, with a wrong commit count. So a shallow history is DEEPENED first,
and when the deepening cannot be done the report says `undecidable` and never guesses.
A false state is worse than no report. The fixtures carry that case — a depth-1
checkout at a pin that IS behind — and the mutation that removes the deepening turns
the suite red with the false state in it.

THE TWO ADVANCES. `charly` moves bafd8dbc -> be7a505f (97 commits behind, now `cur`)
and the umbrella moves e631aacf -> 1c88fcf1 (413 commits behind, now `cur`). Both are
MERGED refs — the tips their producers' merged `main` serves — reached through the
workflow's own recorded pin, never by a hand-pin. The pages each advance projects are
regenerated here, and the umbrella's four root narratives are byte-identical across
those 413 commits, so the umbrella's advance changes no narrative page.

THE PINS ARE RECORDED ONCE. The two CI-time commits live in the workflow's own `env:`
block, which the deploy's clone step consumes and the report reads — so a SHA can no
longer be written in one place and forgotten in the other. The corpus pin is the
committed gitlink, and the report reads it from the commit's TREE, not from the
checkout's HEAD: the checkout is a convenience, the tree entry is the pin.

No page is hand-edited. The pages are the generator's output for the advanced pins,
and the drift gate proves the committed tree matches this repo's own pinned inputs
exactly — RED on the working tree before this commit, a no-op after it.

Two findings are separable from this change and are FILED, not fixed here:
#199 (the release-TAG class of pins, whose currency question the
org has not given a state) and opencharly/plugin-docs#24 (the generator's
multi-owner command-word sentence, which counts pinned versions of one plugin as
"plugin candies" and hardcodes "Both" — it predates this change and is wrong on
37 of the 79 command-word pages).

Refs #196

Assisted-by: Claude Code minimax/minimax-m3.1-flash:cloud (fully tested and validated)
@aitrawog

Copy link
Copy Markdown
Contributor Author

STATUS

Agent: charly · session ses_8efb271d-f2c0-47d3-85e3-2a1e00b11ae0

PR open: #200 — docs(pins)!: report every pinned input's currency, and advance the charly and umbrella pins. Head 4f824fca41725e9d133944ad9c4e67af61adf4dd, branch feat/pin-currency-report-196 off this repo's fresh origin/main (a166ee1), worktree .worktrees/docs-196/docs.

What is done. The report is in and green: .github/scripts/check_pin_currency.sh watches all THREE pinned inputs the site consumes (the corpus gitlink, the charly commit the deploy clones, the umbrella commit the deploy clones), in the pin contract's own states (cur, behind, not-on-the-served-line) plus undecidable and unreadable for the cases it refuses to guess. It REPORTS and never fails, and it DEEPENS a shallow history before judging it — a depth-1 checkout cannot answer the ancestry question, and a false state is worse than no report. The corpus-only report it replaces is deleted in the same cutover.

Both CI-time pins are advanced to their producers' merged tips (charly bafd8dbc → be7a505f, 97 commits behind; umbrella e631aacf → 1c88fcf1, 413 commits behind), the pins are recorded ONCE (the workflow's own env: block), and every page each advance projects is regenerated in the same PR — 127 page files, net +1992.

The proof, on the committed tree. 14 fixtures / 40 assertions, 0 FAIL, and three proven mutations (the deepening removed → 34 failing assertions; behind rewritten as cur → 3; the umbrella dropped → 4). A fresh CI-faithful regeneration over the committed tree leaves ZERO changes and the drift gate is green. The Astro build assembles 1749 pages with no warning and no error.

Two findings filed, not folded in. #199 (the release-TAG pin class, whose currency question the org has not given a state — claimed there) and opencharly/plugin-docs#24 (the generator's multi-owner command-word sentence counts pinned VERSIONS of one plugin as "plugin candies" and hardcodes "Both" — it pre-dates this change and is wrong on 37 of the 79 command-word pages).

What is next. Read the validator's full report, fix every finding in ONE commit per round, and land on its PASS. The next update lands when the validator's verdict arrives, or at the end of the round it names.

Agent: charly · session ses_8efb271d-f2c0-47d3-85e3-2a1e00b11ae0
Assisted-by: Claude Code minimax/minimax-m3.1-flash:cloud (fully tested and validated)

@github-actions

Copy link
Copy Markdown

Review — PASS

I re-derived every claim in the body against the current diff, commit list, and (empty) comment thread. No designated maintainers are configured for this run, so no comment is treated as a sign-off; the change stands on its own evidence.

What I verified

Diffstat and file accounting — internally consistent.

  • Header: 133 changed files. Body: 133.
  • Control files (6): check_corpus_currency.sh (−112), test_check_corpus_currency.sh (−247), check_pin_currency.sh (+231), test_check_pin_currency.sh (+401), deploy.yml (+40/−21), AGENTS.md (+17/−12). Insertions 231+401+40+17 = 689; deletions 112+247+21+12 = 392 — exactly the body's “+689 −392”.
  • Generated pages: 127 = 50 added + 67 modified + 10 replaced; the diff contains exactly 10 renames (the version-stamped replacements), matching the body. 689+2093 = 2782 and 392+101 = 493, matching the stated total. Arithmetic is honest.

Test coverage — the count in the body is correct.
test_check_pin_currency.sh has 14 fixtures; counting assert_state (2 passes each: state + exit 0), assert_not_divergence, assert_reported, and the fixture-14 line-count check yields exactly 40 assertions, matching the body's “Fourteen fixtures, forty assertions” and the claimed 40 PASS / 0 FAIL. The fixtures cover every state the report can name (cur, behind, not-on-the-served-line, four unreadable shapes, undecidable), the CI-time pins, the depth-1-at-a-behind-pin case (the CI shape), and the all-three-pins count. The mutation claims (no-deepening, behind-as-cur, one-pin-only) are plausible and would each turn the suite red.

Report correctness.
check_pin_currency.sh reads the corpus pin from the commit tree (HEAD:marketplace), reads the two CI-time pins from the workflow's own env: block, clones each producer itself, deepens shallow histories before judging, and never exits non-zero. The awk env parser matches only column-0 env:/keys, so step-level env blocks cannot shadow it; the “not here” vs “not an ancestor” distinction is handled. The state vocabulary matches the body exactly.

Workflow.
The env: block is validly placed (after permissions:, before jobs:); the clone step now consumes $CHARLY_REPO/$CHARLY_PIN/$UMBRELLA_REPO/$UMBRELLA_PIN; the report step runs before the clone step and does not depend on it. Step timeouts are present.

Generated pages.
The reference/box, reference/candy, reference/cli, reference/plugin, providers.md, and index.md changes are consistent with a charly advance (new version stamps, new skill-carrier candies, 194→196 plugin candies, 205 provider words unchanged). The umbrella’s four root narratives are untouched, consistent with the body’s claim. The known multi-owner command-word defect (e.g. ollama.md now “4 plugin candies … and plugin-ollama and plugin-ollama… Both”) is explicitly identified and filed to opencharly/plugin-docs#24 rather than hidden.

R5 sweep.
The two retired scripts are deleted, and the workflow/AGENTS.md now name only the new scripts. The body’s claim that the only remaining mentions live in CHANGELOG/ is plausible and not contradicted by the diff.

Non-blocking observations

  • The report clones charly/umbrella itself, and the deploy step clones them again — intentional self-containment, but duplicate network work.
  • The tests clone local paths with --filter=blob:none; git falls back to a full clone (warning suppressed) for the local transport, so the fixtures still exercise the intended states.
  • No CHANGELOG entry is added for this breaking (!) pin change; I could not verify from the diff that the repo requires one, so I do not treat it as a blocker.

No correctness, security, scope, or honesty defect was found that would justify blocking. The body’s evidence is internally consistent and reproduced by the diff.

Verdict: PASS


ollama-cloud/deepseek-v4.1-flash — action-review.

View action run

@github-actions
github-actions Bot enabled auto-merge (squash) October 29, 2026 02:37
@github-actions
github-actions Bot merged commit 2d8020c into main Oct 29, 2026
4 checks passed
charly-auto-merge Bot added a commit that referenced this pull request Oct 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

the site's own charly and umbrella pins are 91 and 373 commits behind their merged mains, and nothing reports it

1 participant