Repository navigation
The docs-site guidance names a control (task docs:pin) that does not exist, so the DOCS_REF contract is unenforced #10
Description
The claim, and where it lives
The docs-site skill, this repo's AGENTS.md, and this repo's charly.yml all state that a
control named task docs:pin exists and polices the DOCS_REF pin. In the skill's words:
task docs:pinfails whenDOCS_REFis not the docs repo's currentmainhead (it fetches
ls-remoteand compares — charly has nodocsgitlink anymore: the docs repo is standalone,
and this candy's pin is the only thing that fixes what the bed tests).
and
task docs:pintherefore asserts BOTH: it comparesDOCS_REFagainst the docs repo's
currentmainhead AND requires the sha to occur at least twice in the file, so a re-pin
that updates only one of them fails the gate instead of leaving the check asserting a
commit nobody builds.
Five mentions, in two files (measured with grep -c 'docs:pin'), plus the published
corpus that projects them:
.agents/skills/docs-site/SKILL.md— 3 (the paragraph above, the "the pin is TWO
occurrences, and both are asserted" paragraph, and the troubleshooting row
"task docs:pinfails |DOCS_REF(or the check's literal sha) is not the docs repo's
currentmainhead — bump it in a charly PR")charly.yml— 2 (theDOCS_REFvar's comment and thedocs-site-pinned-commit
check's comment)AGENTS.md— 0 by name: it states the CONTRACT (both occurrences must be updated
together) without naming the task, so it needs no change under either fix- the published corpus (
opencharly/marketplace,tools/skills/docs-site/SKILL.md) — the
same 3 skill mentions, projected
The measurement: the task does not exist
task docs:pin is not a task in any repo of the org. The charly repo's task set has no
docs group and no pin task; the umbrella's charly.yml has no docs:pin; this repo's
charly.yml declares no tasks: block at all. The command a reader would run fails:
$ charly task docs:pin
charly: error: unknown task "docs:pin" (declared tasks: ...)
The pin contract this repo's AGENTS.md describes — "DOCS_REF is an immutable commit, never
a branch, and it appears TWICE … both occurrences must be updated together" — is therefore
unenforced. Nothing checks that the two occurrences agree, and nothing checks that the
pin is the docs repo's current head.
Mechanism, and why it was never implemented
The control is described as a failure: "task docs:pin fails when DOCS_REF is not the
docs repo's current main head". Run in any gate, it would be red for every merge of the
docs repo that has not yet been re-pinned here — that is, permanently red between docs
merges. A gate that is red on a healthy tree is not a control; it is a nuisance that gets
bypassed. That is the most likely reason the described control was never written, and the
reason the sentence in charly.yml that matters is the one that is implemented: the bed
asserts the pin from inside the built image (docs-site-pinned-commit reads
/srv/docs/.charly-pinned-commit and matches the literal sha) — that proves the image
holds the pinned commit, and it fails loudly when a stale clone layer survives a re-pin.
What is missing is the half the bed cannot see: that the pinned commit is the docs repo's
current head, and that the two occurrences of the sha in charly.yml agree.
Blast radius
- This repo's contract is unpoliced, so the pin drifts. It did: the pin was two docs merges
behind, which is Refresh docs-site consumer pin after docs#157 #8 (re-pinning it is the change that issue
asks for). - A re-pin that updated only ONE of the two occurrences would leave the bed's
docs-site-pinned-commitcheck asserting a commit the image never builds — and the bed
would still report PASS, because the check's literal and the clone'sDOCS_REFare
independent. That is the exact failure the claimed control exists to prevent, and it is
the one thing a reader of this skill is told is impossible. - The published corpus carries the same three mentions, so every agent that loads
/charly-tools:docs-siteis told a control exists. The claim is the guidance's whole
account of how the pin is policed.
Root fix
Two honest options; both are one contract, so pick one and do not leave both:
(a) Implement it as a REPORT, not a failure. A task in this repo that names the drift
without reddening the gate — the same shape the umbrella's pins MODE=currency uses
(opencharly/opencharly#621): a pin that is behind is an advance available NOW, in the
producer's own repo, so the gate reports it and stays green; only a pin the workflow cannot
judge fails. It would assert the two things the current claims say it asserts: that
DOCS_REF is the docs repo's current main head (git ls-remote against DOCS_REPO), and
that the sha occurs twice in charly.yml. Run it where? This repo's own gate, and the
umbrella's verify — which already composes tasks.
(b) Delete the claims and state the real mechanism. If the control is not wanted, then
the guidance must stop asserting it: the DOCS_REF contract is a config edit, policed by
the bed's docs-site-pinned-commit check (the image holds the pinned commit) and by the docs
repo's own deploy workflow (content freshness against the pinned charly). Every one of the
five mentions above goes, and the "both occurrences" rule is stated as what it is — a
convention the reader must honour — rather than as something a task checks.
Either way the corpus follows: opencharly/marketplace pins this repo by TAG in
candy/charly-marketplace/charly.yml (@github.com/opencharly/layer-docs-site:v2026.274.0639),
so the regenerated corpus can only be produced after this repo merges and is tagged, and the
docs repo's corpus pin bump follows that. The producer-first order is: this repo → the
marketplace corpus → the docs site.
Evidence
$ grep -rn 'docs:pin' . --exclude-dir=.git | grep -v '^./CHANGELOG/'
.agents/skills/docs-site/SKILL.md:53:... `task docs:pin` fails when `DOCS_REF` is not the docs repo's current
.agents/skills/docs-site/SKILL.md:66:... `task docs:pin` therefore asserts BOTH: it compares `DOCS_REF` against the docs
.agents/skills/docs-site/SKILL.md:126:| `task docs:pin` fails | `DOCS_REF` (or the check's literal sha) is not the docs repo's current `main` head
charly.yml:52: # docs:pin` checks that (charly no longer carries a `docs` gitlink ...
charly.yml:83: # so it must not depend on substitution. `task docs:pin` asserts BOTH occurrences
$ grep -c 'docs:pin' .agents/skills/docs-site/SKILL.md AGENTS.md charly.yml
.agents/skills/docs-site/SKILL.md:3
AGENTS.md:0
charly.yml:2
$ grep -rn 'docs:pin' --include='*.yml' --include='*.yaml' --include='*.go' --include='*.mjs' --include='*.sh' /home/atrawog/Sync/Atrapub/a/claude/opencharly/.worktrees/light-init/charly /home/atrawog/Sync/Atrapub/a/claude/opencharly/.worktrees/light-init/opencharly
(no match)
Agent: charly
Assisted-by: Claude Code minimax/minimax-m3.1-flash:cloud (analysed on a live system)
Activity
aitrawog commentedon Oct 23, 2026
CLAIM — this finding is surfaced while landing #8 (the
DOCS_REFre-pin), and it is not in that PR's scope: #8 re-pins the two occurrences of the sha and
proves the pin; it does not change what the guidance claims about how the pin is policed.
What is done. The claim is measured, not theorised:
task docs:pinis not a task inthis repo, in
opencharly/charly, or in the umbrella — the command a reader would runfails with an unknown-task error. The four surfaces that carry the claim (this repo's
SKILL.md×3,AGENTS.md×1,charly.yml×2) are listed in the issue body, together withthe mechanism and the two root-fix options.
What is next. Nothing here in this session — the finding is filed, not fixed. The fix
is a 3-repo cutover under the producer-first order: this repo (implement the control
as a report, or delete the claims and state the real mechanism) → the marketplace
corpus (the refs list pins this repo by TAG, so the corpus follows the merged tag) →
the docs site (the corpus pin bump). The #8 PR lists this issue under
## Filed issues.Why it is not blocking #8. #8's claim is that
DOCS_REFnames the docs repo's currentmainhead in both occurrences and that the built image holds that commit — both provenby the
check-docsbed on the committed tree. Whether a task also asserts those factsis a separate contract, and the fix for it is not separable into a one-line edit here.
What would close it. Either a task that reports the two facts without reddening the
gate (the shape the umbrella's
pins MODE=currencyuses), or the five claims deleted withthe real mechanism stated in their place — and the regenerated corpus carrying the
change.
Agent: charly
Assisted-by: Claude Code minimax/minimax-m3.1-flash:cloud (analysed on a live system)
aitrawog commentedon Oct 23, 2026
REFINEMENT — the root cause is sharper than the issue body states, and it changes the
recommended fix.
The issue body says the control "was never implemented". The truth is that it was
implemented, it lived in the charly repo, and it was deleted there with an explicit
delegation to this repo.
charly#452 (
665693b9c96816aa43a7b641b959e6925b4d7c62, "fix: sweep the dead candy/couplings and repair the contract-pin gate", 2026-08-29) removed
taskfiles/Docs.yml—the file that held
task docs:pin. Its own words:The task was alive before that: charly's own changelog records
task docs:pin EXIT 0(
CHANGELOG/2026.230.1856.md) and its assertions (both occurrences match the gitlink) inCHANGELOG/2026.227.1426.md. The de-submodule cutover (charly#381) moved the candy'scharly.ymlout of the charly repo, which broke the task's grep; #452 removed the brokentask and said where the check belongs.
This repo never took the delegation. The five surfaces that still name
task docs:pinwere written against the charly repo's task, and nothing updated themwhen it was deleted. So the guidance points at a control that has not existed since
2026-08-29.
This changes the recommended fix. Option (a) — implement it here — is now clearly the
intended one, because that is what the deleting commit asked for, and the delegation
names the exact assertions the old task had:
DOCS_REFequals the docs repo's currentmainhead, compared withls-remote(the old task's own mechanism), and
charly.yml(both occurrences updated together).The shape of the gate is the one the umbrella's
pins MODE=currencyuses(opencharly/opencharly#621): a pin that is behind is an advance available NOW, in the
producer's own repo, so the gate reports it and stays green; only a pin the workflow
cannot judge fails. That is also the only shape that survives the docs repo landing
between waves — a task that FAILED on a stale pin would be red on a healthy tree, which is
presumably why the delegated control was never written.
Option (b) — delete the five claims and state the real mechanism — remains legal, but it
would refuse a delegation the charly repo explicitly made, so (a) is the better answer.
Not blocking the re-pin (#8): the pin's VALUE is the
contract this repo's
AGENTS.mdalready states, and the bed'sdocs-site-pinned-commitcheck proves from inside the built image that the image holds the pinned commit. The
delegated control would additionally prove the pin is the docs main head and that the two
occurrences agree — that is this issue's job, not #8's.
Agent: charly
Assisted-by: Claude Code minimax/minimax-m3.1-flash:cloud (analysed on a live system)
aitrawog commentedon Oct 24, 2026
STATUS — the delegated DOCS_REF control is implemented and up for review.
Head. #12, branch
feat/docs-pin-report-10, head91f2da9da10aa3ad9958c6c026f9416a03426346, off freshorigin/main(e505b26).What is done. The delegation charly#452 left open is taken up:
scripts/docs-pin-report.showns the report, thedocs-pintask incharly.ymlruns it plus its--self-test, and thecheck-docsbed dispatches the task on the host — so the control runs in this repo's own gate. The report is a REPORT on the currency half (a pin that is BEHIND stays green — the advance is available NOW inopencharly/docs) and a FAILURE on the agreement half (the two occurrences must match) and on a pin whose currency cannot be judged. The five mentions of the retired identifier now name the control that exists, and the retired name survives only inCHANGELOG/.Proof.
charly -C . task docs-pin→ 2 steps, 0 failed; the report names the live BEHIND state and exits 0; the self-test proves each of five states discriminates; a mutation that movesDOCS_REFand leaves the check's literal behind turns the task red;charly check run check-docs→ PASS (steps=16) with the newdocs-pin-statestep green inside it;charly box validate→ 0 warnings, 0 errors.What is next. The org's
charly/pr-validatorrules on #12. Once this repo merges and is tagged, the corpus leg follows — opencharly/marketplace#574 (the refs-list bump and the regeneration) — and the docs site after that. The umbrella's bridge, which will compose this task intocharly task verify, is a separate umbrella PR.When the next update is due. On the validator's verdict on #12, or on a request for changes there.
Agent: charly
Assisted-by: Claude Code minimax/minimax-m3.1-flash:cloud (fully tested and validated)
feat(task): add the docs-pin report — the DOCS_REF control this repo …
aitrawog commentedon Oct 24, 2026
RESOLVED — the delegated control now exists, the pin contract is enforced, and the
producer has landed.
What landed. #12 merged at
a22c63be65c50d582ebfec98508c00e3bc36cd73with the merge-time tag
v2026.297.0923pointing at that exact commit. The control thisissue asked for is
scripts/docs-pin-report.sh, wired into the repo as thedocs-pintask node and dispatched by the
check-docsbed stepdocs-pin-state.What it does. The report judges the
DOCS_REFpin against the docs repo's realmainhead, fetched withgit ls-remote:advance available NOW in opencharly/docs, not a defect;
gate;
DOCS_REFis declared — FAIL.Why it is trusted. Each state is proved by the state's own report, not only by an
exit status —
currentandBEHINDshare the exit code 0, so only the message tellsthem apart. All five branches are mutation-proven: each was broken on purpose and the
self-test turned red. The R10 gate (
check-docsbed) passed on the committed tree withthe changed path executing live inside it, and
charly box validatereported 0 warningsand 0 errors.
The root cause, for the record.
charly#452deleted the original implementation(
taskfiles/Docs.yml) when the docs candy moved out of the charly repo, and thedelegation was never taken up — so the five guidance surfaces pointed at a control that
did not exist, and the
DOCS_REFcontract this repo'sAGENTS.mdstates was unpoliced.The delegation is now taken up.
What is next. The
DOCS_REFre-pin itself is a separate, producer-first leg inopencharly/docs (the docs repo's
mainhas moved on since the last re-pin — thereport names the exact drift). This issue covers the control only.
Agent: charly
Assisted-by: Claude Code minimax/minimax-m3.1-flash:cloud (fully tested and validated)