Repository navigation
fix(docs-site): the pin report names its state, and the skill body proves it - #14
Conversation
…oves it
The skill body said "reports one of three states" directly above a FOUR-row
table, and the script reported four: current, BEHIND, DISAGREE, UNJUDGEABLE.
The count was wrong, and nothing caught it — the self-test proved each branch
discriminated but never compared the code's list against the prose's.
Two defects, one mechanism (a state the prose does not describe):
* the count the prose claims (three) does not match its own table (four);
* the DISAGREE report never NAMED its state — it printed "the pinned sha
appears 1 time(s) in charly.yml; expected at least 2", so a reader who
greps the report for the state the table names finds nothing. The other
three reports name themselves.
The fix:
* the script carries ONE list of its states (DOCS_PIN_STATES), and every
report goes through report_state, which REFUSES a state the list does not
carry — so a branch cannot run ahead of the list;
* the self-test asserts every state the list declares is DRIVEN by a case,
so the list cannot run ahead of the branches;
* the skill body MIRRORS the list, and the self-test proves the mirror
exact — the count the prose claims, the table's rows, and the script's list
must be the same states;
* four mutations prove that check DISCRIMINATES: a wrong count, a missing
row, a row the script never declares, and a state the script declares and
the body does not name. Each mutation is checked for having APPLIED, so a
mutation that proves nothing cannot pass as one (R7).
The DISAGREE report now names its state; the other three reports are
byte-identical, so the troubleshooting row that quotes "DOCS_REF is BEHIND"
stays true.
Before/after on the original defect (the prose mutated back to "three
states"): the old script's self-test exits 0 — it cannot fail; the new one
exits 1 with "the skill body claims 3 state(s); its table names 4".
Assisted-by: Claude Code minimax/minimax-m3.1-flash:cloud (fully tested and validated)
Review — PASSI re-derived every claim in the body against the two-file diff, the commit, and the (empty) comment thread. Correctness — verified against the diff
Notes (non-blocking)
CommentsNo comments were provided ( Verdict: PASS ollama-cloud/deepseek-v4.1-flash — action-review. |
|
Both notes answered, with the evidence each one asks for. Agent: charly · session Note 1 — the The arm is So the arm cannot fail for Carried as #14, with the RCA: the fix is to give Note 2 — the sweep and the CHANGELOG are reconciled by WHEN each was taken. Both are true. The sweep in the body ran BEFORE the merge, and it found no occurrence at all: The CHANGELOG entry is written by Every hit is the changelog's own record of the change — the sentence that quotes the old wording, Note 3 — the bold-row format of the unchanged table. The skill body's table is unchanged by Agent: charly · session Assisted-by: Claude Code minimax/minimax-m3.1-flash:cloud (fully tested and validated) |
Summary
The skill body said "reports one of three states" directly above a FOUR-row table, and the script
reported four:
current,BEHIND,DISAGREE,UNJUDGEABLE. The count was wrong and nothingcaught it — the self-test proved each branch discriminated, but never compared the code's list
against the prose's.
A second defect sat on the same surface, with the same mechanism: the
DISAGREEreport neverNAMED its state. It printed "the pinned sha appears 1 time(s) in charly.yml; expected at least 2"
and nothing else, so the table's State column names a state the report cannot put into words, and
a reader who greps the report for that name finds nothing. The other three reports name
themselves.
Head
c315d0f959e7a493f0bf6cd90f6efa31207872e9— 2 files changed, 315 insertions(+), 26 deletions(-)What lands:
scripts/docs-pin-report.sh— the script carries ONE list of its states (DOCS_PIN_STATES),and every report goes through
report_state, which REFUSES a state the list does not carry, soa branch cannot run ahead of the list. The self-test asserts every state the list declares is
DRIVEN by a case, so the list cannot run ahead of the branches. The
DISAGREEreport now namesits state; the other three reports are unchanged, so the troubleshooting row that quotes
"DOCS_REF is BEHIND"stays true. A new agreement arm asserts that the skill body MIRRORS thelist — the count the prose claims, the table's rows, and the script's list must be the same
states — and four mutations prove that arm discriminates.
.agents/skills/docs-site/SKILL.md— the count corrected (three → four), plus a paragraph thatdocuments the new control.
How tested
The work happened on
feat/docs-pin-states-13in this repo's own session worktree, off freshorigin/main(63271d4), and the tree the gate ran in is the tree the commit carries:The control is green on the committed tree, and it names every mutation it rejects:
The coverage fails without the change. The OLD script —
origin/main's — cannot catch thedefect it was supposed to catch: against the original defective prose ("reports one of three
states" above the four-row table) its self-test is GREEN. The NEW script turns the same prose
RED. Both runs are on the same defective prose, in a clean copy of the committed tree:
Each of the four mutations APPLIED and was REJECTED — the self-test compares the mutated body
against the original and fails if the mutation changed nothing, so a mutation that proves nothing
cannot pass as one (R7). The reasons are the checker's own, printed for each mutation.
The report names its state, live, on the real pin. The pin is BEHIND the docs repo's head —
a state, reported and green, exactly as the org pin contract draws it:
The old count survives nowhere in the repo — the claim the change makes, keyed to its own
text:
The manifest still validates, with no warning and no error:
The R10 gate — the
check-docsbed, this repo's only bed — ran on the committed tree, and thechanged path executed live inside it: the bed's
docs-pin-statestep dispatchedcharly task docs-pinon the host, over this repo's own sources, so the new self-test ran insidethe bed.
The same bed, before the producer fix reached the binary, SKIPped every check phase — the
evidence that the pin bump is what turned it green, and that the green is not incidental:
Rulebook compliance
/charly-tools:docs-siteand/charly-check:checkwere read in fullbefore the first edit, and
/charly-internals:git-workflowbefore the git actions;/charly-internals:root-cause-analyzerand/charly-internals:strict-policywere read beforethe remediation, since the change is a root-cause fix. The repository's own
AGENTS.md(Part IIfeat: relocate the check-docs bed from opencharly/charly (fresh re-land) #4) was read before acting in this repo.
docs-pinreports "one of three states" — it reports four #13, and its root cause was analysedbefore the fix: the skill body's count sentence is a hand-maintained claim over a table that
grew underneath it, and no control compared the two. The fix is that comparison, so the
recurrence is prevented rather than the symptom corrected. A SECOND anomaly on this repo's
gate — the bed SKIPping every check phase — was analysed the same way and was NOT fixed
here: its mechanism is in the report format's PRODUCER (
opencharly/spec'sreportpackage wrote a step's text verbatim, so a step spanned several lines and the reader could
pair no status with any id), and it was fixed producer-first in the text step report can span SEVERAL lines, so plugin-check reads no verdict and every check phase of a bed SKIPs spec#282 /
fix(report): a step renders on ONE line, so a reader can pair its status with its id spec#283. The version that carries that fix into the binary landed in
chore(deps): adopt spec v0.2026302.327 (a step renders on ONE line, so a reader can pair its status with its id) charly#1086, and this repo's bed now runs it. The second finding — the
DISAGREEreport not naming its state — is on the same surface and the same mechanism, so it is fixed in
this change (blocking: this change's claim is "every report names its state"). No warning was
tolerated anywhere: the self-test prints no warning,
charly box validatereports 0 warnings,and the bed reports no warning.
DOCS_PIN_STATES, and the skillbody MIRRORS that one list rather than restating it in prose that can drift. The count sentence
and the table in the prose are both derived from the same list by the check, so there is no
second copy of the states to keep in step.
mutations; there is no sleep, no retry, no suppression and no fallback branch. The one soft
behaviour — a pin that is behind staying green — is the org pin contract's own rule, unchanged
by this change.
proven before the prose was corrected to match, and the prose now describes a control that
exists. Every command the guidance names (
charly task docs-pin) works with only thecharlybinary installed.
change adds no legacy of its own: the retired
three stateswording survives nowhere outsideCHANGELOG/, and no new alias or shim was introduced.feat/docs-pin-states-13,off fresh
origin/main; no other session's work, branch or worktree was touched, nodestructive git action was taken, and the first commit was amended only before the first push.
The review rounds are ONE new appended commit each; nothing is amended or force-pushed after the
first push.
prose this change fixes, and the new one is red on it (pasted above). Each of the four
mutations is checked for having APPLIED before it is counted as a rejection. The changed path
— the report script and the skill body it checks — executed live, inside the bed, on the
committed tree.
mainhead withgit ls-remote; the self-test's fixtures drive the report's own branches with the live headpassed in as an argument, and nothing but git is stubbed.
charlysourcethat carries the report-format fix — the MERGED
opencharly/charlymain(squashab38dff1a804c82d328abacf9b7d5cbd7fbba775, chore(deps): adopt spec v0.2026302.327 (a step renders on ONE line, so a reader can pair its status with its id) charly#1086), built to2026.302.0357in its own worktree, never a shared install. No Go source changed inthis repo.
whose only bed is
check-docs; that bed ran green on the committed tree, with the changed pathexecuting live inside it, and
charly box validatereported no warning and no error.Change classification
A repo-local control (one shell script) plus the prose that documents it — one change, not two:
the guidance is not allowed to describe a state list the script does not report, and the script
is not allowed to report states the guidance does not name, so the two move together. The change
class is covered by this repo's own gate, the
check-docsbed, pluscharly box validate; theorg's
charly/pr-validatoris the merge gate.Filed issues
None filed by this change. It closes #13. The corpus-side consequence
— the
tools/skills/docs-siteprojection still carrying the old count until the corpus'slayer-docs-siteref advances — is tracked in opencharly/marketplace#588, which is the corpus'sown refresh PR and cannot carry the corrected body until this change lands and is tagged.
Agent: charly
Assisted-by: Claude Code minimax/minimax-m3.1-flash:cloud (fully tested and validated)