Skip to content

The docs-site guidance names a control (task docs:pin) that does not exist, so the DOCS_REF contract is unenforced #10

Closed

Description

@aitrawog

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:pin fails when DOCS_REF is not the docs repo's current main head (it fetches
ls-remote and compares — charly has no docs gitlink anymore: the docs repo is standalone,
and this candy's pin is the only thing that fixes what the bed tests).

and

task docs:pin therefore asserts BOTH: it compares DOCS_REF against the docs repo's
current main head 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:pin fails | DOCS_REF (or the check's literal sha) is not the docs repo's
    current main head — bump it in a charly PR"
    )
  • charly.yml — 2 (the DOCS_REF var's comment and the docs-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-commit check asserting a commit the image never builds — and the bed
    would still report PASS, because the check's literal and the clone's DOCS_REF are
    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-site is 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

  1. aitrawog commented on Oct 23, 2026

    @aitrawog
    ContributorAuthor

    CLAIM — this finding is surfaced while landing #8 (the DOCS_REF
    re-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:pin is not a task in
    this repo, in opencharly/charly, or in the umbrella — the command a reader would run
    fails 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 with
    the 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_REF names the docs repo's current
    main head in both occurrences and that the built image holds that commit — both proven
    by the check-docs bed on the committed tree. Whether a task also asserts those facts
    is 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=currency uses), or the five claims deleted with
    the 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)

  2. self-assigned this
    on Oct 23, 2026
  3. aitrawog commented on Oct 23, 2026

    @aitrawog
    ContributorAuthor

    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:

    taskfiles/Docs.yml - docs:pin greps candy/docs-site/charly.yml, which moved to
    opencharly/layer-docs-site. This one did NOT no-op: the grep on a missing file yields
    an empty DOCS_REF, which then compares unequal to the live docs HEAD, so the task
    reported drift and exited 1. charly cannot maintain another repo's pin; that check
    belongs to layer-docs-site
    .

    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) in
    CHANGELOG/2026.227.1426.md. The de-submodule cutover (charly#381) moved the candy's
    charly.yml out of the charly repo, which broke the task's grep; #452 removed the broken
    task and said where the check belongs.

    This repo never took the delegation. The five surfaces that still name
    task docs:pin were written against the charly repo's task, and nothing updated them
    when 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_REF equals the docs repo's current main head, compared with ls-remote
      (the old task's own mechanism), and
    • the sha occurs at least twice in charly.yml (both occurrences updated together).

    The shape of the gate is the one 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. 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.md already states, and the bed's docs-site-pinned-commit
    check 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)

  4. aitrawog commented on Oct 24, 2026

    @aitrawog
    ContributorAuthor

    STATUS — the delegated DOCS_REF control is implemented and up for review.

    Head. #12, branch feat/docs-pin-report-10, head 91f2da9da10aa3ad9958c6c026f9416a03426346, off fresh origin/main (e505b26).

    What is done. The delegation charly#452 left open is taken up: scripts/docs-pin-report.sh owns the report, the docs-pin task in charly.yml runs it plus its --self-test, and the check-docs bed 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 in opencharly/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 in CHANGELOG/.

    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 moves DOCS_REF and leaves the check's literal behind turns the task red; charly check run check-docs → PASS (steps=16) with the new docs-pin-state step green inside it; charly box validate → 0 warnings, 0 errors.

    What is next. The org's charly/pr-validator rules 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 into charly 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)

  5. aitrawog commented on Oct 24, 2026

    @aitrawog
    ContributorAuthor

    RESOLVED — the delegated control now exists, the pin contract is enforced, and the
    producer has landed.

    What landed. #12 merged at a22c63be65c50d582ebfec98508c00e3bc36cd73
    with the merge-time tag v2026.297.0923 pointing at that exact commit. The control this
    issue asked for is scripts/docs-pin-report.sh, wired into the repo as the docs-pin
    task node and dispatched by the check-docs bed step docs-pin-state.

    What it does. The report judges the DOCS_REF pin against the docs repo's real
    main head, fetched with git ls-remote:

    • the pin IS the head, and both occurrences of the sha agree — green;
    • the pin is BEHIND the head — REPORTED and green, because a pin that is behind is an
      advance available NOW in opencharly/docs, not a defect;
    • the two occurrences disagree — FAIL, because the tree contradicts itself;
    • the pin's currency cannot be judged — FAIL, because a gate that cannot judge is not a
      gate;
    • no DOCS_REF is declared — FAIL.

    Why it is trusted. Each state is proved by the state's own report, not only by an
    exit status — current and BEHIND share the exit code 0, so only the message tells
    them apart. All five branches are mutation-proven: each was broken on purpose and the
    self-test turned red. The R10 gate (check-docs bed) passed on the committed tree with
    the changed path executing live inside it, and charly box validate reported 0 warnings
    and 0 errors.

    The root cause, for the record. charly#452 deleted the original implementation
    (taskfiles/Docs.yml) when the docs candy moved out of the charly repo, and the
    delegation was never taken up — so the five guidance surfaces pointed at a control that
    did not exist, and the DOCS_REF contract this repo's AGENTS.md states was unpoliced.
    The delegation is now taken up.

    What is next. The DOCS_REF re-pin itself is a separate, producer-first leg in
    opencharly/docs (the docs repo's main has moved on since the last re-pin — the
    report 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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions