Uh oh!
There was an error while loading. Please reload this page.
feat(docs-audit): anchor a changed @docs-rule block on the expressions it states - #9394
Conversation
📓 Docs Drift CheckThis PR changes 1 package(s): 6 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 1 release-owned page(s) also name something this change touched. These are read-only:
What this run could not seeCoarse fallback — 14 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop):
|
Uh oh!
There was an error while loading. Please reload this page.
Fixes#9282
The gap
packages/objectql/src/declared-fields.tsis 191 lines, 179 of them one doc comment thatis the canonical statement of the sparse-face guard rule, and one exported function. A
change confined to that comment derived no anchor at all, so the docs-drift run
reported "this run has no opinion" — which a reader reasonably takes as "nothing to
check" — while three pages restating the rule in prose sat unlisted.
Re-measured on current
origin/main(51cd953fb, i.e. after #9230 landed thecommandkind), the instance reproduces verbatim:
Why the coarse fallback was measured and rejected
Triage's route input was the package-mention fallback for an anchorless file's own package.
I priced it on this specimen before building anything, and it is wrong in both
directions — the exact failure the #9192 rewrite exists to undo:
ruleanchors)14 pages name
@objectstack/objectqlorpackages/objectql, and not one of them isautomation/flows.mdx,protocol/objectui/actions.mdxorui/actions.mdx. Those threedocument the authoring face and never name the implementing package at all. So bounded
width (14, not 140) does not rescue the fallback — it is 0-for-3 on recall on the single
instance it was proposed for. The measured width is reported here because that is what
turns this from a preference into a verdict.
What the restating pages do share with the rule is the expressions the rule is written
in. That is what this PR anchors on.
What landed
A fifth anchor kind,
rule, built on the precedent #9230 set forcommand:@docs-ruletag in a doc comment opts the block in. Ittakes no argument and carries no anchor list — it says derive anchors from this block,
never which. The anchors are read off the block's own code spans, so an author cannot
write one, forget to update one, or leave one behind: the marker lives inside the prose
it describes and is deleted with it. That is the whole difference from the hand-curated
registry of canonical-rule sites the card ruled out.
one-line refinement to any of them can stale any page restating any part. Line-scoping
measured this specimen down to zero: the changed line's own span was
has(), which isnot an expression.
isRuleExpressionrequires a comparison orlogical operator and a dotted-or-called reference. Both halves are load-bearing and
each drops a measured class: the operator half drops the block's caller list
(
visibleWhen,requiredWhen,readonlyWhen— admitting them took the specimen from 7pages to 27); the reference half drops prose a stray backtick paired across two lines.
rulejoinsPHRASE_ANCHOR_KINDSand then faces the existingcorpus-share guard unchanged. The shape guard is untouched for every single-token kind —
the exemption is beside it, never through it, and it is earned by construction: a span
carrying
&&or!=cannot be the bare lowercase word the guard exists to drop.The honest-failure property is preserved, and that is deliberate
The card is explicit that this run's shape was more honest than most — it said it had no
opinion and named the file it could not anchor, which is the only reason the defect was
filable. A fallback that quietly widened the list without saying it fell back would have
destroyed exactly that. Three disclosure paths, all verified end to end:
anchorlessChanges, never buried under a package-wide fallback.unanchoredRuleBlocksfield plus a summary note — modelled directly on [finding][devx] The docs-drift anchor derivation cannot see a CLI command name —os meta resyncis a lowercase word, so the shape guard drops it #9230'sunmappedCommandFiles, and reported besideanchorlessChanges, not instead of it,because such a file may still have anchored through
symbol.record.x != null (rule).Reverse verification, both legs predicted red in advance
Run from the committed state, so each leg has a real restore point.
Leg 1 — the measured instance. Replaying the specimen edit:
All three restating pages found (
*), each naming the anchor that put it there.Leg 2 — silence not traded for noise. Two sub-legs:
rule's statement did not change, so the restating pages are not dragged in. The file
anchors on
materializeDeclaredFieldsexactly as it always did.record-change-trigger.ts, thedeliberate structural mirror) still reports honestly:
no anchors derived, named inanchorlessChanges, 0 docs.A third check confirms the new disclosure fires: tagging a block with no expressions in it
produces
unanchoredRuleBlocks: ["packages/triggers/.../record-change-trigger.ts"]and thematching summary note.
Harness ablations — three, each red in the predicted direction, then restored green:
neutralising the operator half of
isRuleExpression(5 cases red); making the tagnon-optional so every doc comment becomes a rule block (2 cases red); collapsing
touchedinto the span set, which is what would destroy disclosure path 2 (1 case red).
Gates
Union run at
44225b82b, the final commit on this branch:pnpm check:docs-audit-scopenode scripts/docs-audit/check-affected-docs.mjspnpm check:nul-bytespnpm check:durability-log-levelnode scripts/check-engine-split-ratio.mjspnpm --filter @objectstack/objectql typecheckpnpm --filter @objectstack/objectql testRows 4 and 5 were not in the dispatch's gate list. I re-derived the family from my actual
changed paths with
node scripts/pm/dispatch-gates.mjs, and both were pulled in by thepackages/objectqlpath once the diff extended there. Named here per the rule that thedispatch list is a lead, not a spec. Rows 6 and 7 are the affected package's own checks.
Scope
Two files.
scripts/docs-audit/affected-docs.mjscarries the derivation;packages/objectql/src/declared-fields.tsgets the 12-line marker and nothing else — anopt-in mechanism with zero users would not close the ruling. The claim's file surface was
amended on the card in the same round.
skip-changeset: repo tooling plus a comment-only edit. Nothing published changes.Generated by Claude Code
Generated by Claude Code