fix(tooling): put three more package-root plugin manifests inside a tsc program - #14458

Merged
baozhoutao merged 2 commits into
mainfrom
claude/issue-14386-coverage-gate-package-root-source
Sep 2, 2026
Merged

fix(tooling): put three more package-root plugin manifests inside a tsc program#14458
baozhoutao merged 2 commits into
mainfrom
claude/issue-14386-coverage-gate-package-root-source

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#14386

What

check:type-check-coverage's isUncheckedSourceCandidate skipped depth === 0
(the package root) unconditionally, so any package-root .ts file was invisible
to SOURCES_COVERED regardless of content — not reported, not tracked. This is
exactly why #13284's driver-memory / plugin-hono-server manifests went
unchecked for as long as they did: pnpm --filter <pkg> typecheck exited 0
over a file no tsc program read, while check:type-check-coverage called the
package COVERED at the same time.

Per the triage (comment 5504408509 on #14386), this queues the narrow repair
only — admitting a declared set of root filenames that are authored source,
not every package-root .ts file:

  1. ROOT_SOURCE_FILES (currently {'objectstack.config.ts'}) — the depth-0
    exception to isUncheckedSourceCandidate, with a docblock stating the
    104-file question (every un-programmed vitest.config.ts / tsup.config.ts
    at a package root) is deliberately not answered here.
  2. The uncheckedByDir aggregation now keys a root-level unread file at '.'
    — which posix.join(dir, top) collapses to the package's own directory —
    instead of the rel.slice(0, -1) garbage key the old indexOf('/') === -1
    arithmetic produced.
  3. A --self-test case for a root-level source file (predicate rows for
    objectstack.config.ts / tsup.config.ts / a hypothetical root .d.ts,
    plus an evaluate()-level fixture pinning that the . root key renders as
    the package's own directory) — the existing source-layer cases were all
    subdirectory cases (packages/a/scripts), which is exactly why this hole
    survived.
  4. The three sites the widened predicate then surfaces are put into a program:

All three type-check clean at zero errors — no UNCHECKED_SOURCE_DEBT entry
is added.

Not this card

Per the triage, the 104-file question (whether every un-programmed
vitest.config.ts / tsup.config.ts at a package root owes a program or a
ledger entry) is explicitly not decided here. ROOT_SOURCE_FILES is a
closed, exact-name allowlist rather than a pattern, precisely so growing it
stays a decision made on its own card.

#13284 is not addressed here beyond what already landed — its fence (driver-memory,
plugin-hono-server) holds; this touches neither.

Verified: no other package-root objectstack.config.ts outside the three named

find packages apps examples -name objectstack.config.ts (filtered to
directories that are themselves a package.json root) turns up 8 hits: the 3
examples/app-* (already inside their own tsc programs, pre-existing),
driver-memory + plugin-hono-server (#13284, already covered), the 3 named
here, andpackages/create-objectstack/src/templates/blank/. That last one
is a scaffold template with its own nested pnpm-workspace.yaml — not a member
of this repo's own workspace (workspacePackageDirs() does not walk into it),
so the widened predicate correctly does not surface it. Left untouched, per the
triage's instruction not to add programs or ledger entries beyond the three
named sites — noted here for the record, not acted on.

Before / after

Baseline (origin/mainbd8795ea1, before any edit):

check-type-check-coverage: OK — 68/78 workspace packages type-checked (plus the root), 10 in the DEBT ledger (305 frozen raw errors, https://github.com/objectstack-ai/objectstack/issues/4311), 1 exempt.
test layer: 13 package(s) still hide their own tests from tsc (554 files hidden as counted by this run, 466 frozen raw errors in TEST_DEBT).
source layer: 1 directory(ies) of non-test source in 1 ledgered entr(y/ies) sit outside every tsc program their package's own `typecheck` runs (1 files as counted by this run).
...

Predicate-only (before the three tsconfig edits — proves the widened predicate
now sees the sites):

check-type-check-coverage: 3 problem(s)
• packages/plugins/plugin-auth: 1 non-test source file(s) here sit outside every tsc program that `@objectstack/plugin-auth`'s `typecheck` script runs, ...
• packages/plugins/plugin-security: 1 non-test source file(s) here sit outside every tsc program that `@objectstack/plugin-security`'s `typecheck` script runs, ...
• packages/services/service-i18n: 1 non-test source file(s) here sit outside every tsc program that `@objectstack/service-i18n`'s `typecheck` script runs, ...

Final, after the three tsconfig edits:

check-type-check-coverage: OK — 68/78 workspace packages type-checked (plus the root), 10 in the DEBT ledger (305 frozen raw errors, #4311), 1 exempt.
source layer: 1 directory(ies) of non-test source in 1 ledgered entr(y/ies) sit outside every tsc program their package's own `typecheck` runs (1 files as counted by this run).

Same shape as baseline — the pre-existing 1-entry source-layer ledger is
unchanged, and the three new sites are NOT in it (they are fully covered, zero
debt).

Each package's own typecheck, run against a freshly built dependency closure
(pnpm --filter "<pkg>..." build), also passes clean:

@objectstack/plugin-auth typecheck → tsc --noEmit && tsc --noEmit -p tsconfig.examples.json && check:test-typecheck — all pass (test layer: pre-existing 94 errors / 10 files, ledgered in test-typecheck-debt.json, unchanged by this PR)
@objectstack/plugin-security typecheck → tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json && check:test-typecheck — all pass, 0 errors
@objectstack/service-i18n typecheck → tsc --noEmit && tsc --noEmit -p tsconfig.typecheck.json — all pass

A second gate the new program onboarding tripped: check:type-source-resolution

Putting service-i18n's manifest into tsconfig.typecheck.json onboards that
package's first tsc program to reach the bare @objectstack/spec specifier —
src/ only ever imports subpaths (@objectstack/spec/contracts,
@objectstack/spec/system), never the bare package. check:type-source-resolution
correctly flagged this (a dep resolving through dist/ with no paths rule
pointing at source). Repaired via that gate's own documented onboarding-limb
registry re-baseline
— the sanctioned tool for exactly this shape (a dep
reached only through a newly-onboarded program; paths is measured wrong for
this shape on PR #12570, since it would pull packages/spec/src — and
everything it imports — into a program whose rootDir is .). One entry added
to KNOWN_DIST_RESOLVED_TYPE_IMPORTS:

'@objectstack/service-i18n': ['@objectstack/spec'],

--list before/after (measured at bd8795ea1, the entry excluded from "after"
to isolate what onboarding the program added):

before 55 of 77 packages, 111 programs, 269 pairs, 22 clean
after 56 of 77 packages, 112 programs, 270 pairs, 21 clean

+1 program, +1 pair, +1 package — this entry and nothing else. Full reasoning
in the file's own comment beside the entry. This edit is outside the file
surface named in the dispatch, filed as a bounded in-place-fix exemption per
os-dev.md rule 3 (surface amendment posted on #14386 before this PR opened).

Tests

  • node scripts/check-type-check-coverage.mjs --self-test — 48 semantic +
    68 observation (+1 / +3 over baseline) + 43 re-measure + 28 built-closure +
    19 auto-lowering + 18 exit-code cases hold.
  • node scripts/check-type-check-coverage.mjs — before/predicate-only/final shown above.
  • node scripts/check-type-source-resolution.mjs --self-test — OK.
  • node scripts/check-type-source-resolution.mjs — OK, 56 registered (was 55 pre-onboarding, +1 this PR's entry), 0 unregistered exposure.
  • pnpm --filter "@objectstack/plugin-auth..." --filter "@objectstack/plugin-security..." --filter "@objectstack/service-i18n..." build then each package's own pnpm --filter <pkg> typecheck — all pass, shown above (os-verify-lock VERDICT command-exit 0, held 368s).
  • 31 of 34 additional gates dispatch-gates.mjs derives for this diff run green directly; the remaining 3 are legitimate NOT MEASURED (check-test-completeness needs a CI test log; check:type-check-debt --re-measure needs the full unfiltered workspace build closure, explicitly "not a pass and not a finding" per the gate's own refusal; check-half-states.mjs timed out against the network proxy under container contention — retried, not yet resolved by report time).
  • check:i18n / check:i18n-stale-fill (convention-triggered by the plugin-security/tsconfig.scripts.json edit) — both green, all 9 packages' bundles in sync.
  • pnpm check:pm-dispatch-gates (~11.5 min gate) — run in background under the shared verify lock; see report comment for its result.
  • Derived gate family via node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands — 48 commands (44 by path + 4 by change kind); see report comment for the full list and results.

Generated by Claude Code


Generated by Claude Code

…sc program
check:type-check-coverage's isUncheckedSourceCandidate skipped depth === 0
(the package root) unconditionally, so a package-root .ts file was invisible
to SOURCES_COVERED regardless of content. This is why #13284's driver-memory
/ plugin-hono-server manifests went unchecked for as long as they did.
Per the triage on #14386 (comment 5504408509), this admits depth === 0 only
for a declared, exact-name allowlist (ROOT_SOURCE_FILES, currently just
objectstack.config.ts) rather than every package-root file -- the wider
104-file question stays explicitly unresolved. The uncheckedByDir
aggregation now keys a root-level file at '.' (which posix.join collapses
to the package's own directory) instead of the rel.slice(0, -1) garbage key
the old indexOf('/') === -1 arithmetic produced.
The three sites the widened predicate then surfaces (plugin-auth,
plugin-security, service-i18n) are put into a program: widened include on
the existing sibling noEmit programs for the first two, a new sibling
tsconfig.typecheck.json (following the driver-memory shape from #13284) for
service-i18n, which had none to widen.
Putting service-i18n's manifest into a program onboards that package's
first tsc program to reach the bare @objectstack/spec specifier (src/ only
ever imports subpaths), which check:type-source-resolution correctly
flagged. Repaired via that gate's own documented onboarding-limb registry
re-baseline (the sanctioned tool for a dep reached only through a
newly-onboarded program -- paths is measured wrong for this shape on
PR #12570), with --list before/after numbers stated in place.
Fixes#14386
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

⚠️3 changed file(s) yielded no anchor (packages/plugins/plugin-auth/tsconfig.examples.json, packages/plugins/plugin-security/tsconfig.scripts.json, packages/services/service-i18n/tsconfig.typecheck.json), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files. Nothing else in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 3 changed package(s)).

What this run could not see
  • 3 changed file(s) yielded no anchor (packages/plugins/plugin-auth/tsconfig.examples.json, packages/plugins/plugin-security/tsconfig.scripts.json, packages/services/service-i18n/tsconfig.typecheck.json) — pages documenting those are invisible to this run
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 21 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 1d8ad0ffe51caae6892ccece9f8abad9794ac545packageMentionDocs.

@github-actionsgithub-actionsBot added dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation tooling labels Sep 2, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependenciesPull requests that update a dependency filedocumentationImprovements or additions to documentationsize/mtooling

Projects

None yet

2 participants

@baozhoutao@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

fix(tooling): put three more package-root plugin manifests inside a tsc program - #14458

Merged
baozhoutao merged 2 commits into
mainfrom
claude/issue-14386-coverage-gate-package-root-source
Sep 2, 2026
Merged

fix(tooling): put three more package-root plugin manifests inside a tsc program#14458
baozhoutao merged 2 commits into
mainfrom
claude/issue-14386-coverage-gate-package-root-source

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#14386

What

check:type-check-coverage's isUncheckedSourceCandidate skipped depth === 0
(the package root) unconditionally, so any package-root .ts file was invisible
to SOURCES_COVERED regardless of content — not reported, not tracked. This is
exactly why #13284's driver-memory / plugin-hono-server manifests went
unchecked for as long as they did: pnpm --filter <pkg> typecheck exited 0
over a file no tsc program read, while check:type-check-coverage called the
package COVERED at the same time.

Per the triage (comment 5504408509 on #14386), this queues the narrow repair
only — admitting a declared set of root filenames that are authored source,
not every package-root .ts file:

  1. ROOT_SOURCE_FILES (currently {'objectstack.config.ts'}) — the depth-0
    exception to isUncheckedSourceCandidate, with a docblock stating the
    104-file question (every un-programmed vitest.config.ts / tsup.config.ts
    at a package root) is deliberately not answered here.
  2. The uncheckedByDir aggregation now keys a root-level unread file at '.'
    — which posix.join(dir, top) collapses to the package's own directory —
    instead of the rel.slice(0, -1) garbage key the old indexOf('/') === -1
    arithmetic produced.
  3. A --self-test case for a root-level source file (predicate rows for
    objectstack.config.ts / tsup.config.ts / a hypothetical root .d.ts,
    plus an evaluate()-level fixture pinning that the . root key renders as
    the package's own directory) — the existing source-layer cases were all
    subdirectory cases (packages/a/scripts), which is exactly why this hole
    survived.
  4. The three sites the widened predicate then surfaces are put into a program:

All three type-check clean at zero errors — no UNCHECKED_SOURCE_DEBT entry
is added.

Not this card

Per the triage, the 104-file question (whether every un-programmed
vitest.config.ts / tsup.config.ts at a package root owes a program or a
ledger entry) is explicitly not decided here. ROOT_SOURCE_FILES is a
closed, exact-name allowlist rather than a pattern, precisely so growing it
stays a decision made on its own card.

#13284 is not addressed here beyond what already landed — its fence (driver-memory,
plugin-hono-server) holds; this touches neither.

Verified: no other package-root objectstack.config.ts outside the three named

find packages apps examples -name objectstack.config.ts (filtered to
directories that are themselves a package.json root) turns up 8 hits: the 3
examples/app-* (already inside their own tsc programs, pre-existing),
driver-memory + plugin-hono-server (#13284, already covered), the 3 named
here, andpackages/create-objectstack/src/templates/blank/. That last one
is a scaffold template with its own nested pnpm-workspace.yaml — not a member
of this repo's own workspace (workspacePackageDirs() does not walk into it),
so the widened predicate correctly does not surface it. Left untouched, per the
triage's instruction not to add programs or ledger entries beyond the three
named sites — noted here for the record, not acted on.

Before / after

Baseline (origin/mainbd8795ea1, before any edit):

check-type-check-coverage: OK — 68/78 workspace packages type-checked (plus the root), 10 in the DEBT ledger (305 frozen raw errors, https://github.com/objectstack-ai/objectstack/issues/4311), 1 exempt.
test layer: 13 package(s) still hide their own tests from tsc (554 files hidden as counted by this run, 466 frozen raw errors in TEST_DEBT).
source layer: 1 directory(ies) of non-test source in 1 ledgered entr(y/ies) sit outside every tsc program their package's own `typecheck` runs (1 files as counted by this run).
...

Predicate-only (before the three tsconfig edits — proves the widened predicate
now sees the sites):

check-type-check-coverage: 3 problem(s)
• packages/plugins/plugin-auth: 1 non-test source file(s) here sit outside every tsc program that `@objectstack/plugin-auth`'s `typecheck` script runs, ...
• packages/plugins/plugin-security: 1 non-test source file(s) here sit outside every tsc program that `@objectstack/plugin-security`'s `typecheck` script runs, ...
• packages/services/service-i18n: 1 non-test source file(s) here sit outside every tsc program that `@objectstack/service-i18n`'s `typecheck` script runs, ...

Final, after the three tsconfig edits:

check-type-check-coverage: OK — 68/78 workspace packages type-checked (plus the root), 10 in the DEBT ledger (305 frozen raw errors, #4311), 1 exempt.
source layer: 1 directory(ies) of non-test source in 1 ledgered entr(y/ies) sit outside every tsc program their package's own `typecheck` runs (1 files as counted by this run).

Same shape as baseline — the pre-existing 1-entry source-layer ledger is
unchanged, and the three new sites are NOT in it (they are fully covered, zero
debt).

Each package's own typecheck, run against a freshly built dependency closure
(pnpm --filter "<pkg>..." build), also passes clean:

@objectstack/plugin-auth typecheck → tsc --noEmit && tsc --noEmit -p tsconfig.examples.json && check:test-typecheck — all pass (test layer: pre-existing 94 errors / 10 files, ledgered in test-typecheck-debt.json, unchanged by this PR)
@objectstack/plugin-security typecheck → tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json && check:test-typecheck — all pass, 0 errors
@objectstack/service-i18n typecheck → tsc --noEmit && tsc --noEmit -p tsconfig.typecheck.json — all pass

A second gate the new program onboarding tripped: check:type-source-resolution

Putting service-i18n's manifest into tsconfig.typecheck.json onboards that
package's first tsc program to reach the bare @objectstack/spec specifier —
src/ only ever imports subpaths (@objectstack/spec/contracts,
@objectstack/spec/system), never the bare package. check:type-source-resolution
correctly flagged this (a dep resolving through dist/ with no paths rule
pointing at source). Repaired via that gate's own documented onboarding-limb
registry re-baseline
— the sanctioned tool for exactly this shape (a dep
reached only through a newly-onboarded program; paths is measured wrong for
this shape on PR #12570, since it would pull packages/spec/src — and
everything it imports — into a program whose rootDir is .). One entry added
to KNOWN_DIST_RESOLVED_TYPE_IMPORTS:

'@objectstack/service-i18n': ['@objectstack/spec'],

--list before/after (measured at bd8795ea1, the entry excluded from "after"
to isolate what onboarding the program added):

before 55 of 77 packages, 111 programs, 269 pairs, 22 clean
after 56 of 77 packages, 112 programs, 270 pairs, 21 clean

+1 program, +1 pair, +1 package — this entry and nothing else. Full reasoning
in the file's own comment beside the entry. This edit is outside the file
surface named in the dispatch, filed as a bounded in-place-fix exemption per
os-dev.md rule 3 (surface amendment posted on #14386 before this PR opened).

Tests

  • node scripts/check-type-check-coverage.mjs --self-test — 48 semantic +
    68 observation (+1 / +3 over baseline) + 43 re-measure + 28 built-closure +
    19 auto-lowering + 18 exit-code cases hold.
  • node scripts/check-type-check-coverage.mjs — before/predicate-only/final shown above.
  • node scripts/check-type-source-resolution.mjs --self-test — OK.
  • node scripts/check-type-source-resolution.mjs — OK, 56 registered (was 55 pre-onboarding, +1 this PR's entry), 0 unregistered exposure.
  • pnpm --filter "@objectstack/plugin-auth..." --filter "@objectstack/plugin-security..." --filter "@objectstack/service-i18n..." build then each package's own pnpm --filter <pkg> typecheck — all pass, shown above (os-verify-lock VERDICT command-exit 0, held 368s).
  • 31 of 34 additional gates dispatch-gates.mjs derives for this diff run green directly; the remaining 3 are legitimate NOT MEASURED (check-test-completeness needs a CI test log; check:type-check-debt --re-measure needs the full unfiltered workspace build closure, explicitly "not a pass and not a finding" per the gate's own refusal; check-half-states.mjs timed out against the network proxy under container contention — retried, not yet resolved by report time).
  • check:i18n / check:i18n-stale-fill (convention-triggered by the plugin-security/tsconfig.scripts.json edit) — both green, all 9 packages' bundles in sync.
  • pnpm check:pm-dispatch-gates (~11.5 min gate) — run in background under the shared verify lock; see report comment for its result.
  • Derived gate family via node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands — 48 commands (44 by path + 4 by change kind); see report comment for the full list and results.

Generated by Claude Code


Generated by Claude Code

…sc program
check:type-check-coverage's isUncheckedSourceCandidate skipped depth === 0
(the package root) unconditionally, so a package-root .ts file was invisible
to SOURCES_COVERED regardless of content. This is why #13284's driver-memory
/ plugin-hono-server manifests went unchecked for as long as they did.
Per the triage on #14386 (comment 5504408509), this admits depth === 0 only
for a declared, exact-name allowlist (ROOT_SOURCE_FILES, currently just
objectstack.config.ts) rather than every package-root file -- the wider
104-file question stays explicitly unresolved. The uncheckedByDir
aggregation now keys a root-level file at '.' (which posix.join collapses
to the package's own directory) instead of the rel.slice(0, -1) garbage key
the old indexOf('/') === -1 arithmetic produced.
The three sites the widened predicate then surfaces (plugin-auth,
plugin-security, service-i18n) are put into a program: widened include on
the existing sibling noEmit programs for the first two, a new sibling
tsconfig.typecheck.json (following the driver-memory shape from #13284) for
service-i18n, which had none to widen.
Putting service-i18n's manifest into a program onboards that package's
first tsc program to reach the bare @objectstack/spec specifier (src/ only
ever imports subpaths), which check:type-source-resolution correctly
flagged. Repaired via that gate's own documented onboarding-limb registry
re-baseline (the sanctioned tool for a dep reached only through a
newly-onboarded program -- paths is measured wrong for this shape on
PR #12570), with --list before/after numbers stated in place.
Fixes#14386
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

⚠️3 changed file(s) yielded no anchor (packages/plugins/plugin-auth/tsconfig.examples.json, packages/plugins/plugin-security/tsconfig.scripts.json, packages/services/service-i18n/tsconfig.typecheck.json), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files. Nothing else in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 3 changed package(s)).

What this run could not see
  • 3 changed file(s) yielded no anchor (packages/plugins/plugin-auth/tsconfig.examples.json, packages/plugins/plugin-security/tsconfig.scripts.json, packages/services/service-i18n/tsconfig.typecheck.json) — pages documenting those are invisible to this run
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 21 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 1d8ad0ffe51caae6892ccece9f8abad9794ac545packageMentionDocs.

@github-actionsgithub-actionsBot added dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation tooling labels Sep 2, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependenciesPull requests that update a dependency filedocumentationImprovements or additions to documentationsize/mtooling

Projects

None yet

2 participants

@baozhoutao@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(tooling): put three more package-root plugin manifests inside a tsc program - #14458

Merged
baozhoutao merged 2 commits into
mainfrom
claude/issue-14386-coverage-gate-package-root-source
Sep 2, 2026
Merged

fix(tooling): put three more package-root plugin manifests inside a tsc program#14458
baozhoutao merged 2 commits into
mainfrom
claude/issue-14386-coverage-gate-package-root-source

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#14386

What

check:type-check-coverage's isUncheckedSourceCandidate skipped depth === 0
(the package root) unconditionally, so any package-root .ts file was invisible
to SOURCES_COVERED regardless of content — not reported, not tracked. This is
exactly why #13284's driver-memory / plugin-hono-server manifests went
unchecked for as long as they did: pnpm --filter <pkg> typecheck exited 0
over a file no tsc program read, while check:type-check-coverage called the
package COVERED at the same time.

Per the triage (comment 5504408509 on #14386), this queues the narrow repair
only — admitting a declared set of root filenames that are authored source,
not every package-root .ts file:

  1. ROOT_SOURCE_FILES (currently {'objectstack.config.ts'}) — the depth-0
    exception to isUncheckedSourceCandidate, with a docblock stating the
    104-file question (every un-programmed vitest.config.ts / tsup.config.ts
    at a package root) is deliberately not answered here.
  2. The uncheckedByDir aggregation now keys a root-level unread file at '.'
    — which posix.join(dir, top) collapses to the package's own directory —
    instead of the rel.slice(0, -1) garbage key the old indexOf('/') === -1
    arithmetic produced.
  3. A --self-test case for a root-level source file (predicate rows for
    objectstack.config.ts / tsup.config.ts / a hypothetical root .d.ts,
    plus an evaluate()-level fixture pinning that the . root key renders as
    the package's own directory) — the existing source-layer cases were all
    subdirectory cases (packages/a/scripts), which is exactly why this hole
    survived.
  4. The three sites the widened predicate then surfaces are put into a program:

All three type-check clean at zero errors — no UNCHECKED_SOURCE_DEBT entry
is added.

Not this card

Per the triage, the 104-file question (whether every un-programmed
vitest.config.ts / tsup.config.ts at a package root owes a program or a
ledger entry) is explicitly not decided here. ROOT_SOURCE_FILES is a
closed, exact-name allowlist rather than a pattern, precisely so growing it
stays a decision made on its own card.

#13284 is not addressed here beyond what already landed — its fence (driver-memory,
plugin-hono-server) holds; this touches neither.

Verified: no other package-root objectstack.config.ts outside the three named

find packages apps examples -name objectstack.config.ts (filtered to
directories that are themselves a package.json root) turns up 8 hits: the 3
examples/app-* (already inside their own tsc programs, pre-existing),
driver-memory + plugin-hono-server (#13284, already covered), the 3 named
here, andpackages/create-objectstack/src/templates/blank/. That last one
is a scaffold template with its own nested pnpm-workspace.yaml — not a member
of this repo's own workspace (workspacePackageDirs() does not walk into it),
so the widened predicate correctly does not surface it. Left untouched, per the
triage's instruction not to add programs or ledger entries beyond the three
named sites — noted here for the record, not acted on.

Before / after

Baseline (origin/mainbd8795ea1, before any edit):

check-type-check-coverage: OK — 68/78 workspace packages type-checked (plus the root), 10 in the DEBT ledger (305 frozen raw errors, https://github.com/objectstack-ai/objectstack/issues/4311), 1 exempt.
test layer: 13 package(s) still hide their own tests from tsc (554 files hidden as counted by this run, 466 frozen raw errors in TEST_DEBT).
source layer: 1 directory(ies) of non-test source in 1 ledgered entr(y/ies) sit outside every tsc program their package's own `typecheck` runs (1 files as counted by this run).
...

Predicate-only (before the three tsconfig edits — proves the widened predicate
now sees the sites):

check-type-check-coverage: 3 problem(s)
• packages/plugins/plugin-auth: 1 non-test source file(s) here sit outside every tsc program that `@objectstack/plugin-auth`'s `typecheck` script runs, ...
• packages/plugins/plugin-security: 1 non-test source file(s) here sit outside every tsc program that `@objectstack/plugin-security`'s `typecheck` script runs, ...
• packages/services/service-i18n: 1 non-test source file(s) here sit outside every tsc program that `@objectstack/service-i18n`'s `typecheck` script runs, ...

Final, after the three tsconfig edits:

check-type-check-coverage: OK — 68/78 workspace packages type-checked (plus the root), 10 in the DEBT ledger (305 frozen raw errors, #4311), 1 exempt.
source layer: 1 directory(ies) of non-test source in 1 ledgered entr(y/ies) sit outside every tsc program their package's own `typecheck` runs (1 files as counted by this run).

Same shape as baseline — the pre-existing 1-entry source-layer ledger is
unchanged, and the three new sites are NOT in it (they are fully covered, zero
debt).

Each package's own typecheck, run against a freshly built dependency closure
(pnpm --filter "<pkg>..." build), also passes clean:

@objectstack/plugin-auth typecheck → tsc --noEmit && tsc --noEmit -p tsconfig.examples.json && check:test-typecheck — all pass (test layer: pre-existing 94 errors / 10 files, ledgered in test-typecheck-debt.json, unchanged by this PR)
@objectstack/plugin-security typecheck → tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json && check:test-typecheck — all pass, 0 errors
@objectstack/service-i18n typecheck → tsc --noEmit && tsc --noEmit -p tsconfig.typecheck.json — all pass

A second gate the new program onboarding tripped: check:type-source-resolution

Putting service-i18n's manifest into tsconfig.typecheck.json onboards that
package's first tsc program to reach the bare @objectstack/spec specifier —
src/ only ever imports subpaths (@objectstack/spec/contracts,
@objectstack/spec/system), never the bare package. check:type-source-resolution
correctly flagged this (a dep resolving through dist/ with no paths rule
pointing at source). Repaired via that gate's own documented onboarding-limb
registry re-baseline
— the sanctioned tool for exactly this shape (a dep
reached only through a newly-onboarded program; paths is measured wrong for
this shape on PR #12570, since it would pull packages/spec/src — and
everything it imports — into a program whose rootDir is .). One entry added
to KNOWN_DIST_RESOLVED_TYPE_IMPORTS:

'@objectstack/service-i18n': ['@objectstack/spec'],

--list before/after (measured at bd8795ea1, the entry excluded from "after"
to isolate what onboarding the program added):

before 55 of 77 packages, 111 programs, 269 pairs, 22 clean
after 56 of 77 packages, 112 programs, 270 pairs, 21 clean

+1 program, +1 pair, +1 package — this entry and nothing else. Full reasoning
in the file's own comment beside the entry. This edit is outside the file
surface named in the dispatch, filed as a bounded in-place-fix exemption per
os-dev.md rule 3 (surface amendment posted on #14386 before this PR opened).

Tests

  • node scripts/check-type-check-coverage.mjs --self-test — 48 semantic +
    68 observation (+1 / +3 over baseline) + 43 re-measure + 28 built-closure +
    19 auto-lowering + 18 exit-code cases hold.
  • node scripts/check-type-check-coverage.mjs — before/predicate-only/final shown above.
  • node scripts/check-type-source-resolution.mjs --self-test — OK.
  • node scripts/check-type-source-resolution.mjs — OK, 56 registered (was 55 pre-onboarding, +1 this PR's entry), 0 unregistered exposure.
  • pnpm --filter "@objectstack/plugin-auth..." --filter "@objectstack/plugin-security..." --filter "@objectstack/service-i18n..." build then each package's own pnpm --filter <pkg> typecheck — all pass, shown above (os-verify-lock VERDICT command-exit 0, held 368s).
  • 31 of 34 additional gates dispatch-gates.mjs derives for this diff run green directly; the remaining 3 are legitimate NOT MEASURED (check-test-completeness needs a CI test log; check:type-check-debt --re-measure needs the full unfiltered workspace build closure, explicitly "not a pass and not a finding" per the gate's own refusal; check-half-states.mjs timed out against the network proxy under container contention — retried, not yet resolved by report time).
  • check:i18n / check:i18n-stale-fill (convention-triggered by the plugin-security/tsconfig.scripts.json edit) — both green, all 9 packages' bundles in sync.
  • pnpm check:pm-dispatch-gates (~11.5 min gate) — run in background under the shared verify lock; see report comment for its result.
  • Derived gate family via node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands — 48 commands (44 by path + 4 by change kind); see report comment for the full list and results.

Generated by Claude Code


Generated by Claude Code

…sc program
check:type-check-coverage's isUncheckedSourceCandidate skipped depth === 0
(the package root) unconditionally, so a package-root .ts file was invisible
to SOURCES_COVERED regardless of content. This is why #13284's driver-memory
/ plugin-hono-server manifests went unchecked for as long as they did.
Per the triage on #14386 (comment 5504408509), this admits depth === 0 only
for a declared, exact-name allowlist (ROOT_SOURCE_FILES, currently just
objectstack.config.ts) rather than every package-root file -- the wider
104-file question stays explicitly unresolved. The uncheckedByDir
aggregation now keys a root-level file at '.' (which posix.join collapses
to the package's own directory) instead of the rel.slice(0, -1) garbage key
the old indexOf('/') === -1 arithmetic produced.
The three sites the widened predicate then surfaces (plugin-auth,
plugin-security, service-i18n) are put into a program: widened include on
the existing sibling noEmit programs for the first two, a new sibling
tsconfig.typecheck.json (following the driver-memory shape from #13284) for
service-i18n, which had none to widen.
Putting service-i18n's manifest into a program onboards that package's
first tsc program to reach the bare @objectstack/spec specifier (src/ only
ever imports subpaths), which check:type-source-resolution correctly
flagged. Repaired via that gate's own documented onboarding-limb registry
re-baseline (the sanctioned tool for a dep reached only through a
newly-onboarded program -- paths is measured wrong for this shape on
PR #12570), with --list before/after numbers stated in place.
Fixes#14386
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

⚠️3 changed file(s) yielded no anchor (packages/plugins/plugin-auth/tsconfig.examples.json, packages/plugins/plugin-security/tsconfig.scripts.json, packages/services/service-i18n/tsconfig.typecheck.json), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files. Nothing else in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 3 changed package(s)).

What this run could not see
  • 3 changed file(s) yielded no anchor (packages/plugins/plugin-auth/tsconfig.examples.json, packages/plugins/plugin-security/tsconfig.scripts.json, packages/services/service-i18n/tsconfig.typecheck.json) — pages documenting those are invisible to this run
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 21 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 1d8ad0ffe51caae6892ccece9f8abad9794ac545packageMentionDocs.

@github-actionsgithub-actionsBot added dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation tooling labels Sep 2, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependenciesPull requests that update a dependency filedocumentationImprovements or additions to documentationsize/mtooling

Projects

None yet

2 participants

@baozhoutao@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(tooling): put three more package-root plugin manifests inside a tsc program - #14458

Merged
baozhoutao merged 2 commits into
mainfrom
claude/issue-14386-coverage-gate-package-root-source
Sep 2, 2026
Merged

fix(tooling): put three more package-root plugin manifests inside a tsc program#14458
baozhoutao merged 2 commits into
mainfrom
claude/issue-14386-coverage-gate-package-root-source

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#14386

What

check:type-check-coverage's isUncheckedSourceCandidate skipped depth === 0
(the package root) unconditionally, so any package-root .ts file was invisible
to SOURCES_COVERED regardless of content — not reported, not tracked. This is
exactly why #13284's driver-memory / plugin-hono-server manifests went
unchecked for as long as they did: pnpm --filter <pkg> typecheck exited 0
over a file no tsc program read, while check:type-check-coverage called the
package COVERED at the same time.

Per the triage (comment 5504408509 on #14386), this queues the narrow repair
only — admitting a declared set of root filenames that are authored source,
not every package-root .ts file:

  1. ROOT_SOURCE_FILES (currently {'objectstack.config.ts'}) — the depth-0
    exception to isUncheckedSourceCandidate, with a docblock stating the
    104-file question (every un-programmed vitest.config.ts / tsup.config.ts
    at a package root) is deliberately not answered here.
  2. The uncheckedByDir aggregation now keys a root-level unread file at '.'
    — which posix.join(dir, top) collapses to the package's own directory —
    instead of the rel.slice(0, -1) garbage key the old indexOf('/') === -1
    arithmetic produced.
  3. A --self-test case for a root-level source file (predicate rows for
    objectstack.config.ts / tsup.config.ts / a hypothetical root .d.ts,
    plus an evaluate()-level fixture pinning that the . root key renders as
    the package's own directory) — the existing source-layer cases were all
    subdirectory cases (packages/a/scripts), which is exactly why this hole
    survived.
  4. The three sites the widened predicate then surfaces are put into a program:

All three type-check clean at zero errors — no UNCHECKED_SOURCE_DEBT entry
is added.

Not this card

Per the triage, the 104-file question (whether every un-programmed
vitest.config.ts / tsup.config.ts at a package root owes a program or a
ledger entry) is explicitly not decided here. ROOT_SOURCE_FILES is a
closed, exact-name allowlist rather than a pattern, precisely so growing it
stays a decision made on its own card.

#13284 is not addressed here beyond what already landed — its fence (driver-memory,
plugin-hono-server) holds; this touches neither.

Verified: no other package-root objectstack.config.ts outside the three named

find packages apps examples -name objectstack.config.ts (filtered to
directories that are themselves a package.json root) turns up 8 hits: the 3
examples/app-* (already inside their own tsc programs, pre-existing),
driver-memory + plugin-hono-server (#13284, already covered), the 3 named
here, andpackages/create-objectstack/src/templates/blank/. That last one
is a scaffold template with its own nested pnpm-workspace.yaml — not a member
of this repo's own workspace (workspacePackageDirs() does not walk into it),
so the widened predicate correctly does not surface it. Left untouched, per the
triage's instruction not to add programs or ledger entries beyond the three
named sites — noted here for the record, not acted on.

Before / after

Baseline (origin/mainbd8795ea1, before any edit):

check-type-check-coverage: OK — 68/78 workspace packages type-checked (plus the root), 10 in the DEBT ledger (305 frozen raw errors, https://github.com/objectstack-ai/objectstack/issues/4311), 1 exempt.
test layer: 13 package(s) still hide their own tests from tsc (554 files hidden as counted by this run, 466 frozen raw errors in TEST_DEBT).
source layer: 1 directory(ies) of non-test source in 1 ledgered entr(y/ies) sit outside every tsc program their package's own `typecheck` runs (1 files as counted by this run).
...

Predicate-only (before the three tsconfig edits — proves the widened predicate
now sees the sites):

check-type-check-coverage: 3 problem(s)
• packages/plugins/plugin-auth: 1 non-test source file(s) here sit outside every tsc program that `@objectstack/plugin-auth`'s `typecheck` script runs, ...
• packages/plugins/plugin-security: 1 non-test source file(s) here sit outside every tsc program that `@objectstack/plugin-security`'s `typecheck` script runs, ...
• packages/services/service-i18n: 1 non-test source file(s) here sit outside every tsc program that `@objectstack/service-i18n`'s `typecheck` script runs, ...

Final, after the three tsconfig edits:

check-type-check-coverage: OK — 68/78 workspace packages type-checked (plus the root), 10 in the DEBT ledger (305 frozen raw errors, #4311), 1 exempt.
source layer: 1 directory(ies) of non-test source in 1 ledgered entr(y/ies) sit outside every tsc program their package's own `typecheck` runs (1 files as counted by this run).

Same shape as baseline — the pre-existing 1-entry source-layer ledger is
unchanged, and the three new sites are NOT in it (they are fully covered, zero
debt).

Each package's own typecheck, run against a freshly built dependency closure
(pnpm --filter "<pkg>..." build), also passes clean:

@objectstack/plugin-auth typecheck → tsc --noEmit && tsc --noEmit -p tsconfig.examples.json && check:test-typecheck — all pass (test layer: pre-existing 94 errors / 10 files, ledgered in test-typecheck-debt.json, unchanged by this PR)
@objectstack/plugin-security typecheck → tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json && check:test-typecheck — all pass, 0 errors
@objectstack/service-i18n typecheck → tsc --noEmit && tsc --noEmit -p tsconfig.typecheck.json — all pass

A second gate the new program onboarding tripped: check:type-source-resolution

Putting service-i18n's manifest into tsconfig.typecheck.json onboards that
package's first tsc program to reach the bare @objectstack/spec specifier —
src/ only ever imports subpaths (@objectstack/spec/contracts,
@objectstack/spec/system), never the bare package. check:type-source-resolution
correctly flagged this (a dep resolving through dist/ with no paths rule
pointing at source). Repaired via that gate's own documented onboarding-limb
registry re-baseline
— the sanctioned tool for exactly this shape (a dep
reached only through a newly-onboarded program; paths is measured wrong for
this shape on PR #12570, since it would pull packages/spec/src — and
everything it imports — into a program whose rootDir is .). One entry added
to KNOWN_DIST_RESOLVED_TYPE_IMPORTS:

'@objectstack/service-i18n': ['@objectstack/spec'],

--list before/after (measured at bd8795ea1, the entry excluded from "after"
to isolate what onboarding the program added):

before 55 of 77 packages, 111 programs, 269 pairs, 22 clean
after 56 of 77 packages, 112 programs, 270 pairs, 21 clean

+1 program, +1 pair, +1 package — this entry and nothing else. Full reasoning
in the file's own comment beside the entry. This edit is outside the file
surface named in the dispatch, filed as a bounded in-place-fix exemption per
os-dev.md rule 3 (surface amendment posted on #14386 before this PR opened).

Tests

  • node scripts/check-type-check-coverage.mjs --self-test — 48 semantic +
    68 observation (+1 / +3 over baseline) + 43 re-measure + 28 built-closure +
    19 auto-lowering + 18 exit-code cases hold.
  • node scripts/check-type-check-coverage.mjs — before/predicate-only/final shown above.
  • node scripts/check-type-source-resolution.mjs --self-test — OK.
  • node scripts/check-type-source-resolution.mjs — OK, 56 registered (was 55 pre-onboarding, +1 this PR's entry), 0 unregistered exposure.
  • pnpm --filter "@objectstack/plugin-auth..." --filter "@objectstack/plugin-security..." --filter "@objectstack/service-i18n..." build then each package's own pnpm --filter <pkg> typecheck — all pass, shown above (os-verify-lock VERDICT command-exit 0, held 368s).
  • 31 of 34 additional gates dispatch-gates.mjs derives for this diff run green directly; the remaining 3 are legitimate NOT MEASURED (check-test-completeness needs a CI test log; check:type-check-debt --re-measure needs the full unfiltered workspace build closure, explicitly "not a pass and not a finding" per the gate's own refusal; check-half-states.mjs timed out against the network proxy under container contention — retried, not yet resolved by report time).
  • check:i18n / check:i18n-stale-fill (convention-triggered by the plugin-security/tsconfig.scripts.json edit) — both green, all 9 packages' bundles in sync.
  • pnpm check:pm-dispatch-gates (~11.5 min gate) — run in background under the shared verify lock; see report comment for its result.
  • Derived gate family via node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands — 48 commands (44 by path + 4 by change kind); see report comment for the full list and results.

Generated by Claude Code


Generated by Claude Code

…sc program
check:type-check-coverage's isUncheckedSourceCandidate skipped depth === 0
(the package root) unconditionally, so a package-root .ts file was invisible
to SOURCES_COVERED regardless of content. This is why #13284's driver-memory
/ plugin-hono-server manifests went unchecked for as long as they did.
Per the triage on #14386 (comment 5504408509), this admits depth === 0 only
for a declared, exact-name allowlist (ROOT_SOURCE_FILES, currently just
objectstack.config.ts) rather than every package-root file -- the wider
104-file question stays explicitly unresolved. The uncheckedByDir
aggregation now keys a root-level file at '.' (which posix.join collapses
to the package's own directory) instead of the rel.slice(0, -1) garbage key
the old indexOf('/') === -1 arithmetic produced.
The three sites the widened predicate then surfaces (plugin-auth,
plugin-security, service-i18n) are put into a program: widened include on
the existing sibling noEmit programs for the first two, a new sibling
tsconfig.typecheck.json (following the driver-memory shape from #13284) for
service-i18n, which had none to widen.
Putting service-i18n's manifest into a program onboards that package's
first tsc program to reach the bare @objectstack/spec specifier (src/ only
ever imports subpaths), which check:type-source-resolution correctly
flagged. Repaired via that gate's own documented onboarding-limb registry
re-baseline (the sanctioned tool for a dep reached only through a
newly-onboarded program -- paths is measured wrong for this shape on
PR #12570), with --list before/after numbers stated in place.
Fixes#14386
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

⚠️3 changed file(s) yielded no anchor (packages/plugins/plugin-auth/tsconfig.examples.json, packages/plugins/plugin-security/tsconfig.scripts.json, packages/services/service-i18n/tsconfig.typecheck.json), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files. Nothing else in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 3 changed package(s)).

What this run could not see
  • 3 changed file(s) yielded no anchor (packages/plugins/plugin-auth/tsconfig.examples.json, packages/plugins/plugin-security/tsconfig.scripts.json, packages/services/service-i18n/tsconfig.typecheck.json) — pages documenting those are invisible to this run
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 21 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 1d8ad0ffe51caae6892ccece9f8abad9794ac545packageMentionDocs.

@github-actionsgithub-actionsBot added dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation tooling labels Sep 2, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependenciesPull requests that update a dependency filedocumentationImprovements or additions to documentationsize/mtooling

Projects

None yet

2 participants

@baozhoutao@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

fix(tooling): put three more package-root plugin manifests inside a tsc program - #14458

Merged
baozhoutao merged 2 commits into
mainfrom
claude/issue-14386-coverage-gate-package-root-source
Sep 2, 2026
Merged

fix(tooling): put three more package-root plugin manifests inside a tsc program#14458
baozhoutao merged 2 commits into
mainfrom
claude/issue-14386-coverage-gate-package-root-source

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#14386

What

check:type-check-coverage's isUncheckedSourceCandidate skipped depth === 0
(the package root) unconditionally, so any package-root .ts file was invisible
to SOURCES_COVERED regardless of content — not reported, not tracked. This is
exactly why #13284's driver-memory / plugin-hono-server manifests went
unchecked for as long as they did: pnpm --filter <pkg> typecheck exited 0
over a file no tsc program read, while check:type-check-coverage called the
package COVERED at the same time.

Per the triage (comment 5504408509 on #14386), this queues the narrow repair
only — admitting a declared set of root filenames that are authored source,
not every package-root .ts file:

  1. ROOT_SOURCE_FILES (currently {'objectstack.config.ts'}) — the depth-0
    exception to isUncheckedSourceCandidate, with a docblock stating the
    104-file question (every un-programmed vitest.config.ts / tsup.config.ts
    at a package root) is deliberately not answered here.
  2. The uncheckedByDir aggregation now keys a root-level unread file at '.'
    — which posix.join(dir, top) collapses to the package's own directory —
    instead of the rel.slice(0, -1) garbage key the old indexOf('/') === -1
    arithmetic produced.
  3. A --self-test case for a root-level source file (predicate rows for
    objectstack.config.ts / tsup.config.ts / a hypothetical root .d.ts,
    plus an evaluate()-level fixture pinning that the . root key renders as
    the package's own directory) — the existing source-layer cases were all
    subdirectory cases (packages/a/scripts), which is exactly why this hole
    survived.
  4. The three sites the widened predicate then surfaces are put into a program:

All three type-check clean at zero errors — no UNCHECKED_SOURCE_DEBT entry
is added.

Not this card

Per the triage, the 104-file question (whether every un-programmed
vitest.config.ts / tsup.config.ts at a package root owes a program or a
ledger entry) is explicitly not decided here. ROOT_SOURCE_FILES is a
closed, exact-name allowlist rather than a pattern, precisely so growing it
stays a decision made on its own card.

#13284 is not addressed here beyond what already landed — its fence (driver-memory,
plugin-hono-server) holds; this touches neither.

Verified: no other package-root objectstack.config.ts outside the three named

find packages apps examples -name objectstack.config.ts (filtered to
directories that are themselves a package.json root) turns up 8 hits: the 3
examples/app-* (already inside their own tsc programs, pre-existing),
driver-memory + plugin-hono-server (#13284, already covered), the 3 named
here, andpackages/create-objectstack/src/templates/blank/. That last one
is a scaffold template with its own nested pnpm-workspace.yaml — not a member
of this repo's own workspace (workspacePackageDirs() does not walk into it),
so the widened predicate correctly does not surface it. Left untouched, per the
triage's instruction not to add programs or ledger entries beyond the three
named sites — noted here for the record, not acted on.

Before / after

Baseline (origin/mainbd8795ea1, before any edit):

check-type-check-coverage: OK — 68/78 workspace packages type-checked (plus the root), 10 in the DEBT ledger (305 frozen raw errors, https://github.com/objectstack-ai/objectstack/issues/4311), 1 exempt.
test layer: 13 package(s) still hide their own tests from tsc (554 files hidden as counted by this run, 466 frozen raw errors in TEST_DEBT).
source layer: 1 directory(ies) of non-test source in 1 ledgered entr(y/ies) sit outside every tsc program their package's own `typecheck` runs (1 files as counted by this run).
...

Predicate-only (before the three tsconfig edits — proves the widened predicate
now sees the sites):

check-type-check-coverage: 3 problem(s)
• packages/plugins/plugin-auth: 1 non-test source file(s) here sit outside every tsc program that `@objectstack/plugin-auth`'s `typecheck` script runs, ...
• packages/plugins/plugin-security: 1 non-test source file(s) here sit outside every tsc program that `@objectstack/plugin-security`'s `typecheck` script runs, ...
• packages/services/service-i18n: 1 non-test source file(s) here sit outside every tsc program that `@objectstack/service-i18n`'s `typecheck` script runs, ...

Final, after the three tsconfig edits:

check-type-check-coverage: OK — 68/78 workspace packages type-checked (plus the root), 10 in the DEBT ledger (305 frozen raw errors, #4311), 1 exempt.
source layer: 1 directory(ies) of non-test source in 1 ledgered entr(y/ies) sit outside every tsc program their package's own `typecheck` runs (1 files as counted by this run).

Same shape as baseline — the pre-existing 1-entry source-layer ledger is
unchanged, and the three new sites are NOT in it (they are fully covered, zero
debt).

Each package's own typecheck, run against a freshly built dependency closure
(pnpm --filter "<pkg>..." build), also passes clean:

@objectstack/plugin-auth typecheck → tsc --noEmit && tsc --noEmit -p tsconfig.examples.json && check:test-typecheck — all pass (test layer: pre-existing 94 errors / 10 files, ledgered in test-typecheck-debt.json, unchanged by this PR)
@objectstack/plugin-security typecheck → tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json && check:test-typecheck — all pass, 0 errors
@objectstack/service-i18n typecheck → tsc --noEmit && tsc --noEmit -p tsconfig.typecheck.json — all pass

A second gate the new program onboarding tripped: check:type-source-resolution

Putting service-i18n's manifest into tsconfig.typecheck.json onboards that
package's first tsc program to reach the bare @objectstack/spec specifier —
src/ only ever imports subpaths (@objectstack/spec/contracts,
@objectstack/spec/system), never the bare package. check:type-source-resolution
correctly flagged this (a dep resolving through dist/ with no paths rule
pointing at source). Repaired via that gate's own documented onboarding-limb
registry re-baseline
— the sanctioned tool for exactly this shape (a dep
reached only through a newly-onboarded program; paths is measured wrong for
this shape on PR #12570, since it would pull packages/spec/src — and
everything it imports — into a program whose rootDir is .). One entry added
to KNOWN_DIST_RESOLVED_TYPE_IMPORTS:

'@objectstack/service-i18n': ['@objectstack/spec'],

--list before/after (measured at bd8795ea1, the entry excluded from "after"
to isolate what onboarding the program added):

before 55 of 77 packages, 111 programs, 269 pairs, 22 clean
after 56 of 77 packages, 112 programs, 270 pairs, 21 clean

+1 program, +1 pair, +1 package — this entry and nothing else. Full reasoning
in the file's own comment beside the entry. This edit is outside the file
surface named in the dispatch, filed as a bounded in-place-fix exemption per
os-dev.md rule 3 (surface amendment posted on #14386 before this PR opened).

Tests

  • node scripts/check-type-check-coverage.mjs --self-test — 48 semantic +
    68 observation (+1 / +3 over baseline) + 43 re-measure + 28 built-closure +
    19 auto-lowering + 18 exit-code cases hold.
  • node scripts/check-type-check-coverage.mjs — before/predicate-only/final shown above.
  • node scripts/check-type-source-resolution.mjs --self-test — OK.
  • node scripts/check-type-source-resolution.mjs — OK, 56 registered (was 55 pre-onboarding, +1 this PR's entry), 0 unregistered exposure.
  • pnpm --filter "@objectstack/plugin-auth..." --filter "@objectstack/plugin-security..." --filter "@objectstack/service-i18n..." build then each package's own pnpm --filter <pkg> typecheck — all pass, shown above (os-verify-lock VERDICT command-exit 0, held 368s).
  • 31 of 34 additional gates dispatch-gates.mjs derives for this diff run green directly; the remaining 3 are legitimate NOT MEASURED (check-test-completeness needs a CI test log; check:type-check-debt --re-measure needs the full unfiltered workspace build closure, explicitly "not a pass and not a finding" per the gate's own refusal; check-half-states.mjs timed out against the network proxy under container contention — retried, not yet resolved by report time).
  • check:i18n / check:i18n-stale-fill (convention-triggered by the plugin-security/tsconfig.scripts.json edit) — both green, all 9 packages' bundles in sync.
  • pnpm check:pm-dispatch-gates (~11.5 min gate) — run in background under the shared verify lock; see report comment for its result.
  • Derived gate family via node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands — 48 commands (44 by path + 4 by change kind); see report comment for the full list and results.

Generated by Claude Code


Generated by Claude Code

…sc program
check:type-check-coverage's isUncheckedSourceCandidate skipped depth === 0
(the package root) unconditionally, so a package-root .ts file was invisible
to SOURCES_COVERED regardless of content. This is why #13284's driver-memory
/ plugin-hono-server manifests went unchecked for as long as they did.
Per the triage on #14386 (comment 5504408509), this admits depth === 0 only
for a declared, exact-name allowlist (ROOT_SOURCE_FILES, currently just
objectstack.config.ts) rather than every package-root file -- the wider
104-file question stays explicitly unresolved. The uncheckedByDir
aggregation now keys a root-level file at '.' (which posix.join collapses
to the package's own directory) instead of the rel.slice(0, -1) garbage key
the old indexOf('/') === -1 arithmetic produced.
The three sites the widened predicate then surfaces (plugin-auth,
plugin-security, service-i18n) are put into a program: widened include on
the existing sibling noEmit programs for the first two, a new sibling
tsconfig.typecheck.json (following the driver-memory shape from #13284) for
service-i18n, which had none to widen.
Putting service-i18n's manifest into a program onboards that package's
first tsc program to reach the bare @objectstack/spec specifier (src/ only
ever imports subpaths), which check:type-source-resolution correctly
flagged. Repaired via that gate's own documented onboarding-limb registry
re-baseline (the sanctioned tool for a dep reached only through a
newly-onboarded program -- paths is measured wrong for this shape on
PR #12570), with --list before/after numbers stated in place.
Fixes#14386
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

⚠️3 changed file(s) yielded no anchor (packages/plugins/plugin-auth/tsconfig.examples.json, packages/plugins/plugin-security/tsconfig.scripts.json, packages/services/service-i18n/tsconfig.typecheck.json), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files. Nothing else in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 3 changed package(s)).

What this run could not see
  • 3 changed file(s) yielded no anchor (packages/plugins/plugin-auth/tsconfig.examples.json, packages/plugins/plugin-security/tsconfig.scripts.json, packages/services/service-i18n/tsconfig.typecheck.json) — pages documenting those are invisible to this run
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 21 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 1d8ad0ffe51caae6892ccece9f8abad9794ac545packageMentionDocs.

@github-actionsgithub-actionsBot added dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation tooling labels Sep 2, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependenciesPull requests that update a dependency filedocumentationImprovements or additions to documentationsize/mtooling

Projects

None yet

2 participants

@baozhoutao@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(tooling): put three more package-root plugin manifests inside a tsc program - #14458

Merged
baozhoutao merged 2 commits into
mainfrom
claude/issue-14386-coverage-gate-package-root-source
Sep 2, 2026
Merged

fix(tooling): put three more package-root plugin manifests inside a tsc program#14458
baozhoutao merged 2 commits into
mainfrom
claude/issue-14386-coverage-gate-package-root-source

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#14386

What

check:type-check-coverage's isUncheckedSourceCandidate skipped depth === 0
(the package root) unconditionally, so any package-root .ts file was invisible
to SOURCES_COVERED regardless of content — not reported, not tracked. This is
exactly why #13284's driver-memory / plugin-hono-server manifests went
unchecked for as long as they did: pnpm --filter <pkg> typecheck exited 0
over a file no tsc program read, while check:type-check-coverage called the
package COVERED at the same time.

Per the triage (comment 5504408509 on #14386), this queues the narrow repair
only — admitting a declared set of root filenames that are authored source,
not every package-root .ts file:

  1. ROOT_SOURCE_FILES (currently {'objectstack.config.ts'}) — the depth-0
    exception to isUncheckedSourceCandidate, with a docblock stating the
    104-file question (every un-programmed vitest.config.ts / tsup.config.ts
    at a package root) is deliberately not answered here.
  2. The uncheckedByDir aggregation now keys a root-level unread file at '.'
    — which posix.join(dir, top) collapses to the package's own directory —
    instead of the rel.slice(0, -1) garbage key the old indexOf('/') === -1
    arithmetic produced.
  3. A --self-test case for a root-level source file (predicate rows for
    objectstack.config.ts / tsup.config.ts / a hypothetical root .d.ts,
    plus an evaluate()-level fixture pinning that the . root key renders as
    the package's own directory) — the existing source-layer cases were all
    subdirectory cases (packages/a/scripts), which is exactly why this hole
    survived.
  4. The three sites the widened predicate then surfaces are put into a program:

All three type-check clean at zero errors — no UNCHECKED_SOURCE_DEBT entry
is added.

Not this card

Per the triage, the 104-file question (whether every un-programmed
vitest.config.ts / tsup.config.ts at a package root owes a program or a
ledger entry) is explicitly not decided here. ROOT_SOURCE_FILES is a
closed, exact-name allowlist rather than a pattern, precisely so growing it
stays a decision made on its own card.

#13284 is not addressed here beyond what already landed — its fence (driver-memory,
plugin-hono-server) holds; this touches neither.

Verified: no other package-root objectstack.config.ts outside the three named

find packages apps examples -name objectstack.config.ts (filtered to
directories that are themselves a package.json root) turns up 8 hits: the 3
examples/app-* (already inside their own tsc programs, pre-existing),
driver-memory + plugin-hono-server (#13284, already covered), the 3 named
here, andpackages/create-objectstack/src/templates/blank/. That last one
is a scaffold template with its own nested pnpm-workspace.yaml — not a member
of this repo's own workspace (workspacePackageDirs() does not walk into it),
so the widened predicate correctly does not surface it. Left untouched, per the
triage's instruction not to add programs or ledger entries beyond the three
named sites — noted here for the record, not acted on.

Before / after

Baseline (origin/mainbd8795ea1, before any edit):

check-type-check-coverage: OK — 68/78 workspace packages type-checked (plus the root), 10 in the DEBT ledger (305 frozen raw errors, https://github.com/objectstack-ai/objectstack/issues/4311), 1 exempt.
test layer: 13 package(s) still hide their own tests from tsc (554 files hidden as counted by this run, 466 frozen raw errors in TEST_DEBT).
source layer: 1 directory(ies) of non-test source in 1 ledgered entr(y/ies) sit outside every tsc program their package's own `typecheck` runs (1 files as counted by this run).
...

Predicate-only (before the three tsconfig edits — proves the widened predicate
now sees the sites):

check-type-check-coverage: 3 problem(s)
• packages/plugins/plugin-auth: 1 non-test source file(s) here sit outside every tsc program that `@objectstack/plugin-auth`'s `typecheck` script runs, ...
• packages/plugins/plugin-security: 1 non-test source file(s) here sit outside every tsc program that `@objectstack/plugin-security`'s `typecheck` script runs, ...
• packages/services/service-i18n: 1 non-test source file(s) here sit outside every tsc program that `@objectstack/service-i18n`'s `typecheck` script runs, ...

Final, after the three tsconfig edits:

check-type-check-coverage: OK — 68/78 workspace packages type-checked (plus the root), 10 in the DEBT ledger (305 frozen raw errors, #4311), 1 exempt.
source layer: 1 directory(ies) of non-test source in 1 ledgered entr(y/ies) sit outside every tsc program their package's own `typecheck` runs (1 files as counted by this run).

Same shape as baseline — the pre-existing 1-entry source-layer ledger is
unchanged, and the three new sites are NOT in it (they are fully covered, zero
debt).

Each package's own typecheck, run against a freshly built dependency closure
(pnpm --filter "<pkg>..." build), also passes clean:

@objectstack/plugin-auth typecheck → tsc --noEmit && tsc --noEmit -p tsconfig.examples.json && check:test-typecheck — all pass (test layer: pre-existing 94 errors / 10 files, ledgered in test-typecheck-debt.json, unchanged by this PR)
@objectstack/plugin-security typecheck → tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json && check:test-typecheck — all pass, 0 errors
@objectstack/service-i18n typecheck → tsc --noEmit && tsc --noEmit -p tsconfig.typecheck.json — all pass

A second gate the new program onboarding tripped: check:type-source-resolution

Putting service-i18n's manifest into tsconfig.typecheck.json onboards that
package's first tsc program to reach the bare @objectstack/spec specifier —
src/ only ever imports subpaths (@objectstack/spec/contracts,
@objectstack/spec/system), never the bare package. check:type-source-resolution
correctly flagged this (a dep resolving through dist/ with no paths rule
pointing at source). Repaired via that gate's own documented onboarding-limb
registry re-baseline
— the sanctioned tool for exactly this shape (a dep
reached only through a newly-onboarded program; paths is measured wrong for
this shape on PR #12570, since it would pull packages/spec/src — and
everything it imports — into a program whose rootDir is .). One entry added
to KNOWN_DIST_RESOLVED_TYPE_IMPORTS:

'@objectstack/service-i18n': ['@objectstack/spec'],

--list before/after (measured at bd8795ea1, the entry excluded from "after"
to isolate what onboarding the program added):

before 55 of 77 packages, 111 programs, 269 pairs, 22 clean
after 56 of 77 packages, 112 programs, 270 pairs, 21 clean

+1 program, +1 pair, +1 package — this entry and nothing else. Full reasoning
in the file's own comment beside the entry. This edit is outside the file
surface named in the dispatch, filed as a bounded in-place-fix exemption per
os-dev.md rule 3 (surface amendment posted on #14386 before this PR opened).

Tests

  • node scripts/check-type-check-coverage.mjs --self-test — 48 semantic +
    68 observation (+1 / +3 over baseline) + 43 re-measure + 28 built-closure +
    19 auto-lowering + 18 exit-code cases hold.
  • node scripts/check-type-check-coverage.mjs — before/predicate-only/final shown above.
  • node scripts/check-type-source-resolution.mjs --self-test — OK.
  • node scripts/check-type-source-resolution.mjs — OK, 56 registered (was 55 pre-onboarding, +1 this PR's entry), 0 unregistered exposure.
  • pnpm --filter "@objectstack/plugin-auth..." --filter "@objectstack/plugin-security..." --filter "@objectstack/service-i18n..." build then each package's own pnpm --filter <pkg> typecheck — all pass, shown above (os-verify-lock VERDICT command-exit 0, held 368s).
  • 31 of 34 additional gates dispatch-gates.mjs derives for this diff run green directly; the remaining 3 are legitimate NOT MEASURED (check-test-completeness needs a CI test log; check:type-check-debt --re-measure needs the full unfiltered workspace build closure, explicitly "not a pass and not a finding" per the gate's own refusal; check-half-states.mjs timed out against the network proxy under container contention — retried, not yet resolved by report time).
  • check:i18n / check:i18n-stale-fill (convention-triggered by the plugin-security/tsconfig.scripts.json edit) — both green, all 9 packages' bundles in sync.
  • pnpm check:pm-dispatch-gates (~11.5 min gate) — run in background under the shared verify lock; see report comment for its result.
  • Derived gate family via node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands — 48 commands (44 by path + 4 by change kind); see report comment for the full list and results.

Generated by Claude Code


Generated by Claude Code

…sc program
check:type-check-coverage's isUncheckedSourceCandidate skipped depth === 0
(the package root) unconditionally, so a package-root .ts file was invisible
to SOURCES_COVERED regardless of content. This is why #13284's driver-memory
/ plugin-hono-server manifests went unchecked for as long as they did.
Per the triage on #14386 (comment 5504408509), this admits depth === 0 only
for a declared, exact-name allowlist (ROOT_SOURCE_FILES, currently just
objectstack.config.ts) rather than every package-root file -- the wider
104-file question stays explicitly unresolved. The uncheckedByDir
aggregation now keys a root-level file at '.' (which posix.join collapses
to the package's own directory) instead of the rel.slice(0, -1) garbage key
the old indexOf('/') === -1 arithmetic produced.
The three sites the widened predicate then surfaces (plugin-auth,
plugin-security, service-i18n) are put into a program: widened include on
the existing sibling noEmit programs for the first two, a new sibling
tsconfig.typecheck.json (following the driver-memory shape from #13284) for
service-i18n, which had none to widen.
Putting service-i18n's manifest into a program onboards that package's
first tsc program to reach the bare @objectstack/spec specifier (src/ only
ever imports subpaths), which check:type-source-resolution correctly
flagged. Repaired via that gate's own documented onboarding-limb registry
re-baseline (the sanctioned tool for a dep reached only through a
newly-onboarded program -- paths is measured wrong for this shape on
PR #12570), with --list before/after numbers stated in place.
Fixes#14386
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

⚠️3 changed file(s) yielded no anchor (packages/plugins/plugin-auth/tsconfig.examples.json, packages/plugins/plugin-security/tsconfig.scripts.json, packages/services/service-i18n/tsconfig.typecheck.json), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files. Nothing else in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 3 changed package(s)).

What this run could not see
  • 3 changed file(s) yielded no anchor (packages/plugins/plugin-auth/tsconfig.examples.json, packages/plugins/plugin-security/tsconfig.scripts.json, packages/services/service-i18n/tsconfig.typecheck.json) — pages documenting those are invisible to this run
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 21 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 1d8ad0ffe51caae6892ccece9f8abad9794ac545packageMentionDocs.

@github-actionsgithub-actionsBot added dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation tooling labels Sep 2, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependenciesPull requests that update a dependency filedocumentationImprovements or additions to documentationsize/mtooling

Projects

None yet

2 participants

@baozhoutao@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(tooling): put three more package-root plugin manifests inside a tsc program - #14458

Merged
baozhoutao merged 2 commits into
mainfrom
claude/issue-14386-coverage-gate-package-root-source
Sep 2, 2026
Merged

fix(tooling): put three more package-root plugin manifests inside a tsc program#14458
baozhoutao merged 2 commits into
mainfrom
claude/issue-14386-coverage-gate-package-root-source

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#14386

What

check:type-check-coverage's isUncheckedSourceCandidate skipped depth === 0
(the package root) unconditionally, so any package-root .ts file was invisible
to SOURCES_COVERED regardless of content — not reported, not tracked. This is
exactly why #13284's driver-memory / plugin-hono-server manifests went
unchecked for as long as they did: pnpm --filter <pkg> typecheck exited 0
over a file no tsc program read, while check:type-check-coverage called the
package COVERED at the same time.

Per the triage (comment 5504408509 on #14386), this queues the narrow repair
only — admitting a declared set of root filenames that are authored source,
not every package-root .ts file:

  1. ROOT_SOURCE_FILES (currently {'objectstack.config.ts'}) — the depth-0
    exception to isUncheckedSourceCandidate, with a docblock stating the
    104-file question (every un-programmed vitest.config.ts / tsup.config.ts
    at a package root) is deliberately not answered here.
  2. The uncheckedByDir aggregation now keys a root-level unread file at '.'
    — which posix.join(dir, top) collapses to the package's own directory —
    instead of the rel.slice(0, -1) garbage key the old indexOf('/') === -1
    arithmetic produced.
  3. A --self-test case for a root-level source file (predicate rows for
    objectstack.config.ts / tsup.config.ts / a hypothetical root .d.ts,
    plus an evaluate()-level fixture pinning that the . root key renders as
    the package's own directory) — the existing source-layer cases were all
    subdirectory cases (packages/a/scripts), which is exactly why this hole
    survived.
  4. The three sites the widened predicate then surfaces are put into a program:

All three type-check clean at zero errors — no UNCHECKED_SOURCE_DEBT entry
is added.

Not this card

Per the triage, the 104-file question (whether every un-programmed
vitest.config.ts / tsup.config.ts at a package root owes a program or a
ledger entry) is explicitly not decided here. ROOT_SOURCE_FILES is a
closed, exact-name allowlist rather than a pattern, precisely so growing it
stays a decision made on its own card.

#13284 is not addressed here beyond what already landed — its fence (driver-memory,
plugin-hono-server) holds; this touches neither.

Verified: no other package-root objectstack.config.ts outside the three named

find packages apps examples -name objectstack.config.ts (filtered to
directories that are themselves a package.json root) turns up 8 hits: the 3
examples/app-* (already inside their own tsc programs, pre-existing),
driver-memory + plugin-hono-server (#13284, already covered), the 3 named
here, andpackages/create-objectstack/src/templates/blank/. That last one
is a scaffold template with its own nested pnpm-workspace.yaml — not a member
of this repo's own workspace (workspacePackageDirs() does not walk into it),
so the widened predicate correctly does not surface it. Left untouched, per the
triage's instruction not to add programs or ledger entries beyond the three
named sites — noted here for the record, not acted on.

Before / after

Baseline (origin/mainbd8795ea1, before any edit):

check-type-check-coverage: OK — 68/78 workspace packages type-checked (plus the root), 10 in the DEBT ledger (305 frozen raw errors, https://github.com/objectstack-ai/objectstack/issues/4311), 1 exempt.
test layer: 13 package(s) still hide their own tests from tsc (554 files hidden as counted by this run, 466 frozen raw errors in TEST_DEBT).
source layer: 1 directory(ies) of non-test source in 1 ledgered entr(y/ies) sit outside every tsc program their package's own `typecheck` runs (1 files as counted by this run).
...

Predicate-only (before the three tsconfig edits — proves the widened predicate
now sees the sites):

check-type-check-coverage: 3 problem(s)
• packages/plugins/plugin-auth: 1 non-test source file(s) here sit outside every tsc program that `@objectstack/plugin-auth`'s `typecheck` script runs, ...
• packages/plugins/plugin-security: 1 non-test source file(s) here sit outside every tsc program that `@objectstack/plugin-security`'s `typecheck` script runs, ...
• packages/services/service-i18n: 1 non-test source file(s) here sit outside every tsc program that `@objectstack/service-i18n`'s `typecheck` script runs, ...

Final, after the three tsconfig edits:

check-type-check-coverage: OK — 68/78 workspace packages type-checked (plus the root), 10 in the DEBT ledger (305 frozen raw errors, #4311), 1 exempt.
source layer: 1 directory(ies) of non-test source in 1 ledgered entr(y/ies) sit outside every tsc program their package's own `typecheck` runs (1 files as counted by this run).

Same shape as baseline — the pre-existing 1-entry source-layer ledger is
unchanged, and the three new sites are NOT in it (they are fully covered, zero
debt).

Each package's own typecheck, run against a freshly built dependency closure
(pnpm --filter "<pkg>..." build), also passes clean:

@objectstack/plugin-auth typecheck → tsc --noEmit && tsc --noEmit -p tsconfig.examples.json && check:test-typecheck — all pass (test layer: pre-existing 94 errors / 10 files, ledgered in test-typecheck-debt.json, unchanged by this PR)
@objectstack/plugin-security typecheck → tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json && check:test-typecheck — all pass, 0 errors
@objectstack/service-i18n typecheck → tsc --noEmit && tsc --noEmit -p tsconfig.typecheck.json — all pass

A second gate the new program onboarding tripped: check:type-source-resolution

Putting service-i18n's manifest into tsconfig.typecheck.json onboards that
package's first tsc program to reach the bare @objectstack/spec specifier —
src/ only ever imports subpaths (@objectstack/spec/contracts,
@objectstack/spec/system), never the bare package. check:type-source-resolution
correctly flagged this (a dep resolving through dist/ with no paths rule
pointing at source). Repaired via that gate's own documented onboarding-limb
registry re-baseline
— the sanctioned tool for exactly this shape (a dep
reached only through a newly-onboarded program; paths is measured wrong for
this shape on PR #12570, since it would pull packages/spec/src — and
everything it imports — into a program whose rootDir is .). One entry added
to KNOWN_DIST_RESOLVED_TYPE_IMPORTS:

'@objectstack/service-i18n': ['@objectstack/spec'],

--list before/after (measured at bd8795ea1, the entry excluded from "after"
to isolate what onboarding the program added):

before 55 of 77 packages, 111 programs, 269 pairs, 22 clean
after 56 of 77 packages, 112 programs, 270 pairs, 21 clean

+1 program, +1 pair, +1 package — this entry and nothing else. Full reasoning
in the file's own comment beside the entry. This edit is outside the file
surface named in the dispatch, filed as a bounded in-place-fix exemption per
os-dev.md rule 3 (surface amendment posted on #14386 before this PR opened).

Tests

  • node scripts/check-type-check-coverage.mjs --self-test — 48 semantic +
    68 observation (+1 / +3 over baseline) + 43 re-measure + 28 built-closure +
    19 auto-lowering + 18 exit-code cases hold.
  • node scripts/check-type-check-coverage.mjs — before/predicate-only/final shown above.
  • node scripts/check-type-source-resolution.mjs --self-test — OK.
  • node scripts/check-type-source-resolution.mjs — OK, 56 registered (was 55 pre-onboarding, +1 this PR's entry), 0 unregistered exposure.
  • pnpm --filter "@objectstack/plugin-auth..." --filter "@objectstack/plugin-security..." --filter "@objectstack/service-i18n..." build then each package's own pnpm --filter <pkg> typecheck — all pass, shown above (os-verify-lock VERDICT command-exit 0, held 368s).
  • 31 of 34 additional gates dispatch-gates.mjs derives for this diff run green directly; the remaining 3 are legitimate NOT MEASURED (check-test-completeness needs a CI test log; check:type-check-debt --re-measure needs the full unfiltered workspace build closure, explicitly "not a pass and not a finding" per the gate's own refusal; check-half-states.mjs timed out against the network proxy under container contention — retried, not yet resolved by report time).
  • check:i18n / check:i18n-stale-fill (convention-triggered by the plugin-security/tsconfig.scripts.json edit) — both green, all 9 packages' bundles in sync.
  • pnpm check:pm-dispatch-gates (~11.5 min gate) — run in background under the shared verify lock; see report comment for its result.
  • Derived gate family via node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands — 48 commands (44 by path + 4 by change kind); see report comment for the full list and results.

Generated by Claude Code


Generated by Claude Code

…sc program
check:type-check-coverage's isUncheckedSourceCandidate skipped depth === 0
(the package root) unconditionally, so a package-root .ts file was invisible
to SOURCES_COVERED regardless of content. This is why #13284's driver-memory
/ plugin-hono-server manifests went unchecked for as long as they did.
Per the triage on #14386 (comment 5504408509), this admits depth === 0 only
for a declared, exact-name allowlist (ROOT_SOURCE_FILES, currently just
objectstack.config.ts) rather than every package-root file -- the wider
104-file question stays explicitly unresolved. The uncheckedByDir
aggregation now keys a root-level file at '.' (which posix.join collapses
to the package's own directory) instead of the rel.slice(0, -1) garbage key
the old indexOf('/') === -1 arithmetic produced.
The three sites the widened predicate then surfaces (plugin-auth,
plugin-security, service-i18n) are put into a program: widened include on
the existing sibling noEmit programs for the first two, a new sibling
tsconfig.typecheck.json (following the driver-memory shape from #13284) for
service-i18n, which had none to widen.
Putting service-i18n's manifest into a program onboards that package's
first tsc program to reach the bare @objectstack/spec specifier (src/ only
ever imports subpaths), which check:type-source-resolution correctly
flagged. Repaired via that gate's own documented onboarding-limb registry
re-baseline (the sanctioned tool for a dep reached only through a
newly-onboarded program -- paths is measured wrong for this shape on
PR #12570), with --list before/after numbers stated in place.
Fixes#14386
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

⚠️3 changed file(s) yielded no anchor (packages/plugins/plugin-auth/tsconfig.examples.json, packages/plugins/plugin-security/tsconfig.scripts.json, packages/services/service-i18n/tsconfig.typecheck.json), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files. Nothing else in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 3 changed package(s)).

What this run could not see
  • 3 changed file(s) yielded no anchor (packages/plugins/plugin-auth/tsconfig.examples.json, packages/plugins/plugin-security/tsconfig.scripts.json, packages/services/service-i18n/tsconfig.typecheck.json) — pages documenting those are invisible to this run
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 21 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 1d8ad0ffe51caae6892ccece9f8abad9794ac545packageMentionDocs.

@github-actionsgithub-actionsBot added dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation tooling labels Sep 2, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependenciesPull requests that update a dependency filedocumentationImprovements or additions to documentationsize/mtooling

Projects

None yet

2 participants

@baozhoutao@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

fix(tooling): put three more package-root plugin manifests inside a tsc program - #14458

Merged
baozhoutao merged 2 commits into
mainfrom
claude/issue-14386-coverage-gate-package-root-source
Sep 2, 2026
Merged

fix(tooling): put three more package-root plugin manifests inside a tsc program#14458
baozhoutao merged 2 commits into
mainfrom
claude/issue-14386-coverage-gate-package-root-source

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#14386

What

check:type-check-coverage's isUncheckedSourceCandidate skipped depth === 0
(the package root) unconditionally, so any package-root .ts file was invisible
to SOURCES_COVERED regardless of content — not reported, not tracked. This is
exactly why #13284's driver-memory / plugin-hono-server manifests went
unchecked for as long as they did: pnpm --filter <pkg> typecheck exited 0
over a file no tsc program read, while check:type-check-coverage called the
package COVERED at the same time.

Per the triage (comment 5504408509 on #14386), this queues the narrow repair
only — admitting a declared set of root filenames that are authored source,
not every package-root .ts file:

  1. ROOT_SOURCE_FILES (currently {'objectstack.config.ts'}) — the depth-0
    exception to isUncheckedSourceCandidate, with a docblock stating the
    104-file question (every un-programmed vitest.config.ts / tsup.config.ts
    at a package root) is deliberately not answered here.
  2. The uncheckedByDir aggregation now keys a root-level unread file at '.'
    — which posix.join(dir, top) collapses to the package's own directory —
    instead of the rel.slice(0, -1) garbage key the old indexOf('/') === -1
    arithmetic produced.
  3. A --self-test case for a root-level source file (predicate rows for
    objectstack.config.ts / tsup.config.ts / a hypothetical root .d.ts,
    plus an evaluate()-level fixture pinning that the . root key renders as
    the package's own directory) — the existing source-layer cases were all
    subdirectory cases (packages/a/scripts), which is exactly why this hole
    survived.
  4. The three sites the widened predicate then surfaces are put into a program:

All three type-check clean at zero errors — no UNCHECKED_SOURCE_DEBT entry
is added.

Not this card

Per the triage, the 104-file question (whether every un-programmed
vitest.config.ts / tsup.config.ts at a package root owes a program or a
ledger entry) is explicitly not decided here. ROOT_SOURCE_FILES is a
closed, exact-name allowlist rather than a pattern, precisely so growing it
stays a decision made on its own card.

#13284 is not addressed here beyond what already landed — its fence (driver-memory,
plugin-hono-server) holds; this touches neither.

Verified: no other package-root objectstack.config.ts outside the three named

find packages apps examples -name objectstack.config.ts (filtered to
directories that are themselves a package.json root) turns up 8 hits: the 3
examples/app-* (already inside their own tsc programs, pre-existing),
driver-memory + plugin-hono-server (#13284, already covered), the 3 named
here, andpackages/create-objectstack/src/templates/blank/. That last one
is a scaffold template with its own nested pnpm-workspace.yaml — not a member
of this repo's own workspace (workspacePackageDirs() does not walk into it),
so the widened predicate correctly does not surface it. Left untouched, per the
triage's instruction not to add programs or ledger entries beyond the three
named sites — noted here for the record, not acted on.

Before / after

Baseline (origin/mainbd8795ea1, before any edit):

check-type-check-coverage: OK — 68/78 workspace packages type-checked (plus the root), 10 in the DEBT ledger (305 frozen raw errors, https://github.com/objectstack-ai/objectstack/issues/4311), 1 exempt.
test layer: 13 package(s) still hide their own tests from tsc (554 files hidden as counted by this run, 466 frozen raw errors in TEST_DEBT).
source layer: 1 directory(ies) of non-test source in 1 ledgered entr(y/ies) sit outside every tsc program their package's own `typecheck` runs (1 files as counted by this run).
...

Predicate-only (before the three tsconfig edits — proves the widened predicate
now sees the sites):

check-type-check-coverage: 3 problem(s)
• packages/plugins/plugin-auth: 1 non-test source file(s) here sit outside every tsc program that `@objectstack/plugin-auth`'s `typecheck` script runs, ...
• packages/plugins/plugin-security: 1 non-test source file(s) here sit outside every tsc program that `@objectstack/plugin-security`'s `typecheck` script runs, ...
• packages/services/service-i18n: 1 non-test source file(s) here sit outside every tsc program that `@objectstack/service-i18n`'s `typecheck` script runs, ...

Final, after the three tsconfig edits:

check-type-check-coverage: OK — 68/78 workspace packages type-checked (plus the root), 10 in the DEBT ledger (305 frozen raw errors, #4311), 1 exempt.
source layer: 1 directory(ies) of non-test source in 1 ledgered entr(y/ies) sit outside every tsc program their package's own `typecheck` runs (1 files as counted by this run).

Same shape as baseline — the pre-existing 1-entry source-layer ledger is
unchanged, and the three new sites are NOT in it (they are fully covered, zero
debt).

Each package's own typecheck, run against a freshly built dependency closure
(pnpm --filter "<pkg>..." build), also passes clean:

@objectstack/plugin-auth typecheck → tsc --noEmit && tsc --noEmit -p tsconfig.examples.json && check:test-typecheck — all pass (test layer: pre-existing 94 errors / 10 files, ledgered in test-typecheck-debt.json, unchanged by this PR)
@objectstack/plugin-security typecheck → tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json && check:test-typecheck — all pass, 0 errors
@objectstack/service-i18n typecheck → tsc --noEmit && tsc --noEmit -p tsconfig.typecheck.json — all pass

A second gate the new program onboarding tripped: check:type-source-resolution

Putting service-i18n's manifest into tsconfig.typecheck.json onboards that
package's first tsc program to reach the bare @objectstack/spec specifier —
src/ only ever imports subpaths (@objectstack/spec/contracts,
@objectstack/spec/system), never the bare package. check:type-source-resolution
correctly flagged this (a dep resolving through dist/ with no paths rule
pointing at source). Repaired via that gate's own documented onboarding-limb
registry re-baseline
— the sanctioned tool for exactly this shape (a dep
reached only through a newly-onboarded program; paths is measured wrong for
this shape on PR #12570, since it would pull packages/spec/src — and
everything it imports — into a program whose rootDir is .). One entry added
to KNOWN_DIST_RESOLVED_TYPE_IMPORTS:

'@objectstack/service-i18n': ['@objectstack/spec'],

--list before/after (measured at bd8795ea1, the entry excluded from "after"
to isolate what onboarding the program added):

before 55 of 77 packages, 111 programs, 269 pairs, 22 clean
after 56 of 77 packages, 112 programs, 270 pairs, 21 clean

+1 program, +1 pair, +1 package — this entry and nothing else. Full reasoning
in the file's own comment beside the entry. This edit is outside the file
surface named in the dispatch, filed as a bounded in-place-fix exemption per
os-dev.md rule 3 (surface amendment posted on #14386 before this PR opened).

Tests

  • node scripts/check-type-check-coverage.mjs --self-test — 48 semantic +
    68 observation (+1 / +3 over baseline) + 43 re-measure + 28 built-closure +
    19 auto-lowering + 18 exit-code cases hold.
  • node scripts/check-type-check-coverage.mjs — before/predicate-only/final shown above.
  • node scripts/check-type-source-resolution.mjs --self-test — OK.
  • node scripts/check-type-source-resolution.mjs — OK, 56 registered (was 55 pre-onboarding, +1 this PR's entry), 0 unregistered exposure.
  • pnpm --filter "@objectstack/plugin-auth..." --filter "@objectstack/plugin-security..." --filter "@objectstack/service-i18n..." build then each package's own pnpm --filter <pkg> typecheck — all pass, shown above (os-verify-lock VERDICT command-exit 0, held 368s).
  • 31 of 34 additional gates dispatch-gates.mjs derives for this diff run green directly; the remaining 3 are legitimate NOT MEASURED (check-test-completeness needs a CI test log; check:type-check-debt --re-measure needs the full unfiltered workspace build closure, explicitly "not a pass and not a finding" per the gate's own refusal; check-half-states.mjs timed out against the network proxy under container contention — retried, not yet resolved by report time).
  • check:i18n / check:i18n-stale-fill (convention-triggered by the plugin-security/tsconfig.scripts.json edit) — both green, all 9 packages' bundles in sync.
  • pnpm check:pm-dispatch-gates (~11.5 min gate) — run in background under the shared verify lock; see report comment for its result.
  • Derived gate family via node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands — 48 commands (44 by path + 4 by change kind); see report comment for the full list and results.

Generated by Claude Code


Generated by Claude Code

…sc program
check:type-check-coverage's isUncheckedSourceCandidate skipped depth === 0
(the package root) unconditionally, so a package-root .ts file was invisible
to SOURCES_COVERED regardless of content. This is why #13284's driver-memory
/ plugin-hono-server manifests went unchecked for as long as they did.
Per the triage on #14386 (comment 5504408509), this admits depth === 0 only
for a declared, exact-name allowlist (ROOT_SOURCE_FILES, currently just
objectstack.config.ts) rather than every package-root file -- the wider
104-file question stays explicitly unresolved. The uncheckedByDir
aggregation now keys a root-level file at '.' (which posix.join collapses
to the package's own directory) instead of the rel.slice(0, -1) garbage key
the old indexOf('/') === -1 arithmetic produced.
The three sites the widened predicate then surfaces (plugin-auth,
plugin-security, service-i18n) are put into a program: widened include on
the existing sibling noEmit programs for the first two, a new sibling
tsconfig.typecheck.json (following the driver-memory shape from #13284) for
service-i18n, which had none to widen.
Putting service-i18n's manifest into a program onboards that package's
first tsc program to reach the bare @objectstack/spec specifier (src/ only
ever imports subpaths), which check:type-source-resolution correctly
flagged. Repaired via that gate's own documented onboarding-limb registry
re-baseline (the sanctioned tool for a dep reached only through a
newly-onboarded program -- paths is measured wrong for this shape on
PR #12570), with --list before/after numbers stated in place.
Fixes#14386
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

⚠️3 changed file(s) yielded no anchor (packages/plugins/plugin-auth/tsconfig.examples.json, packages/plugins/plugin-security/tsconfig.scripts.json, packages/services/service-i18n/tsconfig.typecheck.json), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files. Nothing else in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 3 changed package(s)).

What this run could not see
  • 3 changed file(s) yielded no anchor (packages/plugins/plugin-auth/tsconfig.examples.json, packages/plugins/plugin-security/tsconfig.scripts.json, packages/services/service-i18n/tsconfig.typecheck.json) — pages documenting those are invisible to this run
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 21 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 1d8ad0ffe51caae6892ccece9f8abad9794ac545packageMentionDocs.

@github-actionsgithub-actionsBot added dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation tooling labels Sep 2, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependenciesPull requests that update a dependency filedocumentationImprovements or additions to documentationsize/mtooling

Projects

None yet

2 participants

@baozhoutao@claude