From 3fe37b186729f50d2dc699f8cf1eeb679a253e00 Mon Sep 17 00:00:00 2001 From: boshu <241868352+boshu2@users.noreply.github.com> Date: Wed, 8 Jul 2026 22:42:41 -0400 Subject: [PATCH] docs: repair strict docs-build link/anchor warnings + disposition the rest (age-y0ww) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make `scripts/docs-build.sh --check` a MEANINGFUL signal instead of advisory noise (was 82 strict-mode warnings, always ignored). Root cause: mkdocs --strict fails on 82 links that leave docs/ (the knowledge graph deliberately links out to skills/, scripts/, schemas/, evals/, and canonical repo-root docs). All 82 were verified to resolve to REAL repo files on disk — zero accidental breaks — so they are intentional cross-references, not bugs. Fixes (category A + B, INFO-level drift, verified against built HTML anchors): - Anchors: GLOSSARY SKILLS.md#beads->#beads-br; INCIDENT-RUNBOOK scenario-C double->single hyphen (x2); pawls.md directive-precedence / diversity-mode / escalation double->single (referrers in ADR-0007, autonomy-ladder, pawls self); catch-derived-fuel membrane update anchor (single + date suffix). - Suffixes: levels L1-L4 README next-level links + workflows meta-observer -> explicit README.md targets. Dispositions (category C + D): the 82 intentional external cross-refs are enumerated in tests/docs/mkdocs-strict-allowlist.txt and explained per-class in docs/docs-build-dispositions.md. `docs-build.sh --check` now runs mkdocs --strict end-to-end (nothing weakened, no --no-strict) and fails on any warning NOT on the allowlist — proven: a fresh broken link still fails the check; the 82 pass. Result: `docs-build.sh --check` is CLEAN-or-dispositioned (exit 0). Wired doc into nav + CONTRIBUTING pointer. --- docs/CONTRIBUTING.md | 2 +- docs/GLOSSARY.md | 2 +- docs/INCIDENT-RUNBOOK.md | 4 +- ...-deterministic-loop-only-operator-stops.md | 2 +- docs/architecture/autonomy-ladder.md | 2 +- docs/contracts/pawls.md | 14 +-- docs/docs-build-dispositions.md | 75 +++++++++++++++ .../catch-derived-fuel-council-and-probe.md | 2 +- docs/levels/L1-basics/README.md | 2 +- docs/levels/L2-persistence/README.md | 2 +- docs/levels/L3-state-management/README.md | 2 +- docs/levels/L4-parallelization/README.md | 2 +- docs/workflows/README.md | 2 +- mkdocs.yml | 1 + scripts/docs-build.sh | 95 ++++++++++++++++++- tests/docs/mkdocs-strict-allowlist.txt | 78 +++++++++++++++ 16 files changed, 264 insertions(+), 23 deletions(-) create mode 100644 docs/docs-build-dispositions.md create mode 100644 tests/docs/mkdocs-strict-allowlist.txt diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 3c0ec6648..f9f08776b 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -107,7 +107,7 @@ scripts/docs-build.sh --serve MkDocs-specific expectations: -- Every internal link must resolve. `mkdocs build --strict` fails on unresolved relative links; `tests/docs/validate-links.sh` catches the same class without a Python toolchain. +- Every internal link must resolve. `mkdocs build --strict` fails on unresolved relative links; `tests/docs/validate-links.sh` catches the same class without a Python toolchain. `--check` tolerates only the enumerated, intentional cross-references in `tests/docs/mkdocs-strict-allowlist.txt` (docs pages linking to real repo artifacts outside the site) — see [Docs-Build Dispositions](docs-build-dispositions.md); any *other* strict warning fails the build, so fix the link rather than silencing it. - Skill pages and the CLI reference are **generated at build time** from `skills/**/SKILL.md` and `cli/docs/COMMANDS.md` respectively — do not hand-author `docs/skills/*.md` or `docs/cli/commands.md`. - Navigation is declared in `mkdocs.yml` under `nav:`. New top-level docs need an entry there. diff --git a/docs/GLOSSARY.md b/docs/GLOSSARY.md index 780528ab9..2091bc33c 100644 --- a/docs/GLOSSARY.md +++ b/docs/GLOSSARY.md @@ -107,7 +107,7 @@ A shell script that fires automatically on agent lifecycle events. **AgentOps 3. Historical name for session-start knowledge loading. Retired as a skill: on-demand retrieval is `ao lookup --query ""`, and knowledge activation (beliefs/playbooks/briefings/gaps) lives in the operationalize skill. [Full documentation](../skills/operationalize/SKILL.md) ### Issue -A discrete unit of trackable work, stored as a bead. Created by `/plan`, executed by `/implement` or `/crank`. Has status, dependencies, and parent/child relationships. [Full documentation](SKILLS.md#beads) +A discrete unit of trackable work, stored as a bead. Created by `/plan`, executed by `/implement` or `/crank`. Has status, dependencies, and parent/child relationships. [Full documentation](SKILLS.md#beads-br) ## J diff --git a/docs/INCIDENT-RUNBOOK.md b/docs/INCIDENT-RUNBOOK.md index 693da7a2b..070827322 100644 --- a/docs/INCIDENT-RUNBOOK.md +++ b/docs/INCIDENT-RUNBOOK.md @@ -10,7 +10,7 @@ 1. [Emergency Kill Switches](#1-emergency-kill-switches) 2. [Scenario A: Broken Skills After Update](#2-scenario-a-broken-skills-after-update) 3. [Scenario B: Evolve Pushed Bad Code to Main](#3-scenario-b-evolve-pushed-bad-code-to-main) -4. [Scenario C: Skills Not Loading / CI Gate Failing](#4-scenario-c-skills-not-loading--ci-gate-failing) +4. [Scenario C: Skills Not Loading / CI Gate Failing](#4-scenario-c-skills-not-loading-ci-gate-failing) 5. [Rollback Options](#5-rollback-options) 6. [Root Cause Analysis](#6-root-cause-analysis) 7. [Prevention Checklist](#7-prevention-checklist) @@ -31,7 +31,7 @@ echo "incident $(date -Iseconds)" > ~/.config/evolve/KILL > session start, so there is no global "disable hooks" recovery step to take. Orientation is > explicit (`ao session bootstrap`, `ao inject`) and CI (`.github/workflows/validate.yml`) is the > authoritative gate. If you authored your own hooks via the `hooks-authoring` skill, see the -> note under [Scenario C](#4-scenario-c-skills-not-loading--ci-gate-failing) for how to disable them. +> note under [Scenario C](#4-scenario-c-skills-not-loading-ci-gate-failing) for how to disable them. --- diff --git a/docs/adr/ADR-0007-deterministic-loop-only-operator-stops.md b/docs/adr/ADR-0007-deterministic-loop-only-operator-stops.md index 3d847a732..1ba838894 100644 --- a/docs/adr/ADR-0007-deterministic-loop-only-operator-stops.md +++ b/docs/adr/ADR-0007-deterministic-loop-only-operator-stops.md @@ -23,7 +23,7 @@ - An empty claimable queue produces honest **operator-wait** (idle/sanity cycles), never false dormancy. - A genuine regression halts the loop so a human looks — the loop never papers over red. - The guarantee is testable: `tests/scripts/evolve-halt-check.bats` asserts both the gate's behavior and that the skill actually invokes it (no orphaned-primitive regression). -- The same operator-markers-are-authoritative principle generalizes to the **in-session** path: an autonomous-drive directive (a `/goal` Stop-hook, a `/loop`) cannot override a human STOP marker or a pawl HOLD any more than it can self-halt the evolve loop here. See [`pawls.md` § Directive precedence](../contracts/pawls.md#directive-precedence--autonomy-never-overrides-a-human-gate). +- The same operator-markers-are-authoritative principle generalizes to the **in-session** path: an autonomous-drive directive (a `/goal` Stop-hook, a `/loop`) cannot override a human STOP marker or a pawl HOLD any more than it can self-halt the evolve loop here. See [`pawls.md` § Directive precedence](../contracts/pawls.md#directive-precedence-autonomy-never-overrides-a-human-gate). ## Evidence this is needed diff --git a/docs/architecture/autonomy-ladder.md b/docs/architecture/autonomy-ladder.md index 2e4f8d136..9642597b5 100644 --- a/docs/architecture/autonomy-ladder.md +++ b/docs/architecture/autonomy-ladder.md @@ -113,7 +113,7 @@ draft-and-queue at every level. Symmetrically, **no autonomous-drive directive crosses a ceiling either**: a `/goal` Stop-hook ("do not pause to ask"), a `/loop`, or an unattended run moves the reasoning core's leash, never the boundary — a human STOP marker and a pawl -HOLD outrank any drive directive. See [`pawls.md` § Directive precedence](../contracts/pawls.md#directive-precedence--autonomy-never-overrides-a-human-gate). +HOLD outrank any drive directive. See [`pawls.md` § Directive precedence](../contracts/pawls.md#directive-precedence-autonomy-never-overrides-a-human-gate). ## See also diff --git a/docs/contracts/pawls.md b/docs/contracts/pawls.md index 8937cbfa7..1a57bf5c1 100644 --- a/docs/contracts/pawls.md +++ b/docs/contracts/pawls.md @@ -9,7 +9,7 @@ ## The rule 1. About to take an action? Check it against the pawl list **and the [blast-radius rule](#the-blast-radius-rule-the-list-is-examples-not-the-boundary)** below. -2. **A pawl (on the list, OR it trips any clause of the blast-radius rule) → fire the gate** ([`/pre-land-refuters`](../../skills/pre-land-refuters/SKILL.md)): an independent **fresh-context** reviewer (a separate invocation, no shared accumulated context with the author) must confirm before the action proceeds. Fail-closed (ambiguity → hold, never silent-proceed). Fresh-context is the **default** diversity mode; a pawl can be **opted up to multi-model** (≥2 model families) per the [Diversity mode](#diversity-mode--per-pawl-fresh-context-by-default) section below. +2. **A pawl (on the list, OR it trips any clause of the blast-radius rule) → fire the gate** ([`/pre-land-refuters`](../../skills/pre-land-refuters/SKILL.md)): an independent **fresh-context** reviewer (a separate invocation, no shared accumulated context with the author) must confirm before the action proceeds. Fail-closed (ambiguity → hold, never silent-proceed). Fresh-context is the **default** diversity mode; a pawl can be **opted up to multi-model** (≥2 model families) per the [Diversity mode](#diversity-mode-per-pawl-fresh-context-by-default) section below. 3. **Not a pawl (not on the list AND it trips no clause of the blast-radius rule) → chaos.** Just run it. No gate, no review, no ceremony. Iterate as wrong as you want between pawls — the pawls **reduce irreversible regression to the known one-way doors**, so between them you only ever touch state you can recover. (The list is the common instances; the **rule** is the authority — if an action trips a clause but isn't listed, it is still a pawl, and it's a missing list entry to add.) Why so few pawls: a pawl on *every* step is waterfall (validate every tread). It makes every wrong turn expensive and kills the cheap iteration that makes agents productive. The ratchet works **because** the pawls are few and sit only at the irreversible points. Adding a pawl is adding a tread you now validate — do it only when the action is genuinely one-way. @@ -24,10 +24,10 @@ Why so few pawls: a pawl on *every* step is waterfall (validate every tread). It | **schema / contract change** | Changing an interface, schema, or contract other code/agents depend on; regenerating a factory surface; repointing a contract test or canary | Downstream consumers break silently — "looks fine here" ≠ fine for them | [`scope`](../../skills/scope/SKILL.md) (frozen dirs) · contract-canary gates | | **credential / authority change** | Granting access, rotating or overwriting a credential, changing permissions or who-can-do-what | A granted/leaked credential or authority can't be cleanly un-granted; trust changes propagate | [`dcg`](../../skills/dcg/SKILL.md) · `claude-acct` fail-closed verify | | **spend** | Actions that cost real money or burn quota at scale: paid API runs, large agent fan-outs, deploys that bill | Money/quota is spent; you can't un-spend it | *(partial: fan-out consent)* | -| **plan-pawl** *(`multi-model`)* | Committing a **fanout-class / irreversible discovery plan** — an architecture fork, a one-way-door decision, a contract/coordination change — *before* the fan-out builds on it | Once N agents (or one expensive wave) build on the wrong plan SHAPE, the direction is costly-to-impossible to reverse; the plan is the architecture, and the architecture is the one-way door | the SAME enforcement as every pawl — the [`multi-model` diversity mode](#diversity-mode--per-pawl-fresh-context-by-default) (fresh-context floor **plus** ≥2 families) + [REFUTED→auto-redo loop + circuit-breaker](#escalation--the-circuit-breaker-model) **verbatim**, written through `schemas/pawl-verdict.v1.schema.json`. Invoked by the [`discovery`](../../skills/discovery/SKILL.md) skill's plan-pawl **duel** over the plan artifact (the consumer-side wiring is delivered by epic `age-plan-pawl-9yib`) | +| **plan-pawl** *(`multi-model`)* | Committing a **fanout-class / irreversible discovery plan** — an architecture fork, a one-way-door decision, a contract/coordination change — *before* the fan-out builds on it | Once N agents (or one expensive wave) build on the wrong plan SHAPE, the direction is costly-to-impossible to reverse; the plan is the architecture, and the architecture is the one-way door | the SAME enforcement as every pawl — the [`multi-model` diversity mode](#diversity-mode-per-pawl-fresh-context-by-default) (fresh-context floor **plus** ≥2 families) + [REFUTED→auto-redo loop + circuit-breaker](#escalation-the-circuit-breaker-model) **verbatim**, written through `schemas/pawl-verdict.v1.schema.json`. Invoked by the [`discovery`](../../skills/discovery/SKILL.md) skill's plan-pawl **duel** over the plan artifact (the consumer-side wiring is delivered by epic `age-plan-pawl-9yib`) | > **Scope note (plan-pawl).** The plan-pawl gates the plan's **SHAPE**, never behavior — it is the -> [`multi-model`](#diversity-mode--per-pawl-fresh-context-by-default) mode applied to the discovery +> [`multi-model`](#diversity-mode-per-pawl-fresh-context-by-default) mode applied to the discovery > *plan artifact* instead of a code diff (recombination + naming, not a new engine). It **never** > replaces the acceptance-test layer: a clean cross-family plan review still misses defects only a > running test catches (the 2026-06-12 auth-bypass learning). It is **risk-class-gated** — ON for @@ -36,7 +36,7 @@ Why so few pawls: a pawl on *every* step is waterfall (validate every tread). It > cross-family-review gates (the single-judge fanout approval + the pre-mortem council) into one gate > — that consumer-side fusion is wired into the discovery skill by epic `age-plan-pawl-9yib` (this > contract row defines the pawl + its governance; it does not itself edit the discovery skill). The escalation governor (auto-redo on REFUTED; -> human only on a tripped circuit breaker) is the [circuit-breaker model](#escalation--the-circuit-breaker-model) above, unchanged. +> human only on a tripped circuit breaker) is the [circuit-breaker model](#escalation-the-circuit-breaker-model) above, unchanged. ## The blast-radius rule (the list is examples, not the boundary) @@ -198,7 +198,7 @@ The model has two layers: a **default auto-redo loop**, and a set of **tunable c This breaker-governed escalation is the **andon** ("Hey! Listen!") — rare and *earned*, never the default. Even fully unattended, the gate runs model-to-model at every pawl and auto-redoes on REFUTED; pulling a human in is the exception that fires only when a tunable circuit breaker trips — and until the human acts, the pawl **holds**. -> **Scope note (threat model).** The pawl verdict (`schemas/pawl-verdict.v1.schema.json`) is an **evidence-bound, commit-bound verdict that requires real reviewer runs** — it defends against a *sloppy agent that skips the real review and self-stamps CONFIRMED*. It is **not** cryptographic provenance: there are no signatures, no peercred, no OS-level writer separation, and cryptographic un-forgeability against a hostile forger is **intentionally out of scope** (single-operator trusted loop — the cut cathedral). What the gate guarantees is that a review *actually ran* (evidence files exist + non-empty), against the *current commit* (head_sha == the PR's live head), by reviewer(s) meeting the pawl's **diversity mode** — fresh-context (≥1 fresh red-team, model-agnostic) by default, or multi-model (the fresh-context floor **plus** ≥2 roster-validated families — strictly stronger) where a pawl is opted up (see [Diversity mode](#diversity-mode--per-pawl-fresh-context-by-default)). +> **Scope note (threat model).** The pawl verdict (`schemas/pawl-verdict.v1.schema.json`) is an **evidence-bound, commit-bound verdict that requires real reviewer runs** — it defends against a *sloppy agent that skips the real review and self-stamps CONFIRMED*. It is **not** cryptographic provenance: there are no signatures, no peercred, no OS-level writer separation, and cryptographic un-forgeability against a hostile forger is **intentionally out of scope** (single-operator trusted loop — the cut cathedral). What the gate guarantees is that a review *actually ran* (evidence files exist + non-empty), against the *current commit* (head_sha == the PR's live head), by reviewer(s) meeting the pawl's **diversity mode** — fresh-context (≥1 fresh red-team, model-agnostic) by default, or multi-model (the fresh-context floor **plus** ≥2 roster-validated families — strictly stronger) where a pawl is opted up (see [Diversity mode](#diversity-mode-per-pawl-fresh-context-by-default)). ## Directive precedence — autonomy never overrides a human gate @@ -208,7 +208,7 @@ A pawl **HOLD** (the merge held on a breaker trip, above) and a **human STOP/KIL the boundary: **no drive directive overrides a HOLD or a human STOP**, and "be autonomous" is *never* authorization to self-approve a door a human deliberately gated. -- The two HOLD senses are distinct: a **breaker-HOLD** holds the *merge* until a breaker clears (the [Escalation](#escalation--the-circuit-breaker-model) model above); a **human STOP marker** halts the *loop* (the evolve Red Button / [`halt-check.sh`](../../scripts/evolve/halt-check.sh) — pre-cycle, mechanical, "not prose the agent can rationalize past"). Neither is overridable by a drive directive. +- The two HOLD senses are distinct: a **breaker-HOLD** holds the *merge* until a breaker clears (the [Escalation](#escalation-the-circuit-breaker-model) model above); a **human STOP marker** halts the *loop* (the evolve Red Button / [`halt-check.sh`](../../scripts/evolve/halt-check.sh) — pre-cycle, mechanical, "not prose the agent can rationalize past"). Neither is overridable by a drive directive. - This **generalizes the evolve Red Button to the in-session path**: an explicit human-authorization gate (a typed ACK on an irreversible action) is a marker in the boundary — an active drive directive does not consume or satisfy it. A drive loop may re-enter and re-present the gate; it does not cross it. Crossing requires the marker cleared by the human, not by the directive that said "keep going". ## Adding a pawl @@ -230,7 +230,7 @@ The cross-family pawl can run as a **standing warm service** (`ao pawl up` — c ## Strict two-family cold quorum — the portable `multi-model` door (age-rk3r.13) -The [`multi-model`](#diversity-mode--per-pawl-fresh-context-by-default) mode above is the strongest +The [`multi-model`](#diversity-mode-per-pawl-fresh-context-by-default) mode above is the strongest diversity requirement, and until now the only place it ran *portably* was the warm tri-family duel (operator machinery). **`ao verify --strict`** (or the `strict: true` key in `.aoverify.yaml` → `PAWL_STRICT`) is the **cold, portable** `multi-model` door: it runs **two DISTINCT strict-eligible diff --git a/docs/docs-build-dispositions.md b/docs/docs-build-dispositions.md new file mode 100644 index 000000000..383957637 --- /dev/null +++ b/docs/docs-build-dispositions.md @@ -0,0 +1,75 @@ +# Docs-build known warnings (dispositions) + +`scripts/docs-build.sh --check` runs `mkdocs build --strict` end-to-end and then +reinterprets the result against an allowlist of **dispositioned** warnings. The +check is CLEAN when the only strict warnings are enumerated, intentional +cross-references; **any warning not on the allowlist fails the build**, so a new +or accidental broken link still breaks `--check`. Nothing is globally suppressed +(no `--no-strict`) — this is a baseline, not a blanket waiver. + +- **Allowlist (source of truth):** `tests/docs/mkdocs-strict-allowlist.txt` — the + verbatim `WARNING - …` lines that are tolerated (whole-line, exact match). +- **Runner:** `scripts/docs-build.sh --check` (also wired as pre-push gate step + 25a — advisory in the fast cockpit lane, blocking in CI / the bushido refinery). +- **Complementary checker:** `tests/docs/validate-links.sh` + + `tests/docs/broken-links-allowlist.txt` validate on-disk link targets across + `docs/`, `skills/`, `skills-codex/`, `cli/`; `--check` is the end-to-end + MkDocs-render complement. + +## Why these warnings exist + +The AgentOps knowledge graph deliberately links from `docs/` narrative pages out +to the **real repo artifacts** they describe — skills, scripts, schemas, eval +data, and the canonical repo-root docs. Those artifacts are intentionally **not** +part of the published MkDocs site (`docs_dir: docs`), so MkDocs cannot resolve the +link and emits a strict `links.not_found` WARNING. The link is correct for a repo +or GitHub reader; it is simply outside the site boundary. Re-pointing such a link +at an in-site generated stub (e.g. a `gen-files` skill page) would break the +GitHub reader, so the deliberate choice is to keep the repo-true link and +disposition the warning. + +## Dispositioned classes (the 82 tolerated warnings) + +All 82 allowlisted warnings were verified to resolve to a **real repo file on +disk**; none is an accidental typo. They group as: + +| Class | Target (outside `docs/`) | Example referrer | Rationale | +|-------|--------------------------|------------------|-----------| +| Skill cross-refs | `../skills//SKILL.md`, `../../skills//SKILL.md` | `GLOSSARY.md`, `SKILLS.md`, `context-lifecycle.md`, `contracts/pawls.md`, `architecture/*` | Points at the canonical skill source (SSOT). The in-site skill pages are generated stubs; the SKILL.md is the real target for repo readers. | +| Scripts | `../../scripts/*.sh` (`pawl.sh`, `pawl-review.sh`, `pawl-verdict.sh`, `reconcile-pr.sh`, `evolve/halt-check.sh`) | `contracts/pawls.md`, `doctrine/operating-discipline.md` | Executable source; not site content. | +| Schemas | `../../schemas/*.json` (`learning.v1`, `pawl-verdict.v1`) | `contracts/corpus-learning-seam.md`, `doctrine/operating-discipline.md` | Declared contracts; live under `schemas/`, not the site. | +| Eval artifacts | `../../evals/membrane/**` (json/jsonl/sh/py scorecards + derived checks) | `evals/harvest-*.md`, `evals/local-membrane-vs-codex-*.md`, `evals/membrane-escape-harvest-no-escape.md` | Raw eval evidence kept as repo artifacts, not re-hosted in the site. | +| Repo-root docs | `../../GOALS.md`, `../../PRODUCT.md`, `../../AGENTS-{WORKFLOW,CI,CODEX,RUNTIME}.md`, `../../README.md#…`, `../../cli/docs/COMMANDS.md`, `../../skills/SKILL-TIERS.md`, `../../.claude/workflows/operating-loop.js` | `architecture/codebase-overview.md`, `architecture/control-loop-model.md`, `architecture/workflow-conformance-pattern.md`, `doctrine/lineage-and-theory.md`, `comparisons/vs-hosted-code-review.md` | Canonical repo-root files that are the source of truth; the site links to them rather than duplicating. | +| Skill-relative schema | `schemas/audit-report.json` in the generated `skills/heal-skill.md` page | (generated) | The link resolves in the skill's own tree (`skills/heal-skill/schemas/audit-report.json`); the schema subfolder is not copied into the generated page. Source is `skills/**` (out of scope to edit). | + +## Non-fatal INFO notices (not counted by strict, not allowlisted) + +MkDocs also logs INFO-level notices that do **not** abort a strict build and so +need no allowlist entry. They are recorded here for completeness: + +- **Excluded templates (13):** links from `documentation-index.md`, + `architecture/intent-to-loop-hexagon.md`, and `architecture/operating-loop.md` + to `templates/*.md`. Templates are intentionally excluded from the built site + but referenced for repo readers. Intentional. +- **`../../skills/domain/references/` (3):** directory links from + `architecture/canonical-loop-model.md` (×2) and `architecture/operating-loop.md` + to a skill reference directory outside the site. No in-site target; intentional. +- **`acceptance-tests/` (2):** from + `plans/bdd-foundry/behavior-first-planning-for-the-recon-re/acceptance-tests.md` + and `plans/bdd-foundry/canonicalize-bdd-foundry-workflow/spec.md`. These point at + a real **directory of test files** (`.bats`, `.sh`, `.go.txt`), not the sibling + `acceptance-tests.md` doc — MkDocs' "did you mean `.md`" suggestion would + misdirect the link, so it is left as-is. Intentional. +- **`skills/discovery.md#open-ended-path-…` (1):** a same-page anchor on the + generated discovery skill page. The source is `skills/discovery/SKILL.md` + (`skills/**`, out of scope for docs-only work); the anchor resolves in the + rendered page. Left for the skill owner. + +## Maintenance + +- When a doc link breaks: **fix the link first.** Only add a line to + `tests/docs/mkdocs-strict-allowlist.txt` when the target is a real repo artifact + that is deliberately outside the docs site and there is no in-site equivalent. +- After an intentional doc move, run `scripts/docs-build.sh --check`; it prints any + un-dispositioned warning verbatim so the allowlist line can be updated. +- Keep the allowlist entries as the exact `WARNING - …` lines MkDocs emits. diff --git a/docs/evals/catch-derived-fuel-council-and-probe.md b/docs/evals/catch-derived-fuel-council-and-probe.md index 1524cb66a..d5219c890 100644 --- a/docs/evals/catch-derived-fuel-council-and-probe.md +++ b/docs/evals/catch-derived-fuel-council-and-probe.md @@ -66,7 +66,7 @@ supports (does not prove) TIERED_MIDDLE. The value half was **subsequently tested** once a stronger producer (Qwen2.5-Coder-32B) supplied real compiling-but-subtly-wrong samples (see -[the stronger-producer run](./membrane-escape-harvest-no-escape.md#update--stronger-producer-qwen25-coder-32b-the-substrate-exists-but-the-membrane-still-catches)). +[the stronger-producer run](./membrane-escape-harvest-no-escape.md#update-stronger-producer-qwen25-coder-32b-the-substrate-exists-but-the-membrane-still-catches-2026-06-22)). Qwen shipped two compiling subtle schema bugs (`rfd-codex-schema`, `rfd-nested-schema`) that the Haiku **panel** caught 3/3. The transfer test: does a catch-derived check help a **cheaper tier** (a single, terse "fast skim" diff --git a/docs/levels/L1-basics/README.md b/docs/levels/L1-basics/README.md index 2c2b56561..bd6718b50 100644 --- a/docs/levels/L1-basics/README.md +++ b/docs/levels/L1-basics/README.md @@ -41,4 +41,4 @@ See the `demo/` directory for real session transcripts. ## Next Level -Once comfortable with single-session work, progress to [L2-persistence](../L2-persistence/) to add cross-session memory. +Once comfortable with single-session work, progress to [L2-persistence](../L2-persistence/README.md) to add cross-session memory. diff --git a/docs/levels/L2-persistence/README.md b/docs/levels/L2-persistence/README.md index fe3b789a6..c5ee9501a 100644 --- a/docs/levels/L2-persistence/README.md +++ b/docs/levels/L2-persistence/README.md @@ -46,4 +46,4 @@ Add the `.agents/` directory for cross-session memory. ## Next Level -Once comfortable with persistence, progress to [L3-state-management](../L3-state-management/) to add issue tracking. +Once comfortable with persistence, progress to [L3-state-management](../L3-state-management/README.md) to add issue tracking. diff --git a/docs/levels/L3-state-management/README.md b/docs/levels/L3-state-management/README.md index 8c93e7996..65dbbdeb0 100644 --- a/docs/levels/L3-state-management/README.md +++ b/docs/levels/L3-state-management/README.md @@ -50,4 +50,4 @@ BEADS_DIR="$(ao beads dir)" br sync --flush-only # Export the git-JSONL l ## Next Level -Once comfortable with issue tracking, progress to [L4-parallelization](../L4-parallelization/) to execute waves. +Once comfortable with issue tracking, progress to [L4-parallelization](../L4-parallelization/README.md) to execute waves. diff --git a/docs/levels/L4-parallelization/README.md b/docs/levels/L4-parallelization/README.md index f28668dc5..7053f6a12 100644 --- a/docs/levels/L4-parallelization/README.md +++ b/docs/levels/L4-parallelization/README.md @@ -143,4 +143,4 @@ Agents do ONE thing. Mayor handles orchestration. ## Next Level -Once comfortable with waves, progress to [L5-orchestration](../L5-orchestration/) for full autonomy with `/crank`. +Once comfortable with waves, progress to [L5-orchestration](../L5-orchestration/README.md) for full autonomy with `/crank`. diff --git a/docs/workflows/README.md b/docs/workflows/README.md index b5b394fee..a55402dd2 100644 --- a/docs/workflows/README.md +++ b/docs/workflows/README.md @@ -88,7 +88,7 @@ tree. **When to use:** Coordinating N autonomous workers through shared memory (stigmergy) without central orchestration. **Complexity:** High (advanced, multi-session) **Key skills:** /swarm -**Deep dive:** [meta-observer/](meta-observer/) (pattern guide, examples, showcase) +**Deep dive:** [meta-observer/](meta-observer/README.md) (pattern guide, examples, showcase) ## Flowchart diff --git a/mkdocs.yml b/mkdocs.yml index f8feb5671..ea9cf1f35 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -257,6 +257,7 @@ nav: - Schemas: SCHEMAS.md - Testing: TESTING.md - CI/CD: CI-CD.md + - Docs-Build Dispositions: docs-build-dispositions.md - Releasing: RELEASING.md - Incident Runbook: INCIDENT-RUNBOOK.md - Troubleshooting: troubleshooting.md diff --git a/scripts/docs-build.sh b/scripts/docs-build.sh index 8b2b79736..ccda00d18 100755 --- a/scripts/docs-build.sh +++ b/scripts/docs-build.sh @@ -54,11 +54,98 @@ case "$mode" in exec mkdocs serve --dev-addr 127.0.0.1:8000 ;; --check|check) - # Strict build, discard output dir + # Strict build, discard output dir. `mkdocs build --strict` runs end-to-end + # (nothing is weakened); the exit is then reinterpreted against an allowlist of + # DISPOSITIONED warnings — intentional cross-references from docs/ pages to real + # repo artifacts outside the published site (skills/, scripts/, schemas/, evals/, + # repo-root docs). Any strict warning NOT in the allowlist still fails the check, + # so new/accidental broken links break the build. See + # docs/docs-build-dispositions.md + tests/docs/mkdocs-strict-allowlist.txt. + allowlist="$REPO_ROOT/tests/docs/mkdocs-strict-allowlist.txt" tmp_site="$(mktemp -d)" - trap 'rm -rf "$tmp_site"' EXIT - mkdocs build --strict --site-dir "$tmp_site" - echo "OK: mkdocs build --strict passed" + build_log="$(mktemp)" + # shellcheck disable=SC2064 + trap "rm -rf '$tmp_site' '$build_log'" EXIT + + set +e + mkdocs build --strict --site-dir "$tmp_site" >"$build_log" 2>&1 + mkdocs_rc=$? + set -e + + # Surface the full build log for the operator. + cat "$build_log" + + # Hard errors (config/plugin failures) are never tolerated. + if grep -qE '^ERROR ' "$build_log"; then + echo "" >&2 + echo "FAIL: mkdocs strict build hit a hard error (see log above)" >&2 + exit 1 + fi + + warnings="$(grep -E '^WARNING ' "$build_log" || true)" + + # A nonzero mkdocs exit that produced NO strict warnings (and no ^ERROR, + # checked above) is an UNEXPLAINED failure — mkdocs missing (exit 127), + # crashed, or a failure mode we do not pattern. Never certify OK on it: + # keying the pass purely on grepping the log would let a broken/missing + # mkdocs (e.g. a fake `mkdocs` that exits 127 first in PATH) print OK. + # A clean strict pass is rc=0; a strict-warnings failure is rc!=0 WITH + # warnings (dispositioned below). rc!=0 with no warnings is a hard fail. + if [[ "$mkdocs_rc" -ne 0 && -z "$warnings" ]]; then + echo "" >&2 + echo "FAIL: mkdocs build --strict exited ${mkdocs_rc} with no strict warnings to" >&2 + echo " disposition — mkdocs is missing, crashed, or hit an unrecognized" >&2 + echo " failure. NOT certifying OK. See the build log above." >&2 + exit 1 + fi + + if [[ -z "$warnings" ]]; then + echo "OK: mkdocs build --strict passed (0 warnings)" + exit 0 + fi + + # Filter comments/blank lines out of the allowlist, then subtract exact, + # whole-line matches. Anything left is an un-dispositioned warning. + allow_tmp="$(mktemp)" + # shellcheck disable=SC2064 + trap "rm -rf '$tmp_site' '$build_log' '$allow_tmp'" EXIT + if [[ -f "$allowlist" ]]; then + grep -vE '^[[:space:]]*(#|$)' "$allowlist" > "$allow_tmp" || true + fi + + if [[ -s "$allow_tmp" ]]; then + undisposed="$(printf '%s\n' "$warnings" | grep -vxF -f "$allow_tmp" || true)" + else + undisposed="$warnings" + fi + + if [[ -n "$undisposed" ]]; then + echo "" >&2 + echo "FAIL: un-dispositioned mkdocs strict warnings. Fix the link, or — only if it" >&2 + echo " is an intentional cross-reference to a real repo artifact outside the" >&2 + echo " docs site — add the verbatim line to tests/docs/mkdocs-strict-allowlist.txt:" >&2 + printf '%s\n' "$undisposed" >&2 + exit 1 + fi + + # All warnings are dispositioned — but a nonzero mkdocs exit must be EXPLAINED + # by the strict-warnings abort, not a crash that merely ALSO emitted an + # allowlisted warning. mkdocs prints "Aborted with N warnings in strict mode!" + # only when it aborts ON warnings; a Python crash/traceback exits nonzero + # WITHOUT that line. So a nonzero exit lacking the signature is a hard failure + # (contract: hard errors are never tolerated), even though the allowlist emptied + # `undisposed`. (Closes: a fake mkdocs that prints one allowlisted warning + a + # traceback and exits 1 would otherwise certify OK.) + if [[ "$mkdocs_rc" -ne 0 ]] && ! grep -qE 'Aborted with [0-9]+ warning.* in strict mode' "$build_log"; then + echo "" >&2 + echo "FAIL: mkdocs build --strict exited ${mkdocs_rc} without the strict-warnings" >&2 + echo " abort signature — it crashed rather than aborting on warnings, so the" >&2 + echo " allowlist must not certify it OK. See the build log above." >&2 + exit 1 + fi + + allowed_count="$(printf '%s\n' "$warnings" | grep -c '^WARNING ' || true)" + echo "OK: mkdocs build --strict clean; ${allowed_count} dispositioned cross-references tolerated (tests/docs/mkdocs-strict-allowlist.txt)" ;; --clean|clean) rm -rf _site diff --git a/tests/docs/mkdocs-strict-allowlist.txt b/tests/docs/mkdocs-strict-allowlist.txt new file mode 100644 index 000000000..0d085712c --- /dev/null +++ b/tests/docs/mkdocs-strict-allowlist.txt @@ -0,0 +1,78 @@ +# MkDocs strict-build dispositioned warnings (age-y0ww) +# +# Each line below is an EXACT mkdocs --strict WARNING that scripts/docs-build.sh +# --check tolerates because it is an INTENTIONAL cross-reference from a docs/ page +# to a real repo artifact that lives OUTSIDE the published site (docs_dir). These +# links resolve for repo/GitHub readers; mkdocs cannot resolve them because the +# target is not part of the built site. See docs/docs-build-dispositions.md for the +# per-class rationale. +# +# Format: the verbatim `WARNING - ...` line mkdocs emits (whole-line, exact match). +# The check FAILS on any strict warning NOT listed here, so NEW/accidental broken +# links still break the build — this is a baseline, not a blanket suppression. +# Add a line here ONLY after confirming the target is a real repo artifact that is +# deliberately outside the docs site; prefer FIXING the link when a docs-site target +# exists. Blank lines and lines starting with '#' are ignored. +# +# Regenerate/refresh after an intentional doc move: +# scripts/docs-build.sh --check # prints any un-dispositioned warning verbatim + +WARNING - Doc file 'GLOSSARY.md' contains a link '../skills/beads-br/SKILL.md', but the target is not found among documentation files. +WARNING - Doc file 'GLOSSARY.md' contains a link '../skills/council/SKILL.md', but the target is not found among documentation files. +WARNING - Doc file 'GLOSSARY.md' contains a link '../skills/crank/SKILL.md', but the target is not found among documentation files. +WARNING - Doc file 'GLOSSARY.md' contains a link '../skills/handoff/SKILL.md', but the target is not found among documentation files. +WARNING - Doc file 'GLOSSARY.md' contains a link '../skills/operationalize/SKILL.md', but the target is not found among documentation files. +WARNING - Doc file 'GLOSSARY.md' contains a link '../skills/post-mortem/SKILL.md', but the target is not found among documentation files. +WARNING - Doc file 'GLOSSARY.md' contains a link '../skills/pre-mortem/SKILL.md', but the target is not found among documentation files. +WARNING - Doc file 'GLOSSARY.md' contains a link '../skills/research/SKILL.md', but the target is not found among documentation files. +WARNING - Doc file 'GLOSSARY.md' contains a link '../skills/standards/SKILL.md', but the target is not found among documentation files. +WARNING - Doc file 'GLOSSARY.md' contains a link '../skills/swarm/SKILL.md', but the target is not found among documentation files. +WARNING - Doc file 'GLOSSARY.md' contains a link '../skills/validate/SKILL.md', but the target is not found among documentation files. +WARNING - Doc file 'SKILL-ROUTER.md' contains a link '../skills/ms/SKILL.md', but the target is not found among documentation files. +WARNING - Doc file 'SKILLS.md' contains a link '../skills/ms/SKILL.md', but the target is not found among documentation files. +WARNING - Doc file 'architecture/codebase-overview.md' contains a link '../../AGENTS-CI.md', but the target '../AGENTS-CI.md' is not found among documentation files. +WARNING - Doc file 'architecture/codebase-overview.md' contains a link '../../AGENTS-CODEX.md', but the target '../AGENTS-CODEX.md' is not found among documentation files. +WARNING - Doc file 'architecture/codebase-overview.md' contains a link '../../AGENTS-RUNTIME.md', but the target '../AGENTS-RUNTIME.md' is not found among documentation files. +WARNING - Doc file 'architecture/codebase-overview.md' contains a link '../../AGENTS-WORKFLOW.md', but the target '../AGENTS-WORKFLOW.md' is not found among documentation files. +WARNING - Doc file 'architecture/codebase-overview.md' contains a link '../../GOALS.md', but the target '../GOALS.md' is not found among documentation files. +WARNING - Doc file 'architecture/codebase-overview.md' contains a link '../../cli/docs/COMMANDS.md', but the target '../cli/docs/COMMANDS.md' is not found among documentation files. +WARNING - Doc file 'architecture/codebase-overview.md' contains a link '../../skills/SKILL-TIERS.md', but the target '../skills/SKILL-TIERS.md' is not found among documentation files. +WARNING - Doc file 'architecture/control-loop-model.md' contains a link '../../PRODUCT.md', but the target '../PRODUCT.md' is not found among documentation files. +WARNING - Doc file 'architecture/operating-loop.md' contains a link '../../skills/automation-shape-routing/SKILL.md', but the target '../skills/automation-shape-routing/SKILL.md' is not found among documentation files. +WARNING - Doc file 'architecture/operating-loop.md' contains a link '../../skills/rpi/references/agile-replan-loop.md', but the target '../skills/rpi/references/agile-replan-loop.md' is not found among documentation files. +WARNING - Doc file 'architecture/operating-loop.md' contains a link '../../skills/using-atm/SKILL.md#when-to-use-atm-vs-am-the-4-case-matrix', but the target '../skills/using-atm/SKILL.md' is not found among documentation files. +WARNING - Doc file 'architecture/workflow-conformance-pattern.md' contains a link '../../.claude/workflows/operating-loop.js', but the target '../.claude/workflows/operating-loop.js' is not found among documentation files. +WARNING - Doc file 'architecture/workflow-conformance-pattern.md' contains a link '../../skills/workflow-builder/SKILL.md', but the target '../skills/workflow-builder/SKILL.md' is not found among documentation files. +WARNING - Doc file 'comparisons/vs-hosted-code-review.md' contains a link '../../README.md#the-honest-version', but the target '../README.md' is not found among documentation files. +WARNING - Doc file 'context-lifecycle.md' contains a link '../skills/council/SKILL.md', but the target is not found among documentation files. +WARNING - Doc file 'context-lifecycle.md' contains a link '../skills/post-mortem/SKILL.md', but the target is not found among documentation files. +WARNING - Doc file 'context-lifecycle.md' contains a link '../skills/pre-mortem/SKILL.md', but the target is not found among documentation files. +WARNING - Doc file 'context-lifecycle.md' contains a link '../skills/validate/SKILL.md', but the target is not found among documentation files. +WARNING - Doc file 'contracts/corpus-learning-seam.md' contains a link '../../schemas/learning.v1.schema.json', but the target '../schemas/learning.v1.schema.json' is not found among documentation files. +WARNING - Doc file 'contracts/pawls.md' contains a link '../../scripts/evolve/halt-check.sh', but the target '../scripts/evolve/halt-check.sh' is not found among documentation files. +WARNING - Doc file 'contracts/pawls.md' contains a link '../../scripts/pawl-review.sh', but the target '../scripts/pawl-review.sh' is not found among documentation files. +WARNING - Doc file 'contracts/pawls.md' contains a link '../../scripts/pawl.sh', but the target '../scripts/pawl.sh' is not found among documentation files. +WARNING - Doc file 'contracts/pawls.md' contains a link '../../skills/dcg/SKILL.md', but the target '../skills/dcg/SKILL.md' is not found among documentation files. +WARNING - Doc file 'contracts/pawls.md' contains a link '../../skills/discovery/SKILL.md', but the target '../skills/discovery/SKILL.md' is not found among documentation files. +WARNING - Doc file 'contracts/pawls.md' contains a link '../../skills/pre-land-refuters/SKILL.md', but the target '../skills/pre-land-refuters/SKILL.md' is not found among documentation files. +WARNING - Doc file 'contracts/pawls.md' contains a link '../../skills/scope/SKILL.md', but the target '../skills/scope/SKILL.md' is not found among documentation files. +WARNING - Doc file 'doctrine/lineage-and-theory.md' contains a link '../../PRODUCT.md#strategic-bet', but the target '../PRODUCT.md' is not found among documentation files. +WARNING - Doc file 'doctrine/lineage-and-theory.md' contains a link '../../PRODUCT.md', but the target '../PRODUCT.md' is not found among documentation files. +WARNING - Doc file 'doctrine/operating-discipline.md' contains a link '../../schemas/pawl-verdict.v1.schema.json', but the target '../schemas/pawl-verdict.v1.schema.json' is not found among documentation files. +WARNING - Doc file 'doctrine/operating-discipline.md' contains a link '../../scripts/pawl-verdict.sh', but the target '../scripts/pawl-verdict.sh' is not found among documentation files. +WARNING - Doc file 'doctrine/operating-discipline.md' contains a link '../../scripts/reconcile-pr.sh', but the target '../scripts/reconcile-pr.sh' is not found among documentation files. +WARNING - Doc file 'evals/harvest-2026-06-22-escape-series-for-e5.md' contains a link '../../evals/membrane/harvest-2026-06-22/derived-check-rfd-nested-schema.md', but the target '../evals/membrane/harvest-2026-06-22/derived-check-rfd-nested-schema.md' is not found among documentation files. +WARNING - Doc file 'evals/harvest-2026-06-22-escape-series-for-e5.md' contains a link '../../evals/membrane/harvest-2026-06-22/escape-rate-series.jsonl', but the target '../evals/membrane/harvest-2026-06-22/escape-rate-series.jsonl' is not found among documentation files. +WARNING - Doc file 'evals/harvest-2026-06-22-escape-series-for-e5.md' contains a link '../../evals/membrane/harvest-2026-06-22/harvest-to-ledger.sh', but the target '../evals/membrane/harvest-2026-06-22/harvest-to-ledger.sh' is not found among documentation files. +WARNING - Doc file 'evals/harvest-2026-06-22-escape-series-for-e5.md' contains a link '../../evals/membrane/harvest-2026-06-22/run-harvest-series.sh', but the target '../evals/membrane/harvest-2026-06-22/run-harvest-series.sh' is not found among documentation files. +WARNING - Doc file 'evals/harvest-2026-06-22-escape-series-for-e5.md' contains a link '../../evals/membrane/harvest-2026-06-22/scorecard.json', but the target '../evals/membrane/harvest-2026-06-22/scorecard.json' is not found among documentation files. +WARNING - Doc file 'evals/harvest-2026-06-22-escape-series-for-e5.md' contains a link '../../evals/membrane/harvest-2026-06-22/summarize-series.py', but the target '../evals/membrane/harvest-2026-06-22/summarize-series.py' is not found among documentation files. +WARNING - Doc file 'evals/local-membrane-vs-codex-2026-06-23.md' contains a link '../../evals/membrane/membrane-compare-2026-06-23/A-local-qwen.json', but the target '../evals/membrane/membrane-compare-2026-06-23/A-local-qwen.json' is not found among documentation files. +WARNING - Doc file 'evals/local-membrane-vs-codex-2026-06-23.md' contains a link '../../evals/membrane/membrane-compare-2026-06-23/B-codex.json', but the target '../evals/membrane/membrane-compare-2026-06-23/B-codex.json' is not found among documentation files. +WARNING - Doc file 'evals/local-membrane-vs-codex-2026-06-23.md' contains a link '../../evals/membrane/subtle-escape-2026-06-23/A-local.json', but the target '../evals/membrane/subtle-escape-2026-06-23/A-local.json' is not found among documentation files. +WARNING - Doc file 'evals/local-membrane-vs-codex-2026-06-23.md' contains a link '../../evals/membrane/subtle-escape-2026-06-23/B-codex.json', but the target '../evals/membrane/subtle-escape-2026-06-23/B-codex.json' is not found among documentation files. +WARNING - Doc file 'evals/local-membrane-vs-codex-2026-06-23.md' contains a link '../../evals/membrane/subtle-escape-2026-06-23/full-A-local.json', but the target '../evals/membrane/subtle-escape-2026-06-23/full-A-local.json' is not found among documentation files. +WARNING - Doc file 'evals/local-membrane-vs-codex-2026-06-23.md' contains a link '../../evals/membrane/subtle-escape-2026-06-23/full-B-codex.json', but the target '../evals/membrane/subtle-escape-2026-06-23/full-B-codex.json' is not found among documentation files. +WARNING - Doc file 'evals/membrane-escape-harvest-no-escape.md' contains a link '../../evals/membrane/flywheel-harvest.workflow.js', but the target '../evals/membrane/flywheel-harvest.workflow.js' is not found among documentation files. +WARNING - Doc file 'evals/membrane-escape-harvest-no-escape.md' contains a link '../../evals/membrane/harvest.sh', but the target '../evals/membrane/harvest.sh' is not found among documentation files. +WARNING - Doc file 'skills/heal-skill.md' contains a link 'schemas/audit-report.json', but the target 'skills/schemas/audit-report.json' is not found among documentation files.