Skip to content

fix(scripts): resolve Record<K,V> intersection-type keys in check-docs-drift's field walker (#8656) - #8720

Merged
JSONbored merged 2 commits into
JSONbored:mainfrom
RealDiligent:fix/critical-issue-docs-drift-record-intersection-8656
Jul 26, 2026
Merged

fix(scripts): resolve Record<K,V> intersection-type keys in check-docs-drift's field walker (#8656)#8720
JSONbored merged 2 commits into
JSONbored:mainfrom
RealDiligent:fix/critical-issue-docs-drift-record-intersection-8656

Conversation

@RealDiligent

Copy link
Copy Markdown
Contributor

Problem

Closes #8656.

scripts/check-docs-drift.ts's extractTypeLiteralFieldEntries parses a type by brace-counting from the first { to its match. For an intersection type like:

export type FocusManifestFeaturesConfig = { present: boolean } & Record<ConvergedFeatureKey, boolean | null>;

brace-counting closes right after present: boolean, so the & Record<...> half — the 8 real feature keys (rag, reputation, safety, grounding, e2eTests, screenshots, improvementSignal, amsReputationBridge) and FocusManifestExperimentalConfig's gittensor — was never inspected. The checker had zero power to catch a 9th or renamed key landing without a doc update.

Fix

Parse the intersection's Record<K, V> half and resolve K's string-literal members to their own field entries:

  • inline "a" | "b" literals;
  • a locally-declared string-literal union type;
  • the (typeof SOME_ARRAY)[number] const-array indirection that ConvergedFeatureKey / ExperimentalPluginKey actually use.

Fully general — any { ... } & Record<...> in the scanned source, no type name hardcoded. A non-literal key (Record<string, V>, a number alias, an unresolvable identifier) resolves to nothing, so no field names are ever invented.

The real FocusManifest field count rises 106 → 115 (the 8 feature keys + gittensor), and the drift check still passes against the current .loopover.yml.example (all 9 already documented — no false positives).

Tests

test/unit/check-docs-drift-script.test.ts:

  • A fixture exercising every key form — inline literal, (typeof ARR)[number] const-array union, direct string-literal union, and non-literal keys (number/string/unresolvable) that must yield no fields — covering every new branch.
  • A live-source assertion that features.rag … features.amsReputationBridge and experimental.gittensor are now surfaced from the real focus-manifest.ts.

git diff --check clean.

@RealDiligent
RealDiligent requested a review from JSONbored as a code owner July 26, 2026 00:46
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

…s-drift's field walker

extractTypeLiteralFieldEntries parses a type by brace-counting from the first '{' to its match. For an
intersection like 'export type FocusManifestFeaturesConfig = { present: boolean } & Record<ConvergedFeatureKey,
boolean | null>', that stops at the object literal's own '}', so the '& Record<...>' half -- the 8 real
feature keys (rag, reputation, safety, grounding, e2eTests, screenshots, improvementSignal,
amsReputationBridge) and FocusManifestExperimentalConfig's 'gittensor' -- was never inspected. The checker
had zero power to catch a 9th/renamed key landing without a doc update.

Parse the intersection's 'Record<K, V>' half and resolve K's string-literal members to their own field
entries: inline '"a" | "b"' literals, a locally-declared string-literal union, or the
'(typeof SOME_ARRAY)[number]' const-array indirection ConvergedFeatureKey/ExperimentalPluginKey actually use.
Fully general -- any '{...} & Record<...>' in the scanned source, no type name hardcoded. A non-literal key
(Record<string,V>, etc.) resolves to nothing, inventing no field names.

The real FocusManifest field count rises 106->115 (the 8 feature keys + gittensor), and the drift check still
passes against the current .loopover.yml.example (all 9 already documented -- no false positives). Tests:
a fixture exercising every key form (inline / named union / typeof-array / non-literal) plus a live-source
assertion that the 8+1 real keys are now surfaced.
@loopover-orb loopover-orb Bot added the gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. label Jul 26, 2026
@loopover-orb

loopover-orb Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Warning

⏸️ LoopOver review result - manual review recommended

Review updated: 2026-07-26 05:09:06 UTC

2 files · 1 AI reviewer · no blockers · CI green · clean

⏸️ Suggested Action - Manual Review

Review summary
This fix correctly extends extractTypeLiteralFieldEntries to parse the `& Record<K, V>` intersection half of FocusManifest config types, resolving inline string-literal unions, locally-declared string-literal union types, and the `(typeof ARR)[number]` const-array indirection pattern that ConvergedFeatureKey/ExperimentalPluginKey actually use. The scoping via `^[^;]*` on `text.slice(index)` correctly limits the intersection search to just this declaration's own tail (verified against a multi-declaration scenario), and a non-literal key correctly falls through to an empty array rather than inventing field names. Tests are thorough: a fixture exercises every branch (inline literal, const-array indirection, direct union, and three non-literal-key shapes that must yield nothing) plus a live-source assertion against the real focus-manifest.ts confirming the previously-invisible 9 keys are now surfaced.

Nits — 3 non-blocking
  • scripts/check-docs-drift.ts's Record-value regex `[^>]+?` would truncate a value type containing its own generic like `Record<K, Record<string, V>>`, though no such case exists in the current FocusManifest types so this is purely theoretical.
  • The JSDoc comments on `resolveRecordKeyLiterals` and the intersection-parsing block are quite long relative to the code they describe; consider trimming once the pattern is well-established in the codebase.
  • No changes needed beyond what's here; if a future Record value type nests its own generics, tighten the value regex to balance angle brackets rather than stopping at the first `>`.

Decision drivers

  • ✅ Code review — No blockers (1 reviewer)
  • ✅ Gate result — Passing (No configured blocker found.)
Context & advisory signals — never blocks the verdict
Signal Result Evidence
Linked issue ✅ Linked #8656
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 328 registered-repo PR(s), 136 merged, 37 issue(s).
Contributor context ✅ Confirmed Gittensor contributor RealDiligent; Gittensor profile; 328 PR(s), 37 issue(s).
Improvement ✅ Minor risk: clean · value: minor
Linked issue satisfaction

Addressed
The diff extends extractTypeLiteralFieldEntries to detect and resolve `{ ... } & Record<K,V>` intersection halves (inline literals, direct unions, and typeof-array indirection), generalized rather than hardcoded to the two named types, matching the issue's core ask. New tests cover a synthetic fixture proving a new key surfaces as a distinct leaf plus a live-source regression check confirming all

Review context
  • Author: RealDiligent
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: not available
  • Official Gittensor activity: 328 PR(s), 37 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Start here: Triage stale or unlinked PRs.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
🧪 Chat with LoopOver

Ask LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.

  • @loopover ask &lt;question&gt; answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat &lt;question&gt; answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @loopover mention with a real question is routed to the closest matching read-only command automatically — no exact syntax required.

Full command reference: https://loopover.ai/docs/loopover-commands

🧪 Experimental — new and may change.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.

  • Re-run LoopOver review

@loopover-orb loopover-orb Bot added the manual-review Gittensor contributor context label Jul 26, 2026
@codecov

codecov Bot commented Jul 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.80%. Comparing base (cdd760d) to head (d57b31c).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #8720   +/-   ##
=======================================
  Coverage   93.80%   93.80%           
=======================================
  Files         797      797           
  Lines       79493    79493           
  Branches    24085    24085           
=======================================
  Hits        74567    74567           
  Misses       3555     3555           
  Partials     1371     1371           
Flag Coverage Δ
backend 95.08% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

@JSONbored
JSONbored merged commit 01bcfbe into JSONbored:main Jul 26, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. manual-review Gittensor contributor context

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(scripts): check-docs-drift.ts cannot see into Record<K,V>-intersected FocusManifest config types

2 participants