Skip to content

feat(entrypoints): file-convention and manifest matchers; level invariance with every tier firing - #163

Merged
rahlk merged 4 commits into
mainfrom
feat/issue-161-entrypoint-files
Sep 6, 2026
Merged

feat(entrypoints): file-convention and manifest matchers; level invariance with every tier firing#163
rahlk merged 4 commits into
mainfrom
feat/issue-161-entrypoint-files

Conversation

@rahlk

@rahlk rahlk commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Closes #161. Unit 5 of the entrypoint spec (#150); plan docs/design/plans/2026-09-03-entrypoints-units-2-5.md, Tasks 7–9. Stacked on #160 (unit 4) — this PR targets that branch, not main. The last unit: with it, #72 is complete.

Two declaration forms python never faced, and the proof that the whole pass is level-free.

What this adds

  • File-convention matcherfiles: rules match a glob over the module file key (**/, *, {a,b}, anchored). Each named export resolves to the exported callable; default is detected from the declaration's source text, because TSModule.exports records only export { } and re-exports. Shipped: Next.js app router (app/**/route.tsGET/POST/…, route from the path), Next.js pages API (default), SvelteKit +server.ts. Gated: without next in the manifest, the same files register nothing.
  • Manifest matcherpackage.json main and bin (string or name→path object) resolve to a module (with dist/src/ and extension fallbacks); the free functions that module calls at top level get confidence: declared records with via = the module id. A path that resolves to nothing, or a module with no such call, is counted, never fabricated. This decides the spec's open question about module-level entrypoints without adding a field to the shared vocabulary.
  • Level invariance, proven on a fixture where every tier fires — nestjs decorators, the calls: heuristic tier and manifest.main — L1 cold, then L2–L4 warm against the cache, byte-identical. The unit-1 contract test only proved the empty case; this closes that gap.
  • README --help block regenerated for --entrypoint-rules.

Verification

  • bun test — 286 pass, 0 fail; container tests run (final unit)
  • Each task reviewed at task scope, all approved without a fix round
  • Whole-branch review on the most capable model, also the final review of the whole plan (it read pipeline.ts and matching.ts in full for cross-unit seams): stage order and never-doubles across all six tiers verified; level/cache invariance verified as genuinely cache-warm; gate holds. Two Important findings — both silent misses — fixed in one wave and re-reviewed: --no-artifact-text stores source: "" and ?? did not fall through, so the manifest tier vanished without a count; and pages/api defaults spelled export default handler; or export default async (req, res) => {} went unfound and uncounted. Both now resolve or are counted. Three one-line minors landed with them: malformed package.json is counted, file-rule globs are validated at load, a consistency nit. Re-review: all five addressed, no new breakage.

Decisions worth your eye

  • routeFromFileKey is a convention pinned by tests, not a contract: app/users/route.ts/users, app/route.ts/, pages/api/hello.ts/api/hello, src/routes/x/+server.ts/src/routes/x.
  • Manifest records are not subject to never-doubles — a function can legitimately be both an Express handler and a main-called root, so the manifest stage runs last and pushes unconditionally.
  • noRepoSections lives on the unmerged feat(cli): --program shard selector, --no-repo-sections, and shard IR #149, not this branch; the manifest matcher's disk fallback is tested by a direct unit call with an empty artifact map.

Deferred (triaged by the final review — nothing blocks)

Follow-up issue #162 collects the coverage gaps and raw-text seams: calls never-doubles against a live files: claim; transitive: false / empty dispatch tests; a stronger file-gate test; the callless-module manifest branch; the literalOf/routeOf/isSignature trio; resolveHandler binding a bare identifier to a same-named class method; the pages/api/index.ts route convention. Marked never: the neo4j-schema.test.ts options literal, resolveByType keyed per type, splitting matching.ts.

@rahlk
rahlk force-pushed the feat/issue-161-entrypoint-files branch from 6e125f6 to 9a060ad Compare September 6, 2026 12:58
@rahlk
rahlk merged commit cbfcb67 into main Sep 6, 2026
@rahlk
rahlk deleted the feat/issue-161-entrypoint-files branch September 6, 2026 12:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(entrypoints): file-convention and manifest matchers, level invariance, closeout (unit 5)

1 participant