Skip to content

feat(entrypoints): framework-tier call rules and a shipped non-web ruleset (electron, commander, worker_threads, process.on) #167

Description

@rahlk

Problem

Measured on an Electron-plus-CLI fixture with the shipped rules: the manifest tier finds the
main/bin roots (declared), and nothing else — app.on("ready", onReady),
ipcMain.handle("ping", …) and commander's .command("start").action(run) all go unclaimed, and
unclaimed calls leave no trace in the report (unresolved counts only calls a rule matched).
Python ships click and celery so its non-web roots are covered out of the box; the TypeScript
ruleset is web-only.

They cannot ship as heuristics.calls rules: app.on(...) is in every Express app and every
EventEmitter, and false positives are worse than misses (spec, Caveats).

Scope boundary

  • Engine: frameworks.<x>.calls — a call rule gated on detect: and matched on the
    import-table-resolved callee (app.onelectron.app.on; ipc.handle via
    import { ipcMain as ipc }electron.ipcMain.handle), default confidence certain, inside the
    per-framework loop so its claim is framework-claimed for never-doubles. Same split decorators
    already have: framework tier resolved, heuristic tier written.
  • Ruleset: electron (app.on, ipcMain.{on,handle}), commander (program.*.action),
    worker_threads (parentPort.{on,once}), and process.on under heuristics.calls (a Node global —
    distinctive, no dependency to gate on).
  • Not in scope: yargs/oclif (follow-up rules once the mechanism lands); a "calls matched by no
    rule" report counter — that is a visibility decision for the spec, deliberately not slipped in.

Goals

  • Framework.calls: CallRule[]; loader accepts calls: under a framework (NOT forced heuristic)
  • entrypointsFromCalls matches the framework tier on the resolved callee and the heuristic tier
    on the written callee; handler/route/via unchanged
  • Shipped rules above; each gated
  • Never-doubles: a framework call claim blocks a heuristic call record on the same handler

Caveats and known risks

  • A chained receiver (program.command("start").action) resolves through its HEAD token; the rest
    of the written spelling is matched by * segments (commander.program.*.action). Multi-line
    chains carry whitespace in receiver_expr, which * ([^.\s]*) rejects — a miss, not a false hit.
  • route carries the event/channel name for on/handle rules — the nearest field; python's
    route is HTTP-only. Documented in the rule comments.
  • Cross-language vocabulary: frameworks.<x>.calls is a second key python must accept-but-ignore;
    noted on python fix(cli): refuse a missing or non-directory input before analysis (#181) #187.

Definition of done

  • Electron fixture: with electron declared, onReady and the inline IPC handler get certain
    records; the identical source WITHOUT the dependency gets nothing from these rules
  • Alias resolution (ipcMain as ipc) and the chained commander receiver both attach
  • process.on("SIGINT", h) attaches at heuristic with no dependency
  • A handler claimed by a framework call rule carries exactly one record
  • bun test green

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions