LearnNewsExamplesServices
Frontmatter
id17202
titleThe entrypoint guard can silently under-report: unmatchable ai:* entries are excluded, and directory specifiers resolve
stateClosed
labels
enhancementai
assigneesneo-kimi-phoebe
createdAtAug 15, 2026, 8:36 PM
updatedAtAug 15, 2026, 9:52 PM
githubUrlhttps://github.com/neomjs/neo/issues/17202
authorneo-kimi-phoebe
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtAug 15, 2026, 9:52 PM

The entrypoint guard can silently under-report: unmatchable ai:* entries are excluded, and directory specifiers resolve

Closed Backlog/active-chunk-16 enhancementai
neo-kimi-phoebe
neo-kimi-phoebe commented on Aug 15, 2026, 8:36 PM

Seeded by the PR #17199 review (pullrequestreview — @neo-opus-ada's two measured-latent Depth Floor findings, dispositioned there as follow-up rather than held against the repair). Both shapes are the guard's own defect class one level up: a dead-published-entrypoint guard that can itself silently under-report.

Problem

ai/scripts/lint/lint-npm-script-entrypoints.mjs has two silent-failure shapes, both measured at zero occurrences on today's tree (the reviewer's own falsifier runs), so this is hardening, not repair:

  1. extractEntrypoints excludes what it cannot match instead of reporting it. An ai:* command naming ai/scripts/… without the leading ./, and a compound command with a second ai/scripts entrypoint (the match is non-global), both fall out of scope silently. The guard's success line — OK — 63 ai:* entr(ies) — then reads as a coverage claim while the count can shrink without saying so, which is structurally the same rot the guard exists to catch: a surface that fails only in the direction nobody looks.
  2. fs.existsSync returns true for directories, so import './foo' with an existing foo/ directory is treated as resolvable while ESM throws ERR_UNSUPPORTED_DIR_IMPORT at runtime. Measured 0 of 1,216 relative specifiers across ai/scripts + ai/services today.

The Architectural Reality

  • The fix for (1) is reporting, not wider matching: an ai:* entry whose command mentions ai/scripts but fails the entrypoint pattern is itself a finding — the guard should list it as unclassifiable rather than drop it. A count that cannot silently shrink no longer needs to be trusted.
  • The fix for (2) is one isDirectory() rejection in the resolver, with the directory-import case named in the module doc's contract (static file resolvability).
  • Both changes belong in the same module and its existing spec (lintNpmScriptEntrypoints.spec.mjs), which already has the fixture harness both arms need.

Acceptance Criteria

  • An ai:* command that references ai/scripts but matches no entrypoint pattern is reported (not silently excluded), red-proved in the spec with a fixture entry of each unmatchable shape (missing ./, compound command).
  • A relative specifier resolving to a directory is reported as unresolvable, red-proved in the spec with a foo/ directory fixture (ESM's ERR_UNSUPPORTED_DIR_IMPORT named as the runtime behavior the guard must mirror).
  • The guard's success line remains a truthful coverage claim after both changes — either every ai:*-into-ai/scripts entry is classified, or the unclassified ones are in the output.
  • Real-tree run stays clean (63/63) after the changes, evidenced by pasted output.

Out of Scope

  • Dynamic import() resolution (the guard's contract is static resolvability, named in its module doc).
  • #16929's capability-closure walker (transitive execution-plane derivation is its lane; this guard's transitive walk stays one contract: static relative imports of ai:* entrypoints).

Evidence class

Source-read plus the reviewer's measured zeros (#17182 review, 2026-08-15): 0 unmatchable entries, 0 of 1,216 directory-resolving specifiers. The specimens are hypothetical today; the ACs exist so they cannot become real silently.

— Phoebe (@neo-kimi-phoebe, Kimi k3, opencode) 🔆

tobiu referenced in commit 245e97a - "feat(build): the entrypoint guard reports what it cannot classify and rejects directory specifiers (#17202) (#17206)" on Aug 15, 2026, 9:52 PM
tobiu closed this issue on Aug 15, 2026, 9:52 PM