You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
lint: no gate resolves a documented @objectstack/* import SPECIFIER against the target package's exports map — check:published-readme-exports asks a different question #16207
Split out of #15931 (delivered by PR #16205), where the dispatch ruled the gate itself out of scope. That card's "Acceptance" section proposes it and the triage seat seconded it; this is the row.
The gap, stated as the difference between two questions
check:published-readme-exports asks "is this documented SYMBOL in the target package's built types?". The defect on #15931 was a documented SPECIFIER that the target package's exports map cannot resolve — a different question, which no gate in the tree asks today. The two are independent: on #15931 the symbols were real and exported, and only the path was wrong, so a symbol-vs-types gate is structurally incapable of seeing it. That is not a coverage shortfall in the existing gate; it is a question nobody asks.
The failure is a hard resolution refusal, not a soft typing gap:
REFUSED: ERR_PACKAGE_PATH_NOT_EXPORTED - Package subpath './security' is not defined
by "exports" in packages/core/package.json
CONTROL: import('@objectstack/core/logger') -> RESOLVED, exports: ObjectLogger,createLogger
The proposed gate would read every documented @objectstack/* import specifier in the tree and resolve it against the named workspace package's own exports map.
What a population count would have to settle first, and why this is its own card
Which documents?PHASE2_IMPLEMENTATION.md was invisible to check:published-readme-exports precisely because packages/core does not publish it: npm pack --dry-run over that package lists 16 files and no PHASE2_IMPLEMENTATION.md, only CHANGELOG.md and README.md. A specifier gate that reads only published documents inherits the same blind spot; one that reads every tracked markdown file has to be sized before it is written.
How many false positives? Measured while delivering core: PHASE2_IMPLEMENTATION.md teaches @objectstack/core/security, a subpath the package exports in no entry #15931, the string @objectstack/core/security appears in 16 tracked files, but only 3 of them carry it in an import-statement shape and only 2 were real instructions to a reader. The rest are prose, changelog history, a @module tag, and a pin test's own commentary about the subpath. A naive matcher reddens on all 16.
Whose exports map? Resolution has to follow the workspace member, not the installed tarball, and has to handle wildcard exports keys — packages/core has none today, but the gate cannot assume that of every package.
The existing green.check:published-readme-exports currently reports 60 published documents across 79 workspace packages, 215 import statements, 200/200 @objectstack/ specifiers naming a workspace member. That 200/200 is a membership count, not a resolution count — it is the natural place to look for either a home for this check or a reason it should not live there.
Unassigned and ungraded on purpose: the sizing above is the work, and the answer decides whether this is a new gate or a second limb on the existing one.
(b) violation of a declared contract — ⛔ none. No rule says documented specifiers must be resolution-checked.
(c) metadata trap — ⛔ not applicable.
⭐ The card states its own disposition better than I could: "That is not a coverage shortfall in the existing gate; it is a question nobody asks." ⇒ That is precisely the line this seat drew today between objectui#8141 (admitted — a gate runs and its verdict reads broader than what it checked, so the absence hides behind a green) and objectui#8286 (closed — no gate asks the question at all, so the absence is visible to anyone who looks). check:published-readme-exports does not over-claim here: it asks "is this documented SYMBOL in the target package's built types?", and it answers that. A specifier is a different question, and it is unasked rather than mis-answered.
⭐ The measurement is exemplary and survives the close — ERR_PACKAGE_PATH_NOT_EXPORTED for ./securitywith a resolving control in the same read (@objectstack/core/logger → RESOLVED, exports ObjectLogger,createLogger). ⇒ A hard resolution refusal, not a soft typing gap, and proven to be a verdict rather than a broken probe.
承接者: ⛔ none.⚠️ Checked, not assumed: #15931 is delivered, so its PR is gone as a vehicle; #16209 (graded p2 today) touches the same script and would be the natural rider — ⛔ but it is scoped to teaching the call-site half to bind a new-built receiver, which is the symbol question again, not the specifier question. ⇒ Adding a resolution limb there would be exactly the unmeasured widening #16209's own scope warning cautions against.
What I am uncertain about, and it is the strongest argument against this close: the card's sizing work is real and would have to be redone by whoever revisits this — the four questions it raises (which documents; the 16-hits-vs-3-import-shapes-vs-2-real false-positive ratio; workspace-member vs tarball resolution with wildcard exports; and that the existing 200/200 is a membership count, not a resolution count) are the actual content, and they are good. ⛔ Closing does not delete them — they stay searchable on this card and are the first thing to read if it reopens. ⚠️ The 200/200 observation in particular is worth someone's attention independently: a green that counts membership while reading as resolution is the over-claim shape, and if anyone measures it as an over-claim rather than as a missing gate, that is a different card and an admissible one.
Reopen conditions (either, no approval needed):
A second documented-specifier resolution defect is found. At n=2 the class is evidenced rather than extrapolated from one fix, and the gate proposal stops being speculative.
check:published-readme-exports grows a resolution limb for any other reason — at which point this card's sizing is the design input and should be read before the population is chosen.
Reversibility: fully reversible, and ⛔ nothing decays while closed. The #15931 defect is fixed; no window closes; npm pack --dry-run and the 16/3/2 counts are re-runnable at any time.
⚠️ One caution for a future round, from the card's own question 1: PHASE2_IMPLEMENTATION.md was invisible to the existing gate because packages/coredoes not publish it (npm pack --dry-run lists 16 files, only CHANGELOG.md and README.md among the docs). ⇒ ⛔ A specifier gate scoped to published documents would inherit that identical blind spot — the same defect one level up. Anyone reviving this must size the document population first, before writing a matcher.
Activity
os-zhuang commentedon Sep 7, 2026
Triage: closing
not planned— outside the three admission classes (#16351, as refined by PR #16557).Against each class:
PHASE2_IMPLEMENTATION.mdteaches@objectstack/core/security, a subpath the package exports in no entry #15931's unresolvable@objectstack/core/securityspecifier) was delivered by PR fix(core): PHASE2_IMPLEMENTATION.md imports from the root barrel, not an undeclared subpath #16205. What remains is a proposal for a gate.⭐ The card states its own disposition better than I could: "That is not a coverage shortfall in the existing gate; it is a question nobody asks." ⇒ That is precisely the line this seat drew today between objectui#8141 (admitted — a gate runs and its verdict reads broader than what it checked, so the absence hides behind a green) and objectui#8286 (closed — no gate asks the question at all, so the absence is visible to anyone who looks).
check:published-readme-exportsdoes not over-claim here: it asks "is this documented SYMBOL in the target package's built types?", and it answers that. A specifier is a different question, and it is unasked rather than mis-answered.⭐ The measurement is exemplary and survives the close —
ERR_PACKAGE_PATH_NOT_EXPORTEDfor./securitywith a resolving control in the same read (@objectstack/core/logger→ RESOLVED, exportsObjectLogger,createLogger). ⇒ A hard resolution refusal, not a soft typing gap, and proven to be a verdict rather than a broken probe.承接者: ⛔ none.⚠️ Checked, not assumed: #15931 is delivered, so its PR is gone as a vehicle; #16209 (graded
p2today) touches the same script and would be the natural rider — ⛔ but it is scoped to teaching the call-site half to bind anew-built receiver, which is the symbol question again, not the specifier question. ⇒ Adding a resolution limb there would be exactly the unmeasured widening #16209's own scope warning cautions against.What I am uncertain about, and it is the strongest argument against this close: the card's sizing work is real and would have to be redone by whoever revisits this — the four questions it raises (which documents; the 16-hits-vs-3-import-shapes-vs-2-real false-positive ratio; workspace-member vs tarball resolution with wildcard⚠️ The 200/200 observation in particular is worth someone's attention independently: a green that counts membership while reading as resolution is the over-claim shape, and if anyone measures it as an over-claim rather than as a missing gate, that is a different card and an admissible one.
exports; and that the existing 200/200 is a membership count, not a resolution count) are the actual content, and they are good. ⛔ Closing does not delete them — they stay searchable on this card and are the first thing to read if it reopens.Reopen conditions (either, no approval needed):
check:published-readme-exportsgrows a resolution limb for any other reason — at which point this card's sizing is the design input and should be read before the population is chosen.Reversibility: fully reversible, and ⛔ nothing decays while closed. The #15931 defect is fixed; no window closes;
npm pack --dry-runand the 16/3/2 counts are re-runnable at any time.PHASE2_IMPLEMENTATION.mdwas invisible to the existing gate becausepackages/coredoes not publish it (npm pack --dry-runlists 16 files, onlyCHANGELOG.mdandREADME.mdamong the docs). ⇒ ⛔ A specifier gate scoped to published documents would inherit that identical blind spot — the same defect one level up. Anyone reviving this must size the document population first, before writing a matcher.Generated by Claude Code