=== RESEARCH ===
{'issue': 304, 'kind': 'docs', 'defect_status': 'confirmed', 'category': 'ci-decision', 'target_files': ['docs/lint_docs.jl', '.github/workflows/DocsLint.yml'], 'summary': 'Create docs/lint_docs.jl implementing the seven mechanical docrule checks and wire it as a standalone (non-Documentation) CI gate that starts green on the current docs/src.', 'current_state': 'docs/lint_docs.jl does not exist (ls: No such file or directory). CI.yml has only the rng-lint job (CI.yml:111-143); no docs linter. The workflow the issue tells the implementer to wire into — the "Documentation workflow" — was deleted (commit 54a5657 "move doc compilation off CI"; make.jl:113-116: "Since v0.6.x docs are NOT built or deployed by CI (Documentation.yml removed 2026-07-10)"), and CI.yml path-ignores docs/** and **.md (CI.yml:8,10). So the issue\'s CI-wiring instruction and its "keep separate from T011\'s example-verification step" are stale — that step is gone. The upstream structural deps have landed in-tree: skeleton sections present (docs/src has 49 `## Quick Start`, 43 `## Complete Example`, 48 `## Common Pitfalls`, 50 `## References` across 58 pages; the 15 pages lacking Complete Example are the hubs/API/index — index.md, plotting.md, structural_identification.md, the *Overview* hubs io.md/innovation_accounting.md/nongaussian.md/tests.md, io_* leaves, dsge_continuous.md, api*.md); API split present (make.jl:100-104); docrule rules present (docrule.md:7-48 anatomy, :95/:140/:189/:370 no-println, :130/:345-359 iframe+save_plot, :138 single group name). Gregory-Hansen DOI is NOT in docs/src (grep of docs/src finds only prose \'Gregory-Hansen\', no DOI string); audit report line 367 confirms it is a genuine Elsevier PII DOI. 43 pages carry `| Default` keyword tables (check-7 scope).', 'proposed_change': 'Create docs/lint_docs.jl (standalone Julia script, `julia --project=docs`) that scans docs/src/**.md and reports `file:line [RULE-ID] message`, exiting non-zero on any violation. Implement the seven checks exactly per docrule.md (treat docrule as the spec — there is no literal \'§7\'; map to the sections cited above):\n  1. Skeleton-per-page-type. Classify each page as Hub vs Method by reading docs/make.jl `pages=` (make.jl:24-105): pages that are the FIRST child under a section header, or are titled "Overview", plus a small hardcoded hub allowlist (index.md, plotting.md, structural_identification.md, api.md/api_types.md/api_functions.md, io.md, innovation_accounting.md, nongaussian.md, tests.md, dsge.md) are Hubs; the rest are Methods. Method pages MUST have `## Quick Start`, `## Complete Example`, `## Common Pitfalls`, `## References` (anatomy docrule.md:7-48). Hubs require the hub skeleton (decision table + one Quick Start + child list + References) and MUST NOT be required to have a Complete Example. No H4 (`#### `) on narrative pages. Note: the 15 currently-Complete-Example-less pages listed in current_state must all classify as Hub or the gate starts red — verify the allowlist covers exactly them.\n  2. Single group name per page: each page uses exactly one `@setup`/`@example` NAME (docrule.md:138 "All blocks on a page share the same group name"); flag pages with >1 distinct name.\n  3. No `println` for results inside ```@example blocks (docrule.md:95,140,189,370). Allow println only outside @example blocks; the docrule permits println for scalar diagnostics, so scope the ban to @example blocks and consider a `# lint: ignore`-style opt-out mirroring rng-lint (CI.yml:134).\n  4. No bare hard-coded counts in prose ("NN plot dispatches/pages/methods") not wrapped in `@eval` (Writing Voice / anti-pattern; docrule.md Writing Voice section ~line 64).\n  5. Every embedded iframe `src` (docrule.md:130,345-359) resolves to a file on disk under docs/src/assets/plots/ (or the built assets dir).\n  6. `save_plot` filenames in ```julia blocks match the iframe `src` on the same page (docrule.md §Embedding Plot Iframes, :345-366).\n  7. Keyword-table defaults vs signatures: parse Markdown tables having a "Default" column (43 such pages) and compare against `methods(f)`/signature introspection where f is loadable from MacroEconometricModels; SKIP-with-warning (not fail) rows that can\'t be parsed reliably.\nOptional check 4/DOI: if any DOI/citation-bijection check is added it must RESOLVE DOIs (not pattern-match) and allowlist 10.1016/0304-4076(69)41685-7 (audit report:367) — but note this DOI is not currently in docs/src, so this is precautionary and may be deferred.\nCI wiring (RE-DERIVE — issue is stale): do NOT target the deleted Documentation workflow and do NOT add to CI.yml (it path-ignores docs/**, CI.yml:8,10). Create a new .github/workflows/DocsLint.yml triggered on push/PR touching docs/** and (for check 7) src/**, running `julia --project=docs docs/lint_docs.jl`; gate = job green. Before enabling, run the linter locally against current docs/src and fix or file any residual violations so it starts green (per acceptance criteria). This is docs-quality tooling only (no public API touched) so it fits the v0.6.7 b-bump, but it is L-effort and the "must start green" requirement may surface additional doc edits — budget accordingly and land it LAST in the release so it encodes the final page set.', 'verify': 'After implementing, run `julia --project=docs docs/lint_docs.jl` (scans docs/src/**) and confirm exit code 0 with no violations on the current tree; also lint the new workflow with `actionlint .github/workflows/DocsLint.yml` if available. No makedocs/verify_examples run is needed since this issue adds a script, not a page edit (verify_examples.jl remains the separate example-execution gate).', 'dependencies': [], 'collisions': ['docs/make.jl pages= tree — any #276-331 issue that adds/removes/renames a doc page changes the hub/method classification input the linter reads (make.jl:24-105); linter must land after all such issues', 'docs/src/*.md skeleton sections — any #276-331 issue adding/removing a page or its Quick Start/Complete Example/References sections can flip a page red; linter must start green against the FINAL page set', 'docs/docrule.md — any #276-331 issue that edits the docrule rules the linter encodes (anatomy :7-48, no-println :95/:140/:189/:370, iframe/save_plot :130/:345-366, single-group :138)', '.github/workflows/CI.yml — any concurrent CI-editing issue (kept decoupled here by using a new DocsLint.yml rather than editing CI.yml)'], 'effort': 'L', 'risk': 'med'}

=== VERIFY ===
{'issue': 304, 'verdict': 'CORRECTED', 'assessment': 'Defect is REAL and in-scope for the v0.6.7 b-bump. Confirmed independently: docs/lint_docs.jl does not exist; no docs-lint CI job (only CI.yml rng-lint at 111-143). CI re-derivation is CORRECT: Documentation.yml was deleted in 54a5657 (make.jl:113-116 confirms), CI.yml path-ignores docs/** and **.md (lines 8,10), so a new .github/workflows/DocsLint.yml is right - and this even matches issue #304\'s own text ("in the Documentation workflow or a docs-lint workflow"). Structural facts confirmed: skeleton counts 49/43/48/50 across 58 pages exact; API split make.jl:100-104; 43 pages with |Default| tables; docrule no-println at 95/140/189/370, single-group at :138, scalar-diagnostic carve-out at :189; docrule has NO literal section 7 (named sections) so research\'s mapping is correct. However TWO spec errors make it incomplete. (1) current_state\'s claim "Gregory-Hansen DOI is NOT in docs/src" is FALSE - it is live at docs/src/tests_breaks.md:609 as 10.1016/0304-4076(69)41685-7; the "DOI allowlist may be deferred because absent" rationale is unfounded. (2) The proposed hub classification will NOT start green: verified skeletons show dsge_continuous.md (QS=1/CP=1/Ref=1, CE=0) and io_classical/io_environmental/io_baqaee_farhi/io_download.md (no skeleton at all) are neither Overview nor first-child nor in the hardcoded allowlist, so they classify as Method and fail check-1; separately the "first child under a section header -> Hub" heuristic misclassifies filters/manual/regression/pvar/nowcast (all full Method skeleton QS/CE/CP/Ref=1) as Hubs, risking Hub-skeleton failure. Fix direction is right; the literal classification and DOI premise are wrong/incomplete.', 'corrections': '1) FACTUAL: the Gregory-Hansen DOI IS in the current tree at docs/src/tests_breaks.md:609 (10.1016/0304-4076(69)41685-7). current_state is wrong. Because it is in-tree, IF the implementer adds any DOI/citation-bijection check it MUST allowlist that PII-DOI and RESOLVE (not pattern-match) DOIs, per issue #304 acceptance criterion; it is not deferrable on the false ground of absence. (DOI-check itself remains optional, not one of the 7 mandatory checks.)\n\n2) CLASSIFICATION must be reworked so check-1 starts green - the literal proposed algorithm does not. Two concrete failures verified against current skeletons:\n   (a) Under-inclusive allowlist: dsge_continuous.md, io_classical.md, io_environmental.md, io_baqaee_farhi.md, io_download.md are Complete-Example-less but are NOT Overview, NOT first-child, and NOT in the proposed hardcoded hub list. As written they classify as Method -> require Complete Example -> gate starts RED. The implementer must EITHER add these 5 pages to the hub set / a curated exception list, OR add the missing skeleton sections (scope-expanding doc work).\n   (b) Over-inclusive "first child -> Hub" heuristic: filters.md, manual.md, regression.md, pvar.md, nowcast.md are the FIRST child under their sections but are full Method pages (QS/CE/CP/Ref all present). Classifying them Hub then applies the Hub decision-table/child-list requirement and can fail. Drop the "first child" heuristic; base Hub detection on "Overview" title + an explicitly curated allowlist reconciled against the ACTUAL current skeleton state (the spec\'s own instruction "verify the allowlist covers exactly them" is unsatisfiable with the allowlist as literally listed).\n\n3) Ordering/scope (research already got this right, reaffirm): land LAST in v0.6.7 after every #276-331 doc-page/skeleton/docrule change, since those change the classification input; the "must start green" requirement plus the 5 CE-less leaf pages means either doc-content additions or a hand-curated hub map - keep effort L. Verify method: run `julia --project=docs docs/lint_docs.jl` for exit 0; do NOT run makedocs/verify_examples (separate gate).', 'collision_issues': [], 'discriminating_power': 'n/a - this issue adds a docs-lint script and a CI workflow, not test assertions.', 'final_effort': 'L'}