Repository navigation
Description
Objective
Declare DocTarget, DocComment, Docstring, Comment, DocRunOpener, DocRunDirective and HoldsDocInBody per language, so the documentation epic (#1654–#1682) lands its adapters on rows plus a DocBinding rather than a sixth per-language copy of kind membership. Keep every existing comment predicate and DLOC projection unchanged.
Umbrella: R00: #1690 · Planning ID: R09: #1699
Completion prerequisites: R03: #1693, R06: #1696 (both closed at the start of implementation). Must complete before #1655 freezes its contract; does not wait for R07: #1697, which is used only as an evidence-method source.
Why this exists
#1654's packages D07–D22 add documentation extraction across all 23 source variants. Each needs "which declaration kinds take a doc comment" — today is_doc_target in checker/*.rs, a hand-written matches! per language (Java's java_declaration names thirteen kinds) that already overlaps is_func, is_func_space and get_space_kind. If the epic ships before this exists it restates that list again, in a new file per language, and the next "doc comment on X is not attached" issue has the same trail shape as every other.
The scope is deliberately narrow, per the design review: rows remove the target-list copy only. Candidate selection (source vs legacy views — #1654 contract 2, with the Java empty-/**/ counter-example), profile composition, owner normalisation and text decoding are the epic's own work and are not kind membership. DocBinding (lang_helpers/doc_comment.rs: kept, skips, forward, gathers) stays as it is: its four callback contracts and every verdict are unchanged; where a callback's body restates a row's whole kind list (Kotlin's and PHP's forward), that membership read becomes the row's kind table and the callback's extra kinds stay with their exemption.
Docstring is a separate role from DocComment, because Python's docstring is a string expression, not a comment. Neither Python nor Elixir overrides is_doc_comment — both inherit the trait default false (checker.rs) — and Python's DLOC is computed by python_documentation_string_run in lang_helpers/python.rs, not through that predicate; Elixir's @doc attributes are not legacy DLOC at all. #1654 contract 11 keeps the broad discarded-string classification distinct from docstring recognition. So Docstring rows feed the Python LOC helper and, later, the epic's extraction; they never touch is_comment or is_doc_comment.
Premises corrected (2026-10-31, before implementation)
Re-verified against main at fdd12ad4 per AGENTS.md "Re-verify a deferred issue's premises". Each item below is a departure from the original wording of this issue; the reworded steps, tests and criteria follow.
- Doxygen run openers / directives.
checker/doxygen_doc_binding.rsholdsDOC_BINDINGandis_doc_targetonly.is_doc_run_openeris Lua and Ruby;is_doc_run_directiveis Go and Ruby. The C family declaresDocRunOpener/DocRunDirectiveabsent(Doxygen attaches every block to an entry; none documents by its own content). - Python assignment docs. Python has no
is_doc_target, so itsDocTargetrow isabsentand the parity exception is moot. The assignment-owner recognition an adapter needs already exists inlang_helpers/python.rs(Attributes::documented_by,assignment_target) and is named in the design(ast): define documentation association and extraction contracts #1655 touchpoint edit as a reusable helper outside this package's rows. is_commentreadslists_kind, notowns.Checker::is_comment(&Node)has no bytes and no chain, so it reads the ungated kind tablescomment::lists_kind ∪ doc_comment::lists_kind— the DSL's documented legacy spelling (roles/mod.rs).ownswith an invented empty chain would be the fix(ops): ops walk misses source-aware function spaces #1130 trap.- Rust's
DocCommentis child-gated, not text-gated.checker/rust.rsreads thedoc_commentchild the grammar marks and never the bytes; the row saysgated_by has_doc_marker_child. Commentis partitioned fromDocComment. A kind that is documentation by kind (Groovygroovydoc_comment, Perlpod_statement) sits only onDocComment;Commentholds the plain comment kinds. "Any comment" is the union of the two rows' kind tables, which is what makesis_doc_comment ⇒ is_commentstructural and testable. The role-set table inroles/mod.rsis reworded to match.HoldsDocInBodyis the residual set. The row declares only the kinds a language's Checker names beyondis_func ∨ is_closure(JavaStaticInitializer/Block/SwitchBlock, GroovyStaticInitializer, KotlinGetter/Setter/AnonymousInitializer, C#IndexerDeclaration/PropertyDeclaration); the full answer isfunc_opener::is_callable ∪ closure::owns ∪ holds_doc_in_body::owns, then the language's body-child test. The JS family declares itabsent: its override is the body-child test alone on the openers and closures, and feat(mi): stop charging documentation in the maintainability index #1597's inner-symbol policy isDOC_COMMENTS_IN_FUNCTION_BODIES, unchanged. The role-set table is reworded to match.DocTargetrows are candidates under local gates; parent/scope context stays in the Checker. A row owns a kind under gates that read the node itself (a declarator binds a name, a specifier has a body, a Go declaration is outside a function body). A clause that reads a different node's context — TypeScript'sexport/ambientparent and its inner-declaration sub-query, Ruby'sthen/ modifier unwrapping and YARD scope on the original node, Rust's any-named-kind tuple-struct slot, Doxygen'sERROR-holds-an-entry — stays a namedfninchecker/<lang>.rswith arole-bypass: allow(DocTarget) — contextmarker, and is named per language in the design(ast): define documentation association and extraction contracts #1655 touchpoint edit so an adapter composes it rather than re-deriving it. Where that makes the row over-approximate the Checker (a TS declaration underexport), a test pins it.- Lua. Lua never overrides
is_doc_target; its documentable-item list is consulted only after the---opener and content checks insideis_doc_run_opener. Lua'sDocTargetrow is read by that refinement only; the Checker'sis_doc_targetstays the defaultfalse, because forwarding it would let plain--runs document functions (a DLOC widening). Lua'sDocRunOpenerrow is the opener candidate where LDoc reads; thenext-dependent content decision stays in the Checker. - Doxygen's
doxygen_entryis a second query. It is "entry without conditionals", read byconditional_declares(post-order memo) andno_entry_inside;doxygen_targetis entry ∨ declaring-conditional. The migration keeps that projection (doxygen_entry::<T>testspreproc_conditionalbefore reading the row, so the memo walk is never re-entered) and deletesdoxygen_target. It matchesnode.kind()strings today, so the rows enumerate every alias id and a test asserts the id set equals the old name set exactly. Erroris not a row owner.utils/role_tables.pystrips the generatedERRORsentinel, so Doxygen's error clause stays in the helper.- Acceptance criterion 1 is reworded below from "no kind matched outside a row" to "no membership list restated", because twelve sites inside the boundary still compare a row-owned kind for a non-membership reason (a parent test, a scan terminator, a policy subset, a body-child test), each carrying an
allownaming the role.
Implementation steps
-
DocTargetrows;is_doc_targetreadsowns_DocTargetwith the existing ancestry gates (Java's package rule, fix(metrics/loc): six LOC fixes from the 2026-09-10 residue #1446) as named fns on the row where the gate reads the node's own chain, and in the Checker where it reads another node's context (see "Premises corrected"). -
CommentandDocCommentrows for comment-kind languages, text-gated where the tool reads the marker from bytes (Java/**, Doxygen's forms, KDoc, PHPDoc, C# XML docs, JSDoc / TSDoc, Perl POD) and child-gated for Rust//////!;is_commentreadslists_kind_Comment ∪ lists_kind_DocCommentsois_doc_comment ⇒ is_commentis structural — for comment kinds only. -
Docstringrows for Python (position-gated string expression, one owner per docstring — the statement value, never a fragment underconcatenated_string), read bypython_documentation_string_runat the point its backward scan already runs;is_doc_commentandis_commentfor Python stay at their current verdicts (both unchanged — the defaultfalseforis_doc_comment). Elixir's@doc/@moduledocrecognition is left to the epic (D19, feat(ast): extract Elixir documentation attributes #1676); declareabsent(Docstring, "extraction owned by #1676")for now. -
DocRunOpener/DocRunDirective/HoldsDocInBodyrows where a language has them (Lua and Ruby openers, Go and Ruby directives; JavaStaticInitializer/Block/SwitchBlockand the other residual kinds listed above); theiris_*impls read the rows, composed with the retained content / body-child refinements. - Note in
roles/mod.rsfor the epic: an adapter's recognition set is its rows, composed with the named context fns inchecker/<lang>.rs; itsDocBinding, selection and text work are not rows. Edit design(ast): define documentation association and extraction contracts #1655's "Implementation touchpoints" to namebig-code-analysis-ast/src/roles/<lang>.rsas the recognition source, link this issue, and name per language the reusable entry points (rows, context fns,doc_comment.rstext tests,doxygen.rsmechanism,python.rsrun and assignment helpers).
Tests and edge cases
-
src/metrics/loc/dloc.rsand the DLOC corpus snapshots byte-identical — DLOC must not widen (feat(ast): expose declaration documentation fragments and text across all languages #1654 contract 11). - Derived parity per language:
owns_DocTarget ⊆ owns_FuncOpener ∪ owns_Container ∪ owns_Memberevaluated on the same node and real chain, or an exception names it — asexcludes [K "why"]on the space-tree row where that row's author genuinely rejected the kind (JavaEnumConstantonMember), else in a test-side(language, kind, reason)table; both directions asserted so a stale entry fails. The Rust tuple-struct slot and Lua's default-falseChecker are non-row facts pinned by adapter tests. - Python:
is_commentandis_doc_commentverdicts on a docstring fixture unchanged (both false, beside a#comment answering true);docstring::ownsanswered directly on primary, additional, attribute, discarded, concatenated and non-strstrings;python_documentation_string_run's exact credited row sequence unchanged. - Zero drift; both snapshot forms; plain run.
Acceptance criteria
- No doc-target, comment or docstring membership list restated inside the boundary; every remaining compare of a row-owned kind carries a
role-bypass: allow(<Role>) — <reason>naming the role and its non-membership reason; bypass gate clean. - design(ast): define documentation association and extraction contracts #1655 edited and linked; D07–D22 can reference rows.
Verification and completion evidence
- DLOC corpus diff (all languages,
0 of N, with the command);BCA_GATE:line; the design(ast): define documentation association and extraction contracts #1655 edit linked.
Completion record (2026-11-01)
Landed as two commits on refactor/1699-doc-roles (S0 tooling e809a3d3; the migration). Counts on the final tree against fdd12ad4: corpus 0 of 46,592, fixtures 0 of 952, recovery 0 of 107,106, C-family per-node is_doc_target oracle 7,675,318 nodes byte-identical. Census 0 pending. #1655's touchpoints edited. Commands and the per-slice record are in the completion comment below.
Activity
dekobon commentedon Oct 23, 2026
Tracking is ready
The body now links the master issue and the work packages it references. Native parent and blocked-by relationships match the listed completion prerequisites. Implementation and acceptance checkboxes remain open; prerequisite closure and the R04: #1694 go decision govern execution order.
dekobon commentedon Nov 1, 2026
Premises re-verified; body amended before implementation
Implementation starts on
refactor/1699-doc-rolesfrommainatfdd12ad4. Per AGENTS.md "Re-verify a deferred issue's premises", the body was checked clause by clause against that tree before the first edit, and the departures are now recorded in a Premises corrected block in the body — not only here — because #1655 freezes against whatever this body says.Prerequisites: R03 (#1693) and R06 (#1696) are closed. R07 (#1697) is not a dependency; its oracle / recovery / perturbation drivers are reused as evidence method.
Two stale premises:
checker/doxygen_doc_binding.rs. That file holdsDOC_BINDINGandis_doc_targetonly;is_doc_run_openeris Lua + Ruby andis_doc_run_directiveis Go + Ruby. The C family's two rows areabsentwith the reason.is_doc_target. There is none, so Python'sDocTargetisabsent. The assignment-owner helpers an adapter needs (Attributes::documented_by,assignment_targetinlang_helpers/python.rs) are named in the design(ast): define documentation association and extraction contracts #1655 edit instead.Six readings the body now states explicitly, each argued from the signature or the DSL rather than preferred:
is_commentreadslists_kind, notownsChecker::is_comment(&Node)has no bytes or chain;lists_kindis the DSL's documented legacy spelling (roles/mod.rs).owns(node, &[], known(&[]))would be the #1130 shape.DocCommentis child-gatedchecker/rust.rs:57-64reads thedoc_commentchild, never the bytes.Comment∖DocCommentpartitiongroovydoc_commentand Perlpod_statementare documentation by kind; putting them only onDocCommentis what lets a test fail when the union is dropped fromis_comment. Empty/**/and a POD=begin commentregion stay(is_comment, is_doc_comment) = (true, false)via the ungated kind table.HoldsDocInBodyis residualis_func ∨ is_closure ∨ <extras>then a body-child test; the row owns the extras, so no kind is declared on two rows. The JS family's override is the body-child test alone, so its row isabsent; #1597's policy is the unchangedDOC_COMMENTS_IN_FUNCTION_BODIES.DocTarget= candidate + local gates; context in the Checker(node, code, ancestors)of the node asked about. TypeScript'sexportsub-query, Ruby's unwrapped core, Rust's any-kind tuple slot and Doxygen'sERRORclause each read a different node's context; those stay namedfns withallow(DocTarget) — context, named per language in the #1655 edit.is_doc_targetoverride exists; forwarding one would let--runs document (DLOC widening). The row is read by thenextrefinement ofis_doc_run_openeronly.Two mechanism facts the body now carries:
doxygen_entryis a separate "entry without conditionals" query with a post-order memo, kept as a projection over the row that testspreproc_conditionalfirst; andErrorcannot own a row (role_tables.pystrips the sentinel).Acceptance criterion 1 is reworded from "no kind matched inside the boundary outside a row" to "no membership list restated; every remaining compare carries an
allownaming the role" — twelve sites compare a row-owned kind as a parent test, scan terminator, policy subset or body-child test, and a row projection for each would be a second declaration with one reader.Plan of record: seven slices (comment-only languages → marker languages → positional languages → Doxygen family → JS family → Python → cross-cutting), reviewed at three checkpoints; zero-drift oracle at base and every slice; final history ≤ 3 commits.
dekobon commentedon Nov 1, 2026
Progress: S1 + S2 landed on
refactor/1699-doc-rolesS1 (
8e997a98) — Bash, Tcl, iRules, Ccomment, Preproc, Elixir:Comment+ sixabsentrows;impl_comment_from_rows!readscomment::lists_kind ∪ doc_comment::lists_kind;roles/doc_tests.rsper-node table. CP1 reviews (astra, sol, algorithmic-cost audit): 5 findings, all applied —absentreasons that claimed no tool exists (shdoc, Ruff!) reworded to "convention not recognised"; the Elixir@docnegatives anchored so the fixture cannot lose them; adlocmention removed from a row comment; the union's observability qualified; themod.rsallow rationale updated. Cost audit: release IR shows onekind_idFFI call + oneicmpperis_comment, strictly cheaper than theFrom<u16>round-trip it replaced.S2 (
edc1cf67) — Java, Groovy, Kotlin, C#, PHP, Rust, Perl:Comment,DocComment(text-gated; Rust child-gated),DocTarget,HoldsDocInBodywhere the Checker names residual kinds. Java's package rule is a row gate reading its ownlists_kind; Rust's tuple slot stays a Checker clause; Kotlin/PHPforwardread theDocTargetkind table; Groovygroovydoc_commentand Perlpod_statementsit onDocCommentalone (the partition the union exists for). 11 pre-existingrole-bypassexemptions gainedDocTarget/Commentwhere a newly claimed kind is compared for a non-membership reason.Zero drift (S2 tip
900176c8,bca68c230d210e8vs basefdd12ad43adf2747833b):oracle.pyovertests/repositories(four submodules at the SHAsfdd12ad4records) + the R07 fixtures + the new doc fixtures, sevenmetricsoption variants +ops/dump/find/count+ the verbatimFuncSpaceexport: 0 of 46,592 corpus outputs and 0 of 588 fixture outputs differ.Perturbations (S2): 22 single-edit mutants of a row kind, a gate's condition, or a Checker composition. 19 caught by the named
doc_teststest; 2 (Kotlin / PHPforwarddropping thelists_kindread) caught by the rootloc::suite; 1 (C# reading the row after the callable test) unobservable in any verdict — a cost fact, pinned by theloc/csharp-accessor-docsprobe — and the test comment now says so.Gates:
role-census144 → 72 pending (all R09),role-coverageremove-only,role-bypassOK;cargo nextest --workspace --all-features6631 passed; 0.snap.new, 0.pending-snap.Next: S3 (Go, Lua, Ruby —
DocRunOpener/DocRunDirective), then S4 Doxygen (CP2).dekobon commentedon Nov 1, 2026
Progress: S3 landed (
39df4cd2)Go, Lua, Ruby:
Comment,DocTargetunder the tools' scope and shape gates,DocRunDirective(go/doc directives, Ruby magic comments),DocRunOpener(LDoc---block, RDoc/YARD##/@!block where read);DocCommentabsent. Lua'sChecker::is_doc_targetstays the trait default — its row is read only by the opener's content decision (the fixture-decay guard is a row-true / Checker-false table). Ruby's wrappers and YARD scope stay as Checker context over the original node.Zero drift: 0 of 46,592 corpus outputs, 0 of 630 fixture outputs (
bcab17964b4d69fvs base3adf2747833b). Perturbations: 20 single-edit mutants, every one caught by a nameddoc_teststest (one needed a##-in-a-deffixture row to pin the opener's scope term; added). Gates: census 72 → 54 pending; coverage remove-only; bypass OK after 11 consumer sites gainedDocTarget/Commentin their existingallow; 6636 workspace tests; 0 pending snapshots.Next: S4 Doxygen (CP2). A per-node
is_doc_targetoracle over every C-family node of the corpus and six Doxygen fixtures (entries per dialect, an Objective-C header through C / C++ / Mozcpp, error recovery, a sole conditional child of an error) is captured at base: 7,674,389 nodes, 354,274 targets, to be compared line-for-line after the string-keyeddoxygen_entrybecomes id-keyed rows.dekobon commentedon Nov 1, 2026
Completion and evidence record
Branch
refactor/1699-doc-roles, two commits onfdd12ad4(origin/main):e809a3d3(S0, the bypass-gate self-test case) and the migration. Final tree identical to the pre-squash tip (backup/1699-before-squash, tree hash compared).What landed
roles/<lang>.rs(Comment,DocComment,Docstring,DocTarget,DocRunOpener,DocRunDirective,HoldsDocInBody); fragmentsc_family_doc_entries!,cpp_family_doc_entries!,c_family_doc_conditionals!,objc_doc_conditionals!(roles/c_family.rs),js_family_doc_targets!,ts_family_doc_targets!(roles/js_family.rs); gate emittersc_family_doc_gates!,js_family_doc_gates!,js_doc_gates!,ts_doc_gates!.Checkerforwards inchecker.rs:impl_comment_from_rows!(readscomment::lists_kind ∪ doc_comment::lists_kind),impl_doc_comment_from_row!,impl_doc_run_directive_from_row!(bytes,Ancestors::known(&[])),holds_doc_in_body_kind!(&[]underconst assert!(!TEXT_GATED)).role-bypass: allow(DocTarget …) — <reason>:tsdoc_target(declaration underexport/declare), Rubythenwrapper +ruby_yard_readsscope, Rust tuple-struct slot, DoxygenERRORholding an entry (lang_helpers::doxygen::doxygen_target), Lua's run-content decision.lang_helpers::doxygen:doxygen_targetis deleted as a string-keyed list and reborn as the row ∪ERRORcomposition;doxygen_entry::<T: DoxygenRow>reads the row directly,preproc_conditionalfirst (pinned by count: 12 reads vs 4,095 on the other order,doxygen_entry_never_reenters_the_conditional_walk);conditional_declareshands each child a chain ending in the conditional.lang_helpers::python:python_is_documentation_stringis theDocstringgate;python_documentation_string_runshares its one scan (one_scan_per_run_in_release, counterdocstring_runs_scanned). Newlang_helpers/ruby.rs(YARD scope fold, call forms).roles/doc_tests/{mod,doxygen,parity}.rs.roles/mod.rs: role-set table reworded; "For the documentation epic" note. design(ast): define documentation association and extraction contracts #1655 "Implementation touchpoints" edited (rows, context fns, reusable helpers per file) and its coordination section updated.Zero drift (final tree vs
fdd12ad4)Driver:
oracle.py(R07's, with.h→objcadded to the recovery populations) overtests/repositories(DeepSpeechaa1d2853, pdf.js65c4a4b3f, serded6de9118, big-code-analysis-outputaf5c6222), the R07 fixtures and 26 doc fixtures (one per language spelling every row owner and both sides of every gate; six Doxygen fixtures incl. an Objective-C header read as C / C++ / Mozcpp, recovery, a sole conditional child of an error). Sevenmetricsoption variants +ops/dump/find/count+ the verbatimFuncSpaceexport;compare.pyon each side's capture.Checker::is_doc_targetwith the real chain, error-recovered trees included (doxygen-oracle, four dialects, every.hthrough all four)Per slice (S1–S6) the same corpus compare read 0 of 46,592 each time; fixtures 0/588 → 0/952 as they grew; recovery 0/49,188 (S4), 0/40,104 (S5), 0/107,106 (S6).
One migration defect, caught before any capture saw it (astra + the cost audit at CP3, independently): the TypeScript export gate read its
declarationchild throughlists_kind, gates aside, so/** d */ export const {x} = o;documented (basedloc0 → S5 tree 1; no corpus file has a doc-commented destructuring export). Fixed byowns(&inner, …)with the export's chain; pinned asNONErows in the TS and TSX tables and inchecker_composes_the_row_with_the_wrapper_context. The row-level Python tuple over-approximation ("a", "b"after an assignment) was likewise invisible to the LOC walk and is nowis_bare_statementinsidedocumentation_run.Tests and perturbations
45 tests in
roles/doc_tests/: a per-node answer table per language (seven rows +is_comment/is_doc_comment, exact walk order, every declared owner met, defensive aliases declared-and-unseen),checker_composes_*where context composes (Java, Kotlin, C#, PHP, Rust, Lua, Ruby, TS, TSX), four exact alias guards (old_names_are_the_rowper Doxygen dialect — the row equals the id set the deleted name list denoted), theERRORclause on recovery fixtures, and three cross-language pins:doc_targets_outside_the_space_tree_are_each_named(declared lists, both directions),doc_targets_the_space_tree_rejects_by_gate_are_each_named(gated nodes with the real chain; C#'s bodied property / indexer are the named shapes; non-vacuity count per language),doc_comment_implies_comment_and_docstring_implies_neither(the Checker on nodes; a droppedDocCommentunion fails on Groovy).Perturbation sweeps (in-memory original, restore in
finally,old != newandcount == 1asserted per edit): S1 3, S2 22, S3 20, S4 12 + 5 (CP2), S5 14, S6 5, CP3 6 — every mutant of a row kind list, a gate's condition or a Checker composition fails a named test; the two cost facts no verdict can see (C# branch order, Python one scan per run) are pinned by observation counters (mutants 3 vs 0 searches; 2× scans).Gates (final tree)
make pre-commit→BCA_GATE: pass (gate=pre-commit)(also in a fresh worktree aftermake worktree-setup);make role-census0 pending (144 → 0),make role-coverageremove-only,make role-bypassOK (4 baselined sites, unchanged);make check-test-lang-gates-compare COMPARE_REF=origin/mainOK;make chain-audit613 passed;make bench-scaling99/99, doc-path probes 0.99–1.05;cargo llvm-covperci.yml+utils/patch-coverage.py … fdd12ad4: patch 99.49 % vs project 98.79 %; 0.snap.new/.pending-snap;-p big-code-analysis-ast --no-default-features --features {go,cpp,python,ruby}each green with differing filtered-out counts.Reviews
CP1 (S1), CP2 (S2–S4), CP3 (tip): astra, sol, an algorithmic-cost audit at each; at the tip also
code-review --effort max(correctness, cleanup), a least-reviewed pass, and two closing reviews (contract alignment: 1–8, 10 MET, 9 MET after the final re-capture; architecture). All findings applied or recorded as follow-ups on #1700 / #1701.dekobon commentedon Nov 1, 2026
Post-review update (tip
f4d35453one809a3d3)After the completion comment above, three skills and seven review rounds were applied and squashed into the migration commit. The work is unchanged in shape; what moved:
Found and fixed in review
conditional_declareshanded each conditional's children a copy of the walk's chain,O(depth)per conditional and quadratic over independent conditionals at growing depths (astra 1.85, cost audit 1.47 vs base 0.97 at depth 16k; the existing nest-axis probeloc/c-nested-conditional-docscould not see it). Now a one-entry context (chain_below, no allocation); new probeloc/c-conditional-per-struct-depthreads 1.50 with the copy, 1.04 without.no_entry_insidehands anERROR's child the same context (lesson 103), pinned byerror_child_is_asked_with_the_error_as_its_parent.loc/ruby-nested-doc-constants1.61 at 4k/8k/16k — and off by one).core_is_asked_with_its_own_chainholds the chain's parent to the tree's for every wrapper shape; mutants of both defects fail it.doc_tests/mod.rsharness lostc/cpp/mozcpp/objcfrom its cfg unions to a--fixthat read onlymod.rs(doxygen.rsreaches it viause super::*); every C-family single-language test build broke andlang-go (ast)clippy failed on an unused closure. Fixed with full unions +hand-written(c, cpp, mozcpp, objc)markers,c_entriescfg-gated, and acheck-test-lang-gates-test.pycase for the blind spot.union/enum/struct,#ifdef EMPTY,#elifdef, Gotype_elemoutside an interface, JSusing, TS/TSXcomputed_property_name/module/var/ generator / shorthand, TSX--> html); reachable kinds out ofdefensive; TSX now pins the whole TS table on its own ids;declaration_childrenheld to the grammar'sdeclarationsupertype fromnode-types.json; a deadOWNERS.len()assert dropped;check-role-bypass.pyvalidates the role of an exempted no-scopekind() == "…"site.owned_indialect lists derived from each dialect's space rows; a completeness pin againstroles::doc_target_rows()(itself held toLANG), filtered byis_enabled()so single-language legs pass.Answersslot readsChecker::is_doc_run_directivebeside its row — the last byte-less forward without a chain-dimension pin (mutant: Go + Ruby tables fail).Consolidation:
impl_doc_comment_rows_in_bodies!,impl_doc_target_from_row!,impl_byte_gated_row_predicate!,roles::byte_gate!;c_family_doc_entries!is the 11 shared kinds plusc_doc_declarations!/cpp_doc_entries!;DoxygenRow::doc_target_rowis an associated fn with noCheckersupertrait;YardScope::{DefBody, Namespace};owners_coveredserves all four harnesses (closingspace_tree_tests' weaker inline check); the Pythondebug_assert_eq!double scan removed (one_scan_per_runpinsrunsflat); the twouse crate::Cpp; let _ = …gate-steering hacks removed.Pre-existing, filed: #1767 — the
locwalk is quadratic in C++ namespace nesting depth onmain(found validating the probe; the probe nests structs to avoid it).Evidence on the final tree (
6c564d84≡f4d35453) vsfdd12ad4, same drivers and populations as above: corpus 0 / 46,592; fixtures (68 files) 0 / 952; recovery sweep 0 / 107,106, 0 failed; per-node C-familyis_doc_targetoracle byte-identical (7,675,318 lines).make pre-commitBCA_GATE: passin a fresh worktree aftermake worktree-setup, 0 pending snapshots;chain-audit617;bench-scaling100/100;check-test-lang-gates-compare COMPARE_REF=origin/mainOK;-p big-code-analysis-ast --no-default-features --features {objc,go,ruby}clippy clean,--features gotests 258 passed. Commands and captures:/var/tmp/bca/1699/PROVENANCE.md(tier 2; the counts are the record).Deferred to #1701 from the reviews:
CHAIN_GATEDfor the signature-less forwards (now the only unpinned axis), the four shape helpers inchecker.rstolang_helpers/, whetherlang_helpers/androles/join the bypass BOUNDARY (eleven markers moved there are prose today), a fn-pointer port replacingDoxygenRow,HoldsDocInBodynaming.docs(lessons): the per-call chain copy at every depth, reachable kind…
test: cover the patch's last production arms
bench: size the per-struct-depth conditional probe where the copy goe…
test(utils): pin the two-row kind forward as a bypass-gate forwarder
refactor(roles,checker): declare the documentation rows and read them…
docs(lessons): the per-call chain copy at every depth, reachable kind…
test: cover the patch's last production arms
bench: size the per-struct-depth conditional probe where the copy goe…