fix review findings: don't treat disabled entries as load failures; scope the verify-package-paths lib skip to a real package root

assertEntriesLoaded() flagged ANY fiber-less entry as a failed import, but a
`disabled: true` entry settles without a fiber by design (Entry.refresh() skips
init() when disabled) — a valid "plugin off" config, not a broken import. Both
app bins now filter `fiber === undefined && !entry.disabled`. The stdio built-bin
smoke gains a disabled-(unresolvable)-entry config that must still boot.

The verify-package-paths lib-skip was unconditional and ran before the
moved-package check, so a stale group-less `packages/acp-agent/lib/bin.js` (the
exact drift this gate catches) was silently ignored just for containing `lib`.
Scope the skip: only exempt `lib` when it is the segment after an EXISTING
`packages/<group>/<pkg>` root, so a real-but-unbuilt `lib/bin.js` is still exempt
while a stale package path flags.
This commit is contained in:
Tianyi Cui
2026-06-21 19:47:22 +08:00
parent 9f5e2b352c
commit 4d7726ecd3
4 changed files with 49 additions and 13 deletions

View File

@@ -28,10 +28,13 @@
* Scope mirrors the other doc gates plus repo-authored TypeScript: Markdown
* across README/docs/packages/AGENTS, and `.ts` under packages/** and
* examples/** (excluding built `lib/`, `*.d.ts`, and vendored upstream source).
* A reference whose target path goes through a `lib/` segment is also skipped:
* that is a build OUTPUT (`packages/ui/acp-agent/lib/bin.js`), emitted only by
* `pnpm run build`, which CI runs AFTER this gate — flagging it would be a false
* positive on a path that is correct but not yet on disk.
* A reference to a package's build OUTPUT (`packages/<group>/<pkg>/lib/…`,
* e.g. `packages/ui/acp-agent/lib/bin.js` cited by a built-bin smoke) is also
* skipped — it is emitted only by `pnpm run build`, which CI runs AFTER this
* gate, so flagging it would be a false positive on a path that is correct but
* not yet on disk. That skip is scoped to a REAL package root: a stale
* group-less `packages/acp-agent/lib/bin.js` is still flagged (its root does not
* exist — exactly the moved-package drift this gate catches).
*
* Run: `tsx scripts/verify-package-paths.ts`.
*/
@@ -115,13 +118,17 @@ function findViolations(absPath: string): Violation[] {
// class may have swallowed (`packages/core/tools.` / `…/tools/`).
const ref = m[0].replace(/[./]+$/, '')
if (existsSync(resolve(root, ref))) continue
// A reference INTO a package's built `lib/` is a build-output path, not an
// A reference INTO a package's built `lib/` is a build OUTPUT, not an
// authored-source location: it does not exist until `pnpm run build` emits
// it, and CI runs this gate BEFORE the build step. This gate reports stale
// SOURCE paths (a moved package), so skip `lib/` targets the same way the
// file scan excludes `lib/` files — a `packages/ui/acp-agent/lib/bin.js`
// citation in a built-bin smoke is correct, just not yet on disk at lint.
if (ref.split('/').includes('lib')) continue
// it, and CI runs this gate BEFORE the build step. Skip it — but ONLY when
// the `packages/<group>/<pkg>` ROOT it sits under is real and on disk, so
// `packages/ui/acp-agent/lib/bin.js` (correct, just not yet built) is
// exempt while a stale `packages/acp-agent/lib/bin.js` (group-less, the
// exact moved-package drift this gate exists to catch) still flags. A bare
// `lib` segment is not a blanket escape hatch.
const parts = ref.split('/')
const libAt = parts.indexOf('lib')
if (libAt === 3 && existsSync(resolve(root, parts.slice(0, 3).join('/')))) continue
// Only a stale path to a REAL (moved) package is a violation; a segment
// matching a live package name is the drift signal.
const segments = ref.split('/').slice(1)