@adlc/model-router

中文文档
1.12.0发布于 2026/10/10MITES Module构建来源已验证近 30 天下载 8325

Deterministic per-ticket model assignment from the ticket DAG and ledger — no LLM calls (D1).

原始使用文档
文档目录16 节
  1. Usage
  2. Flags
  3. Output
  4. Human table (default)
  5. JSON (--json)
  6. Exit codes
  7. Assignment rules (ADLC D1)
  8. Rule 1: Frontier / Direct
  9. Rule 2: Direct (critical path)
  10. Rule 3: Ladder (has slack)
  11. Concepts
  12. Rail density
  13. DAG float (CPM)
  14. Priors from the manifest ledger
  15. ADLC phase
  16. Core gaps

@adlc/model-router

Deterministic per-ticket model assignment (ADLC phase D1). No LLM calls. Reads the ticket DAG and manifest ledger history, then emits tier + mode for every ticket so the dispatcher knows which model to invoke and whether to ladder.

Usage

model-router [--tickets <path>] [--floor <number>] [--json]

Flags

FlagDefaultDescription
--tickets <path>.adlc/tickets.jsonPath to the tickets file
--floor <n>0.2Rail-density floor: a non-frontier-category ticket whose railDensity is below it is forced to frontier and raises a P3 finding (exit 2). It does not move the cheap/mid ladder start, which is a fixed railDensity >= 0.5. n must be greater than 0 and at most 1 — the range is (0, 1]. 0 is rejected with exit 1 because it would disable the P3 rail-density gate (every ticket would pass and unrailed tickets would leave frontier, #697).
--jsonoffMachine-readable JSON output (for orchestrators)

Output

Human table (default)

Columns: id, tier, mode, railDensity, float, reason

id            tier        mode      railDensity  float   reason
---------------------------------------------------------------
AUTH-1        cheap       ladder    1.000        3       float=3 → ladder starting at 'cheap' (railDensity=1.000)
AUTH-2        frontier    direct    0.000        0       category 'spec' requires frontier model

JSON (--json)

{
  "assignments": [
    {
      "id": "AUTH-1",
      "tier": "cheap",
      "mode": "ladder",
      "railDensity": 1.0,
      "float": 3,
      "reason": "..."
    }
  ],
  "p3Findings": [],
  "skippedLedger": []
}

Exit codes

CodeMeaning
0All tickets assigned; gate passes
1Operational error (bad tickets file, JSON parse error, cycle in DAG, or --floor outside (0, 1] — 0 is refused, not treated as "no minimum")
2Gate fails: one or more non-frontier-category tickets have railDensity < floor

Assignment rules (ADLC D1)

Rule 1: Frontier / Direct

Applies when:

  • ticket.category is one of contract, spec, architecture
  • OR railDensity < floor (a non-frontier-category ticket below the floor is also a P3 finding and triggers exit 2; a frontier-category ticket is routed here by its category alone and raises no finding)

Result: tier=frontier, mode=direct

Rationale: These tickets produce outputs that are hard to verify deterministically (contracts, specs) or where an escaped error is expensive to find. Only the frontier model is appropriate. Tickets below the rail-density floor are also sent here because the gates are insufficient to catch regeneration failures cheaply — this is surfaced as a P3 finding (the ticket is not railed enough to build cheaply).

Rule 2: Direct (critical path)

Applies when: float === 0 (ticket is on the critical path)

Result: mode=direct, tier = best-performing tier from prior data with >= 3 samples, else mid

Rationale: A failed attempt on a critical-path ticket delays the entire delivery. Skip the escalation ladder; go straight to the highest first-pass-rate tier.

Rule 3: Ladder (has slack)

Applies when: float > 0

Result: mode=ladder, tier = cheap if railDensity >= 0.5 else mid

Rationale: Retries on tickets with DAG float are absorbed by schedule slack with no wall-clock penalty. Start cheap; the escalation harness regenerates one tier up on gate failure, appending the known-dead-ends to the ticket context.

Concepts

Rail density

railDensity = min(1, rails.length / scope.length)   # 0 when rails or scope is absent/empty

A ticket with rails but no scope (missing or empty) has density 0, not 1: rails without a bounded scope are unbounded, and an unbounded ticket must not be routed to the cheapest tier on the strength of a denominator that was never measured (#698). Give the ticket a scope to route it cheap.

rails is the list of frozen paths that provide deterministic checks (test files, contract files). scope is the set of paths the ticket may touch. High density means most outputs are covered by fast, deterministic gates; errors are caught cheaply and regeneration is inexpensive.

Density of 0 (no rails) means there are no automated gates — any error escapes to humans. Such tickets are routed to frontier; a non-frontier-category one also triggers a P3 gate-fail finding (exit 2), while a contract/spec/architecture ticket is already frontier by category and raises none.

DAG float (CPM)

Classic critical-path-method float from computeFloat() in @adlc/core. Float is the amount of time a ticket can slip without delaying the overall delivery (makespan). Tickets on the critical path have float === 0.

Priors from the manifest ledger

Every build-type entry in .adlc/manifest.jsonl with shape { model, category, firstPass: boolean } is counted. Success rate per model (and per model + category when >= 3 samples exist) is computed with Laplace smoothing:

rate = (passes + 1) / (n + 2)

For critical-path tickets (Rule 2), the model name in the ledger is matched against the tier names cheap, mid, frontier to produce a tier recommendation. If no tier-named model has enough data, defaults to mid.

ADLC phase

D1 — The cost dial: model routing.

model-router is the first decision in the D-series (Dispatch). It runs before fan-out (D2) and merge-forecast. Its output drives the dispatcher's --tier and --mode arguments.

Sibling tools:

  • fan-out (D2) — uses the tier assignments to set parallelism budgets
  • flail-detector — triggers escalation when a running job exceeds the failure threshold, consuming the mode=ladder assignments
  • rails-guard — enforces that rails paths exist before allowing the build to start

Core gaps

@adlc/core provides activeTickets to filter completed tickets (dropping them and stripping edges to them so the remaining DAG stays valid) so finished tickets are not assigned a model or gated. Everything else (loadTickets, computeFloat, readEntries, parseArgs, pass, gateFail, opError, printJson) is available in @adlc/core.

版本与发布记录

@adlc/model-router 共发布 18 个版本,首次发布于 2026/06/14;过去 12 个月发布了 18 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
1.12.0latest2026/10/1027 天前
1.11.12026/09/091 个月前
1.11.02026/08/252 个月前
1.10.02026/08/112 个月前
1.9.02026/08/092 个月前
1.8.02026/08/082 个月前

关于 @adlc/model-router 的常见问题

@adlc/model-router 是什么?

Deterministic per-ticket model assignment from the ticket DAG and ledger — no LLM calls (D1).

如何安装 @adlc/model-router?

在项目目录运行 npm install @adlc/model-router,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 model-router,可以用 npx model-router 直接运行。

@adlc/model-router 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/adlc__model-router 是否存在。

@adlc/model-router 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@adlc/model-router 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@adlc/model-router 可以商用吗?

@adlc/model-router 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@adlc/model-router 的下载量有多少?

根据 npm 官方下载统计,@adlc/model-router 在 2026/10/05 – 2026/11/03 这 30 天内被下载 8,325 次,日均约 278 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@adlc/model-router 还在维护吗?

最新版本 1.12.0 发布于 2026/10/10(27 天前);至今共发布 18 个版本,其中过去 12 个月发布了 18 个;首次发布于 2026/06/14。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。