11 KiB
11 KiB
name, description
| name | description |
|---|---|
| docs-dedupe-verify-campaign | Run an exhaustive docs dedupe + fact-verification campaign (command-center or any OKF vault, e.g. franksign): scout cluster ledgers, override scouts with evidence, gate every commit, and sweep scaffolding before PR. |
Exhaustive docs dedupe + verification campaign (dank/command-center; transplants to any OKF vault — proven on franksign 2026-10-21, #64 2026-10-21)
Frame
- Read
omp-docs/references/okf-spec.md(or the vault's vendored OKF contract, e.g.franksign-docs/read-only/okf-v0.2-spec.md) + rootindex.mdfirst; inventory withfind <vault> -name '*.md' | wc -l. - Run
scripts/kb-lint.sh omp-docsbaseline; index-coverage gate isscripts/kb-coverage.py omp-docs(each dir'sindex.mdmust link every sibling file/subdir). On franksign the whole mechanical gate is one seam:bun tests/lib/okf-lint.mjs(frontmatter, links, index coverage, version-once) — run it before and after. - Branch off fresh
origin/mainin a NEW worktree (git -C ~/.omp worktree add ~/.omp/wt/<name> -b docs/<issue>-slug origin/main) — workspace policy blocksgit checkout -bin session worktrees. In a session worktree,git checkout -bis intercepted anyway: commit on the session branch, then named-ref pushHEAD:refs/heads/docs/<n>-slug(verifygit log origin/main..HEADshows ONLY your commit first). - Open the Gitea issue first (multi-moving-parts law); branch name
docs/<issue#>-<slug>.
Scout fleet (overlap detection)
- One
taskcall,tasks[]batch, agentscout, read-only; one cluster per task. Fan out 2-3 clusters at a time, never seven:task.maxConcurrencyis 2 on this fleet, so the excess only queues, andproc://reports queued tasks asrunning— identical uptimes with zero deliveries means thrash, not progress (#64: seven scouts, nothing in 17 min; killing the five redundant ones let the two survivors land within minutes). - Do NOT scout a cluster you have already audited inline. Kill the redundant jobs early with
write proc://<id>/kill— the endpoint is the scarce resource, and your own session shares it. - Ledger format per cluster: inventory rows (file | verdict KEEP|MERGE|DELETE|VENDOR|UPDATE | evidence line/command). Demand the ledger as the yield TEXT, never a
local://file reference: #64 produced one 0-byte ledger plus three files whose names contained the scout's own serialized parameter block (gitea-caddy-inventory.md+ newline + a parameter tag), recoverable only byls-ing~/.omp/agent/sessions/<session>/local/<dir>/. - Scouts lie. Verified misses in the 2026-10-19 campaign: fabricated ledger entries ("peer-reviewed BrowseComp" claim that exists in no file), a DELETE verdict for a generated artifact that is checked in by design AND under test (
tools/niri/keybindings.md, seescripts/gen-keybinds.sh+tests/gen-keybinds.bats), and a KEEP for a leftover the scout misread its own changelog about. Franksign 2026-10-21: 2 of 3 cluster scouts fabricated — "7 missing component stories" refuted by the pairing-law seam that runs green on every push, invented entry/page counts, DELETE verdicts on live-box census numbers the purpose test KEEPS; a third hit the 30-min runtime cap producing zero output. #64 same day: three pages "missing an H1" that have one on their first heading line; a 215-lineomp-docs/AGENTS.mdthat does not exist; a "wikilinks + 700-char wall" defect incore/settings.mdthat a commit from that same morning had already removed;core/subagent-limits.mdcalled superseded whileagent/config.ymlcarries the citedmaxRuntimeMs/softRequestBudget/maxRecursionDepthvalues verbatim. - Four pre-checks before a scout row enters the diff: (1) the file exists; (2) the named heading/marker is actually absent (
grep -c '^# ',grep -c '^# Citations'); (3)git log --oneline -3 -- <file>— a same-day commit may already have fixed it; (4) if the claim is "config supersedes the doc", grep the config for the cited keys. - Cluster sizing: for a vault under ~20 pages, scout fleets are net-negative — audit inline yourself (reading 5 pages beats babysitting a scout). Reserve scouts for multi-hundred-page trees.
Mechanical sweeps that pay (run on every vault)
- Empty-text links:
grep -rnE '(^|[ ,])\]\(' <vault>— a generated "See Also" pass left five- ](index.md)links (#64); rendered, an empty bullet reads as style, never as a broken reference. - Citation convention census BEFORE adding anything: count
grep -rl '^resource:'againstgrep -rl '^# Citations'. command-center's convention isresource:frontmatter (12 vs 3) — "add Citations to six pages" is a convention change, not a fix; only the pages missingresource:were real hits. - Long-line walls:
awk 'length>300 {print FILENAME":"NR"("length")"}'— reflow prose to ~100 columns, wording intact; leave tables (they cannot wrap) and the text of verbatim blockquotes alone. - Dated log headings: three
## YYYY-MM-DDsections for one day is three logs wearing one date. Collapse to one##plus one###per campaign, and write the shape into the spec page so nobody has to infer it.
Fact verification
- Fleet facts: read-only probes over
ssh -o BatchMode=yes dankclaw|dankserver(podman ps/inspect/top, stat, /etc/os-release, curl localhost APIs,podman exec <c> <tool> --version). Live state beats docs even when docs claim recent verification — the 2026-10-18 "audit" still drifted (zealot 27B→9B, build 10754→10777, container census 14→32; #64 then found8C/16Twhere SMT is off, a "masked" unit that is simply absent, Pi-hole missing from a DNS list, and a weekly-drifting engine count that became a size class with/confignamed as the only authority). - Local box facts too:
pacman -Qs <pkg>/command -vbefore trusting a page's "installed tool" claim (#64:wlr-randrdocumented as available, never installed). - Unit health is not endpoint health: an
:7770that answers/v1/modelswhile its systemd unit sits inactiveResult=exit-codemeans a container escaped its unit. Report the drift to the operator; never record transient state as docs, and never touch a production unit without a per-run OK. - Code-bound facts (franksign-style): every doc claim about routes/columns/shipped status gets grepped against
apps/*/src,packages/db/migrations/— docs narrating features that never shipped ("page ships in the slice" while only the API landed) get truthed with a status pointer to the owning issue. - External claims: web_search/web read yourself (no subagents per Frank's rule). Kill fabrications outright (invented distro
FreeToken, nonexistentornith-llama-cpp-setuptree, unattributable "44.5% peer-reviewed CUA") — delete/drop with an explicit note, never keep "plausible" numbers. - Policy drift (live ≠ tuned docs): flag in the doc + PR body as an operator decision; NEVER silently re-apply policy.
- Deletion proposals from scouts die by default: archived trees carrying an honest archive banner (
pi/**, banner 2026-10-18) stay, a directoryindex.mdcannot be deleted (index-coverage gate), and incident logs are laws, not bookkeeping. Deletion is a pruning session with Frank present.
OKF §9 / frontmatter audit (cheap wins, check every vault)
- Log entries filed under the wrong ISO-date heading (crossed midnight): cut the entry (
CUT N.=M @reg), insert the new date heading above the old one (newest-first headings), paste the entry under it. - Missing trust family (
generatedon machine-written pages) — lint may not catch it; grep every frontmatter block. - Laws living only in
log.md: promote each to its owner page (mechanism law → architecture page owning the thing), leave the log entry as the incident record; the HANDOFF/README boundary then points at the vault instead of restating. - A law restated in two tiers (vault spec page + always-loaded
AGENTS.md) is not a duplicate to cut: name the co-ownership in the spec page ("change one, change the other") instead of silently dropping one copy.
Log compaction (log.md)
- Entry law: dated entry = what changed + durable lesson + concept-page pointer; narratives recoverable via
git log --follow. Record the law at the top of the log. Tag historical-era entries. - One
## YYYY-MM-DDper day,###per campaign. Put the fan-out and ledger-verification lesson in the entry — that is what stops the next campaign from trusting a scout.
Gates + landing
- Gate every commit:
bash scripts/kb-lint.sh omp-docs && python3 scripts/kb-coverage.py omp-docs && bats tests/. Pre-commit hook printserror: command not found: caddyon Caddyfile-touching commits — warning only, commit still lands. On franksign: kill the :3000 demo stack first (a live API hangs the gate ~10 min; law lives infranksign-docs/architecture/testing.md), thenbun tests/lib/okf-lint.mjs && tests/run.sh docs. - Before opening the PR:
git diff --stat origin/main..HEAD | grep -i 'tmp\|scratch\|\.bak'— scaffolding merged under a.tmp-name in the 2026-10-19 campaign and needed a follow-up PR to promote. - PR via API (skills
gitea-api-pr-operations,gitea-merge-form-encoded): token through a 600-perm-Kcurl config, never-H(/proc/<pid>/cmdlineis world-readable); create/PATCH = JSON WITH Content-Type, merge = form body with NO Content-Type,do=merge&merge_style=no-ff, success = HTTP 200 empty body verified by landed state, not by re-reading the PR.shred -uthe cfg and payload afterwards.xdg-openthe PR the moment it opens; comment the campaign ledger on the issue — ownership-move table, re-read facts with the command that read them, and rejected findings with their evidence. - After Frank's merge OK: propagate the deployment with
git -C ~/.omp fetch && git merge --ff-only origin/main, but first prove the FF cannot touch live machine-tier state:comm -12 <(git -C ~/.omp status --porcelain | grep -v '^??' | awk '{print $2}' | sort) <(git diff --name-only HEAD..origin/main | sort)must print nothing, and re-check the dirty count after the merge. - Worktree reaping is the live-sync heartbeat's job (
wt/*older than 7 days) unless Frank says otherwise — norm, no deleting a session branch you did not create.
Line-edit op syntax trap (bit five times)
- Valid ops:
PUT N.=M:(body+textlines),CUT N.=M/CUT N.=M @reg,PUT <N @reg,PUT >N:/PUT <N:. There is NOPUT N+=:form — it lands in the file as a literal garbage line and shifts the insert to the wrong position. For gap-insert use a lonePUT >N:orPUT <N:per call; pre-compute line numbers against the file map (ops reference original lines within one call, but a failed op poisons positions). - PUT with an empty body DELETES the range (franksign 2026-10-21: a typo-fix
PUT 7-7:with empty body deleted the whole entry). Bodyless deletes: useCUT N.=M. - A
CUT/PUTrange outside the file errors cleanly (out of range (file has N lines)) — that is the cheapest way to learn a body was shorter than assumed; re-read the tail rather than guessing offsets. - Bare body rows get auto-prefixed with
+and a warning — harmless, but never rely on it: prefix every body row yourself. - Editing a PUT body that ends adjacent to the next original line can silently consume the closing frontmatter
---— after any frontmatter-range PUT, re-read lines 1–10 of the result. - Recovery recipe when a literal op line lands: read exact bounds,
CUT N.=N(junk),CUT A.=B @block(misplaced section), thenPUT <M @blockat the true anchor, re-read tail, add spacing blank if a---now abuts a list line.