Skip to content

chore(tsconfig): drop the two dead @objectstack paths entries and empty their ratchet - #5966

Merged
yinlianghui-tw merged 1 commit into
mainfrom
claude/issue-4820-dead-config-alias-targets
Aug 24, 2026
Merged

chore(tsconfig): drop the two dead @objectstack paths entries and empty their ratchet#5966
yinlianghui-tw merged 1 commit into
mainfrom
claude/issue-4820-dead-config-alias-targets

Conversation

@yinlianghui-tw

Copy link
Copy Markdown
Collaborator

Fixes#4820

Dispatched as a folded pair, #4820 (chain head) + #5380. Only #4820 is implemented here.#5380 remains open — its premise-first stop condition fired, and the fork is reported below rather than settled here.

#4820 — the two dead @objectstack/*paths entries

Root tsconfig.json mapped @objectstack/plugin-msw and @objectstack/objectql into node_modules/**/src/index.ts for two packages that are not dependencies of this workspace at all, so no install could ever produce those targets.

Re-verified on this branch, not inherited from the card:

premisereading
both entries still declaredtsconfig.json:34,35
neither package declared anywherezero hits across every package.json
neither package installednode_modules/@objectstack/ holds only spec; zero hits in node_modules/.pnpm/
no compiled source imports eitherzero real import/require statements in .ts/.tsx/.mts/.js/.mjs/.jsx

Positive controls, because an empty result is not a reading: the same package.json grep hits @objectstack/spec in 31 files, and the same import regex finds 12 real imports of @objectstack/spec.

Deleting the lines is behaviour-neutral — a paths key can only affect resolution of its own specifier, and both have zero importers. A dead mapping never fails a build; it just reads as if the packages were wired up.

Direction A per the 2026-08-18 ruling. Option B (making them real dependencies) is a new-runtime-dependency product decision that must not be back-derived from a dead config line; it stays open on its merits.

The ratchet, before and after

KNOWN_MISSING_TARGETS in scripts/__tests__/vitest-config-alias-targets-3944.test.tsbefore:

constKNOWN_MISSING_TARGETS: readonlystring[]=['@objectstack/plugin-msw','@objectstack/objectql',];

after:

constKNOWN_MISSING_TARGETS: readonlystring[]=[];

Those two entries were its whole content, so the shrink-only ratchet reaches empty and every paths entry is now guarded with no exemptions.

Its pin was renamed and given one added assertion — expect(KNOWN_MISSING_TARGETS).toEqual([]). With an empty list its two existing expectations are vacuous, and a silently vacuous pin is the exact trap this file guards everywhere else ("a zero-hit parse would make every case below vacuous"). The emptiness is now asserted rather than implied.

KNOWN_MISSING_PACKAGE_ALIAS_TARGETS is unchanged — see below.

Reverse verification

Re-added one deleted line on top of the commit, confirmed the mutation on disk (occurrences 0 → 1, at tsconfig.json:34), and ran the gate. Predicted direction: red, because the carve-out is now empty and the generic existence check has to catch it.

GATE_EXIT=1
FAIL objectui#4804 … > '@objectstack/plugin-msw' maps to a path that exists
AssertionError: paths['@objectstack/plugin-msw'] maps to
node_modules/@objectstack/plugin-msw/src/index.ts, which does not exist in the workspace.
Test Files 1 failed (1)
Tests 1 failed | 289 passed (290)

Restored through an EXIT INT TERM trap; the working tree is clean at the tip.

#5380 — NOT implemented; reporting a fork

packages/runner/vite.config.ts:25 is untouched and its KNOWN_MISSING_PACKAGE_ALIAS_TARGETS entry is left in place. The card's premise-first stop condition — "if you find any doc, script or workflow showing the 'App Data Symlink' DX is still wanted, stop and report a fork" — is met, and the measurement is stronger than a simple "still wanted".

The target is not a dead pointer. It is a documented, deliberately git-ignored, user-supplied directory. Several places in the repo describe it, two of them using the word symlink:

  • packages/runner/.gitignore:1src/app-data
  • packages/runner/README.md:85 — "That directory is git-ignored and absent from a fresh checkout, so every load returns null until you copy or symlink your own metadata directory into it." Its Development Workflow step 1 instructs the reader to createpackages/runner/src/app-data/.
  • content/docs/utilities/runner.mdx:156 — "src/app-data/ is git-ignored … you supply it, by copying or symlinking your own metadata directory there."
  • packages/runner/src/lib/MetadataLoader.ts:19-28LocalBundleLoader reads it, and its class doc says the same.

That falsifies the stated grounds of both directions:

What is true is narrower than either: the alias has zero importers, because the loader consumes the directory through relative import.meta.glob('../app-data/…'), never through @app. Deleting it would not break the documented DX — but "unused alias" is a different justification from the one that was ruled, and it leaves a real design question the ruling never saw: should @app remain as the ergonomic entry point for the documented DX, or go because the loader deliberately uses relative globs?

A separate, mechanical consequence worth a maintainer's attention:#5168's pin is checkout-state dependent for this entry. It asserts the carved-out entry is still declared and still missing, via fs.existsSync. Any developer who follows the README's Development Workflow step 1 and creates src/app-data/ makes the target exist, and the pin then fails on their machine with "A carved-out target now exists, so the carve-out is obsolete for it". It is green in CI only because CI never creates the directory. That holds regardless of which direction #5380 takes.

Per the dispatch, direction B is maintainer-floor and is not implemented, and A is not quietly applied with caveats.

Gates

Re-derived from the actual diff (this repo has no dispatch-gates.mjs), all run at 0d31aa8a5:

gateresult
vitest-config-alias-targets-3944.test.ts (both describe blocks)Test Files 1 passed (1) · Tests 289 passed (289)
turbo run type-check (full — root tsconfig.json is extended by every package)Tasks: 81 successful, 81 total
pnpm type-check:scriptsexit 0
pnpm lint:rootexit 0
scripts/__tests__ suite (62 files)Tests 1664 passed (1664)
check-phantom-dependencies.mjs
check-type-check-coverage.mjs
check-control-bytes.mjs✅ 4950 files scanned

pnpm lint (all packages) was narrowed to lint:root, and the narrowing is measured rather than assumed: eslint reports the root tsconfig.json as "File ignored because no matching configuration was supplied", so it is outside eslint's population entirely; the one linted changed file reports errors=0 warnings=0 via --format json; and type-aware linting is not enabled in eslint.config.js (no project / projectService), so this diff cannot move any untouched file's verdict.

Changeset: none owed, and no label.node scripts/check-changeset-presence.mjs exits 0 — "2 file(s) changed, 0 of them under the src/ of a package the release covers … No source of a released package changed in this range, so no changeset is owed." AGENTS.md §161 owes a changeset only when a released package's src/ changes; neither the root tsconfig.json nor a scripts/__tests__/ file is one. objectui has no skip-changeset label mechanism (it appears only in content/docs/guide/ci-cd-pipeline.md describing what does not exist), so none was applied.


Generated by Claude Code

…ty their ratchet
`compilerOptions.paths` mapped `@objectstack/plugin-msw` and
`@objectstack/objectql` into `node_modules/**/src/index.ts` for two packages
that are not dependencies of this workspace at all, so no install could ever
produce those targets. Measured on this branch: zero declarations across every
package.json, `node_modules/@objectstack/` holds only `spec`, nothing in
`node_modules/.pnpm/` matches either name, and no compiled source carries a real
import of either specifier (the same regex finds 12 real imports of
`@objectstack/spec`, so the empty result is a reading rather than a broken grep).
A dead mapping never fails a build — nothing resolves through it — it just reads
as if the packages were wired up. Deleting the lines is behaviour-neutral: a
`paths` key can only affect resolution of its own specifier, and both have zero
importers.
The two entries were the whole content of `KNOWN_MISSING_TARGETS`, the
shrink-only ratchet #4804 carved out pending this decision, so that list is
emptied in the same change and its pin now asserts the emptiness instead of
passing vacuously. Every `paths` entry is guarded with no exemptions.
The two specifiers keep appearing in prose (`skills/` guides, the ObjectOS
integration page) as downstream-user examples; those need no `paths` map in this
repo and are deliberately untouched.
@yinlianghui-tw
yinlianghui-tw marked this pull request as ready for review August 24, 2026 09:42
@yinlianghui-tw
yinlianghui-tw added this pull request to the merge queueAug 24, 2026
Merged via the queue into main with commit cb83cecAug 24, 2026
21 checks passed
@yinlianghui-tw
yinlianghui-tw deleted the claude/issue-4820-dead-config-alias-targets branch August 24, 2026 09:43
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants

@yinlianghui-tw@os-trump