From 686a4c60cb76ea289772fe8e33d6a1be9208a9c0 Mon Sep 17 00:00:00 2001 From: Jack Zhuang <50353452+hotlong@users.noreply.github.com> Date: Tue, 29 Sep 2026 23:47:26 +0800 Subject: [PATCH] docs(types): re-anchor the dead tracker citations in packages/types/src to the commits that decided them Every comment and docblock site under packages/types/src that cited a tracker number answering 404 now cites the commit in this repository's history that decided what the line describes, and says in its own words what that commit decided. Comments only; every touched file keeps its line count. A patch changeset ships because the docblocks reach dist. Claude-Session: https://claude.ai/code/session_local_1d2a197c-c20e-4e90-9be8-413d4d432289 Co-authored-by: Claude --- .changeset/types-provenance-anchors.md | 10 ++++ ...river-error-classification.callers.test.ts | 8 +-- ...error-classification.operator-text.test.ts | 2 +- ...rror-classification.targeted-table.test.ts | 6 +- .../src/driver-error-classification.test.ts | 2 +- .../types/src/driver-error-classification.ts | 32 +++++----- packages/types/src/email-verified.test.ts | 2 +- packages/types/src/email-verified.ts | 2 +- packages/types/src/error-leak.test.ts | 4 +- packages/types/src/index.ts | 4 +- packages/types/src/node.test.ts | 34 +++++------ packages/types/src/node.ts | 60 +++++++++---------- packages/types/src/response-envelope.test.ts | 2 +- packages/types/src/response-envelope.ts | 2 +- packages/types/src/thrown-http-error.test.ts | 2 +- packages/types/src/thrown-http-error.ts | 14 ++--- packages/types/src/unique-violation.test.ts | 4 +- packages/types/src/unique-violation.ts | 8 +-- 18 files changed, 104 insertions(+), 94 deletions(-) create mode 100644 .changeset/types-provenance-anchors.md diff --git a/.changeset/types-provenance-anchors.md b/.changeset/types-provenance-anchors.md new file mode 100644 index 00000000000..240ee520105 --- /dev/null +++ b/.changeset/types-provenance-anchors.md @@ -0,0 +1,10 @@ +--- +'@objectstack/types': patch +--- + +Provenance comments in `@objectstack/types` were re-anchored + +Comment and docblock lines under `src/` that cited tracker numbers which no +longer resolve on GitHub now cite the commit in this repository's history that +decided the matter, and say in their own words what was decided. Comments +only: no error code, refusal text, type, export or runtime behaviour changes. diff --git a/packages/types/src/driver-error-classification.callers.test.ts b/packages/types/src/driver-error-classification.callers.test.ts index 8b09a76fcaf..8c6179336e8 100644 --- a/packages/types/src/driver-error-classification.callers.test.ts +++ b/packages/types/src/driver-error-classification.callers.test.ts @@ -7,7 +7,7 @@ * * ── The defect class ───────────────────────────────────────────────────────── * - * #13324 repaired the predicate by giving it `readObject`, so a driver fault + * Commit 4cda78c9b repaired the predicate by giving it `readObject`, so a driver fault * naming a DIFFERENT relation can no longer be answered "this table is not * provisioned yet". The parameter had to ship OPTIONAL: `@objectstack/types` is * published (17.2.0, `exports` `.` and `./node`), and re-exported again from @@ -17,12 +17,12 @@ * * Optional is right for the world outside this repo and wrong for the inside of * it. `isMissingTableError(err)` still compiles, still type-checks, and still - * returns the pre-#13324 WIDE verdict — silently. On the authz path + * returns the WIDE verdict from before commit 4cda78c9b — silently. On the authz path * (`packages/core/src/security/resolve-authz-context.ts`) that verdict resolves * a permission-store OUTAGE to `[]` permissions instead of failing loud, so the * omission fails in the OPEN direction. That is the same declared-but-not- - * enforced shape #13324 existed to close, one level up: the obligation is - * stated in prose, and prose is exactly what #13324 proved insufficient. + * enforced shape commit 4cda78c9b closed, one level up: the obligation is + * stated in prose, and prose is exactly what that commit's defect proved insufficient. * * ── Why a gate and not a required parameter ────────────────────────────────── * diff --git a/packages/types/src/driver-error-classification.operator-text.test.ts b/packages/types/src/driver-error-classification.operator-text.test.ts index 7093ac0eb99..1d01d7e1223 100644 --- a/packages/types/src/driver-error-classification.operator-text.test.ts +++ b/packages/types/src/driver-error-classification.operator-text.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * [#16657] `operatorFacingErrorText` — the dialect's words for a record an + * [commit 5a95b0e93] `operatorFacingErrorText` — the dialect's words for a record an * operator reads later. * * ## The regression this closes, and why "one `cause` away" was not enough diff --git a/packages/types/src/driver-error-classification.targeted-table.test.ts b/packages/types/src/driver-error-classification.targeted-table.test.ts index fc1a5d13a6c..daf84dcda9b 100644 --- a/packages/types/src/driver-error-classification.targeted-table.test.ts +++ b/packages/types/src/driver-error-classification.targeted-table.test.ts @@ -4,7 +4,7 @@ * #13438 — `isMissingTableError` prefers the table a driver DECLARED it targeted * over the caller-supplied `readObject`. * - * The residual #13324 left behind: a caller names its OBJECT, a driver compiles + * The residual commit 4cda78c9b left behind: a caller names its OBJECT, a driver compiles * the statement against the PHYSICAL table, and for a federated object * (ADR-0015, `external.remoteName`) the two differ. `crm_order` reads * `legacy_orders`; when that remote is genuinely absent the phrase names @@ -14,7 +14,7 @@ * Maintainer ruling 2026-09-01 (option 2 on the card): the driver declares the * table it targeted on the envelope, the predicate prefers it. The pair the * ruling asks for is pinned here — an absent remote reads benign again, and a - * DIFFERENT relation's error still reads not-benign (the #13324 narrowing must + * DIFFERENT relation's error still reads not-benign (the narrowing commit 4cda78c9b made must * not reopen) — with the declaration present. The driver's half (that * `driver-sql` really stamps `external.remoteName`, live, on each dialect) is * `packages/drivers/driver-sql/src/sql-driver-13438-federated-missing-remote-envelope.test.ts`. @@ -181,7 +181,7 @@ describe('isMissingTableError — a declared targeted table beats the caller-sup }); it('a declared node whose phrase mismatches is NOT rescued by a matching cause', () => { - // Same disposition #6347 and #13324 gave the exclusion: recognition + // Same disposition #6347 and commit 4cda78c9b gave the exclusion: recognition // ends the question rather than descending. const err = envelope( Object.assign(new Error('no such table: main.absent_base'), { diff --git a/packages/types/src/driver-error-classification.test.ts b/packages/types/src/driver-error-classification.test.ts index e4f47fc8ffa..e898cc775d9 100644 --- a/packages/types/src/driver-error-classification.test.ts +++ b/packages/types/src/driver-error-classification.test.ts @@ -4,7 +4,7 @@ * #4728 / #4825 — the classifications that decide whether a driver failure may * be silenced. * - * [#13279] Moved here with the module it tests, from + * [commit 6a180e42d] Moved here with the module it tests, from * `packages/metadata/src/utils/schema-sync-errors.test.ts`. Unchanged except * for the import path: `@objectstack/core`'s authorization resolver now asks * `isMissingTableError`, so the predicate lives in the package both sides diff --git a/packages/types/src/driver-error-classification.ts b/packages/types/src/driver-error-classification.ts index 8f514b4f343..48f442b7995 100644 --- a/packages/types/src/driver-error-classification.ts +++ b/packages/types/src/driver-error-classification.ts @@ -4,7 +4,7 @@ * Driver-error classification: "which driver failures may be silenced?" * (#4728, #4825; rule from #4632). * - * ## Home — `@objectstack/types`, since #13279 + * ## Home — `@objectstack/types`, since commit 6a180e42d * * This module was born in `@objectstack/metadata` and lived there through * #4728 / #4825 / #5841. `@objectstack/metadata/errors`' own docblock recorded @@ -16,7 +16,7 @@ * * What forced it: `resolveAuthzContext` (`@objectstack/core`) must ask * {@link isMissingTableError} to tell a permission-store OUTAGE from a - * deployment whose `sys_*` tables were never provisioned (#13279). Core cannot + * deployment whose `sys_*` tables were never provisioned (commit 6a180e42d). Core cannot * import `@objectstack/metadata` — metadata **depends on** core — so the * predicate had to move to a package both sides already depend on, or be * copied. Copying was measured and rejected: two vocabularies of "which driver @@ -134,7 +134,7 @@ // `relation-sub-object.ts` next door for the superstring hole it closes and for // why the exclusion's width deliberately differs from the extractor's. That // module was already this one's dependency across the package boundary; since -// #13279 moved this file into `@objectstack/types`, the two are siblings. +// commit 6a180e42d moved this file into `@objectstack/types`, the two are siblings. import { isRelationSubObjectPhrase } from './relation-sub-object.js'; /** @@ -372,7 +372,7 @@ const MISSING_TABLE: DriverErrorSignature = { * * [#6615] All three now read one home — `@objectstack/types` — instead * of three hand-kept copies, so the phrase can no longer be taught to - * the repo a fourth time or drift in one package only. [#13279] This + * the repo a fourth time or drift in one package only. [commit 6a180e42d] This * file now lives in that same home, so the read is a sibling import. The **width** * difference that used to justify the copy is preserved and is the * reason the home exports two functions rather than one: those two @@ -386,7 +386,7 @@ const MISSING_TABLE: DriverErrorSignature = { */ matchesMessage: isRelationSubObjectPhrase, /** - * [#13324] "…and the relation it names is not the one you read." + * [commit 4cda78c9b] "…and the relation it names is not the one you read." * * The sibling of the phrase above, reached one step further out. That * one recognises a failure about something INSIDE a relation, which @@ -408,7 +408,7 @@ const MAX_CAUSE_DEPTH = 4; * [#13438] The physical table a driver's statement TARGETED, declared on the * error envelope by the producer that knows it. * - * `readObject` closed the #13324 hole for callers that can name what they read + * `readObject` (commit 4cda78c9b) closed the hole for callers that can name what they read * — and left a residual one layer down. A caller names its OBJECT (the API * name); a driver compiles the statement against the PHYSICAL table, and for a * federated object (ADR-0015, `external.remoteName`) those are two different @@ -424,7 +424,7 @@ const MAX_CAUSE_DEPTH = 4; * stamps the table its statement targeted onto it — and the predicate PREFERS * a declared table over the caller-supplied `readObject`. The caller never * needs to know a federated object's remote name, and a driver that declares - * nothing gets exactly the #13324 behaviour. + * nothing gets exactly the behaviour commit 4cda78c9b introduced. * * A symbol key from the global registry, held non-enumerable: the carrier * discipline `driver-sql` already applies to its withheld-diagnostic symbols @@ -438,7 +438,7 @@ const MAX_CAUSE_DEPTH = 4; * ⚠️ A declaration is EVIDENCE, so it also narrows the one-argument form: an * envelope declaring `legacy_orders` whose dialect phrase names some other * relation reads not-benign even with no `readObject` — the driver supplied - * the fact the caller could not. That is the #13324 verdict reached without + * the fact the caller could not. That is commit 4cda78c9b's verdict, reached without * the caller's help, in the direction the module docblock calls cheap. */ export const DRIVER_TARGETED_TABLE: symbol = Symbol.for('objectstack.driver.targetedTable'); @@ -596,7 +596,7 @@ export function isSchemaAlreadyExistsError(error: unknown, depth = 0): boolean { * Postgres' two phrasings — the relation is right there in the message because * it exists (#6347). See {@link MISSING_TABLE}'s `excludes`. * - * [#13324] Neither is a failure that names a **different relation**, and that + * [commit 4cda78c9b] Neither is a failure that names a **different relation**, and that * one cannot be seen without `readObject`. The message test asks what the * phrase LOOKS like and never which table it names, so a read of a view whose * base table has been dropped — `no such table: main.`, measured on @@ -605,7 +605,7 @@ export function isSchemaAlreadyExistsError(error: unknown, depth = 0): boolean { * be about the table the caller asked for, or it is not evidence about it. * * Pass `readObject` from every in-repo call site. It is **optional** so that - * omitting it is exactly the pre-#13324 behaviour rather than a new loud + * omitting it is exactly the behaviour before commit 4cda78c9b rather than a new loud * failure — this is a published export (`@objectstack/types`, and still * `@objectstack/metadata/errors` by re-export), and a required parameter would * be a breaking change to it. The cost of the choice @@ -626,12 +626,12 @@ export function isSchemaAlreadyExistsError(error: unknown, depth = 0): boolean { * federated object (ADR-0015) that is not the name the driver put in the * statement — `crm_order` reads `external.remoteName: 'legacy_orders'`, so a * genuinely absent remote raised a phrase naming `legacy_orders` against a - * caller naming `crm_order`, and the #13324 comparison read it loud. A driver + * caller naming `crm_order`, and the comparison commit 4cda78c9b added read it loud. A driver * that knows the table it targeted now DECLARES it on the envelope * ({@link declareTargetedTable}), and a declared table is preferred over * `readObject` outright: the phrase is compared against the declared name, and * the caller-supplied one is not consulted at that node or below it. Absent a - * declaration the comparison is the #13324 one, unchanged. Two consequences, + * declaration the comparison is commit 4cda78c9b's, unchanged. Two consequences, * both pinned: a genuinely absent federated remote reads benign again without * the caller learning the mapping; and — because a declaration is evidence the * caller did not have — an envelope whose phrase names a relation other than @@ -654,11 +654,11 @@ export function isMissingTableError(error: unknown, readObject?: string, depth = } // --------------------------------------------------------------------------- -// Operator-facing text for a DECLARED driver fault (#16657) +// Operator-facing text for a DECLARED driver fault (commit 5a95b0e93) // --------------------------------------------------------------------------- /** - * [#16657] The ADR-0112 code a driver declares when the backend, not the + * [commit 5a95b0e93] The ADR-0112 code a driver declares when the backend, not the * caller, refused the work. Spelled as a literal for the same reason * {@link declaresServerFault} spells `status`/`code` by hand: this package is * the common dependency every consumer of the question already has, and reading @@ -667,7 +667,7 @@ export function isMissingTableError(error: unknown, readObject?: string, depth = const DECLARED_DATABASE_FAULT_CODE = 'DATABASE_ERROR'; /** - * [#16657] The fragment that identifies `SqlDriver`'s RAW-path envelope, and + * [commit 5a95b0e93] The fragment that identifies `SqlDriver`'s RAW-path envelope, and * only it. * * The raw terminal (`rawStatementFaultError`, `driver-sql/src/sql-driver.ts`; @@ -727,7 +727,7 @@ function messageChannelOf(node: unknown): string { /** * The text an OPERATOR should read for `error` — the dialect's own words when a - * driver composed over them, the error's own message otherwise (#16657). + * driver composed over them, the error's own message otherwise (commit 5a95b0e93). * * # The defect this closes * diff --git a/packages/types/src/email-verified.test.ts b/packages/types/src/email-verified.test.ts index 26d2b2b13f6..ae71ee30fca 100644 --- a/packages/types/src/email-verified.test.ts +++ b/packages/types/src/email-verified.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * [#11343 / #12751] The verified-email allow-list, pinned representation by + * [commit c0714eb5d / #12751] The verified-email allow-list, pinned representation by * representation. This predicate is shared between the walled owner-elevation * gate (which REFUSES on `false`) and the owner-verification boot diagnostic * (which stays quiet on `true`) — the pin here is what both consumers stand diff --git a/packages/types/src/email-verified.ts b/packages/types/src/email-verified.ts index 4be39ea3c38..e5ce36dca9a 100644 --- a/packages/types/src/email-verified.ts +++ b/packages/types/src/email-verified.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * [#11343 / #12751] Verified-email predicate over a stored `sys_user` row — a + * [commit c0714eb5d / #12751] Verified-email predicate over a stored `sys_user` row — a * fail-closed ALLOW-LIST over the representations a driver may hand back for * the `sys_user.email_verified` boolean column (JS `true`, SQLite `1`, and * their stringified forms). Everything else — `false`/`0`, `null`, an ABSENT diff --git a/packages/types/src/error-leak.test.ts b/packages/types/src/error-leak.test.ts index 97a11c9eedb..e9e1e4b5f22 100644 --- a/packages/types/src/error-leak.test.ts +++ b/packages/types/src/error-leak.test.ts @@ -138,7 +138,7 @@ describe('looksLikeInternalErrorLeak — shipped-dialect phrasings (#8132)', () // SQLite/libsql message-only errors: the same conditions with NO // `SQLITE_` prefix to trip the existing limb. Measured shapes in this // repo — `driver-error-classification.ts` (next door, moved here by - // #13279 from `metadata/src/utils/schema-sync-errors.ts`) documents both. + // commit 6a180e42d from `metadata/src/utils/schema-sync-errors.ts`) documents both. ['sqlite bare missing table', 'no such table: sys_metadata'], ['sqlite bare missing table with a schema prefix', 'no such table: main.sys_metadata_history'], ['sqlite bare missing column', 'no such column: bogus'], @@ -177,7 +177,7 @@ describe('looksLikeInternalErrorLeak — shipped-dialect phrasings (#8132)', () * MySQL, and a reviewer sizing a disclosure residual on PR #8737 quoted it in * good faith; the claim was false (`driver-sql` branches on `mysql`/`mysql2`, * CI stands up a live `mysql:8.0` for a required check, live MySQL 8.0.46 - * measurements landed driver fixes #8621/#8622). PR #8824 corrected the + * measurements landed driver fixes #8621/#8622). Commit 8ac232306 corrected the * sentence and pinned the narrower, then-true fact — the predicate did not * COVER MySQL — as a deliberate tripwire for the decision that was still open. * diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 0235d4e7d2e..982575748fc 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -1,7 +1,7 @@ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license. export * from './degraded-boot.js'; -// [#11343/#12751] The one verified-email predicate the walled owner-elevation +// [commit c0714eb5d / #12751] The one verified-email predicate the walled owner-elevation // gate (plugin-security) and the owner-verification boot diagnostic // (plugin-auth) both read — see the module doc for why it must be one. export * from './email-verified.js'; @@ -48,7 +48,7 @@ export * from './relation-sub-object.js'; // Four hand-written vocabularies used to answer it and disagreed about MySQL, // which is why every MySQL conflict came back 500 instead of 409. export * from './unique-violation.js'; -// [#4728/#4825, moved here by #13279] The one "which driver failures may be +// [#4728/#4825, moved here by commit 6a180e42d] The one "which driver failures may be // silenced?" vocabulary — `isMissingTableError` (a READ failed because the // table was never provisioned) and `isSchemaAlreadyExistsError` (a DDL failure // that was just the table already being there). It was `@objectstack/metadata`'s diff --git a/packages/types/src/node.test.ts b/packages/types/src/node.test.ts index 3d663ffee49..f331c53b2c8 100644 --- a/packages/types/src/node.test.ts +++ b/packages/types/src/node.test.ts @@ -214,7 +214,7 @@ describe('host-app package resolution (cloud#1013, #4700)', () => { 'the DEFAULT fallback is this package\'s own resolution — @objectstack/spec and nothing else', async () => { // ⚠️ Read this case for what it measures, not for what it used to be - // called (#10943). It was named "falls back to the importing package's + // called (commit 46d34ab7c). It was named "falls back to the importing package's // own resolution", which is the helper's DOCUMENTED contract — but it // passes because `@objectstack/spec` is the one dependency // `@objectstack/types` declares, so it is green whether the fallback @@ -223,7 +223,7 @@ describe('host-app package resolution (cloud#1013, #4700)', () => { // be found by measurement instead. // // What it legitimately pins is the DEFAULT (no `fallbackImport`) base: - // unchanged by #10943, so an out-of-tree caller keeps working. The + // unchanged by commit 46d34ab7c, so an out-of-tree caller keeps working. The // documented contract is pinned by the caller-anchored matrix below, // where every row can actually fail. const mod = await createHostImporter(undeclaringRoot)('@objectstack/spec'); @@ -443,10 +443,10 @@ describe('what counts as a declaration (#4719)', () => { }); /** - * #10943 — the undeclared fallback resolves from the CALLER, not from + * Commit 46d34ab7c — the undeclared fallback resolves from the CALLER, not from * `@objectstack/types`. * - * The card's own 4-row matrix, measured on `main` from an app declaring + * The 4-row matrix behind that commit, measured on `main` from an app declaring * nothing, is what these cases pin: * * via host importer bare import() from packages/cli @@ -591,7 +591,7 @@ describe('the undeclared fallback resolves from the CALLER (#10943)', () => { }); it('the undeclared failure NAMES a missing caller base instead of hiding it', async () => { - // The pre-#10943 default is retained so an out-of-tree caller (cloud's + // The default from before commit 46d34ab7c is retained so an out-of-tree caller (cloud's // loader) cannot break under this parameter's arrival — so the one thing it // must not be is silent. A `MODULE_NOT_FOUND` naming no base is exactly what // let this defect survive being read. @@ -1475,7 +1475,7 @@ describe('an aliased install is verified against the name its DECLARATION names // // ⚠️ This pin has been re-read twice and its reason has moved twice, so it // is spelled out rather than inherited. It asserted the INSTALL wording - // until #15045 (which re-worded, and kept the refusal). #17046 then gave + // until commit 288fe9c34 (which re-worded, and kept the refusal). #17046 then gave // the fallback a SECOND axis — the declared PATH — under which a `link:` // whose key IS the declared directory now loads. This fixture is not that: // `installAs` writes a plain directory at `node_modules/`, while the @@ -1563,7 +1563,7 @@ describe('an aliased install is verified against the name its DECLARATION names }); /** - * ── #15044: the SUCCEEDING leg recognised the package by the DECLARATION KEY ── + * ── Fixed by commit 088f761e5: the SUCCEEDING leg recognised the package by the DECLARATION KEY ─ * * #14278 taught the #14041 FALLBACK finder that `{"foo": "npm:bar@1"}` installs * a package named `bar`. The same blindness survived one leg over, on the path @@ -1878,7 +1878,7 @@ exports.BUILD = 'cjs'; }); /** - * ── #15045: the location sub-case REFUSES correctly and EXPLAINED itself wrongly ─ + * ── Reworded by commit 288fe9c34: the location sub-case REFUSES correctly and EXPLAINED itself wrongly ─ * * #14278 left one sub-case standing on the fallback leg, deliberately and with * a pin: `link:` / `file:` (and a git or tarball URL) name a LOCATION, not a @@ -1907,7 +1907,7 @@ exports.BUILD = 'cjs'; * the declared directory, which is now the shape that LOADS; the wording below * is therefore driven on the residue that still cannot be verified either way, * and each fixture says which residue it is. ⛔ Nothing here was deleted to - * make room: every #15045 assertion survives, on an input that still reaches + * make room: every assertion commit 288fe9c34 wrote survives, on an input that still reaches * the text it pins. The load itself is pinned in the #17046 suite below, next * to the negative controls that keep the refusal. */ @@ -1984,7 +1984,7 @@ describe('a location install whose manifest differs states the LIMIT, not a fals /** * The residue this suite's wording still governs after #17046: a location * declaration whose key is a COPY rather than the declared directory. Both - * axes are measured, both fail, and the message is the one #15045 wrote. + * axes are measured, both fail, and the message is the one commit 288fe9c34 wrote. */ const copiedApp = (tag: string, key: string, specifier: string, manifestName: string): string => linkedApp(tag, key, specifier, manifestName, ESM_ONLY_EXPORTS, 'copy'); @@ -2050,7 +2050,7 @@ describe('a location install whose manifest differs states the LIMIT, not a fals }); it('THE CARD: the git / tarball sentence is on the spelling that HAS no location', async () => { - // #15045 asked for this sentence and pinned it on a `link:` fixture, + // Commit 288fe9c34 wrote this sentence and pinned it on a `link:` fixture, // because at the time every spelling on the list shared one paragraph. // #17046 split the paragraph — a path specifier now gets the location // axis's own reading instead — so the sentence is pinned where it is true. @@ -2074,7 +2074,7 @@ describe('a location install whose manifest differs states the LIMIT, not a fals }); it('NEGATIVE CONTROL: a `link:` install whose manifest MATCHES the key still loads, silently', async () => { - // The load path #15045 must not have moved, and #17046 must not have moved + // The load path commit 288fe9c34 must not have moved, and #17046 must not have moved // either: this one is carried by the NAME axis, which is untouched. const root = linkedApp('control', 'linked', 'link:../elsewhere', 'linked'); expect((await createHostImporter(root)('linked')).BUILD).toBe('linked'); @@ -2157,7 +2157,7 @@ describe('a location install whose manifest differs states the LIMIT, not a fals * `realpath(resolve(hostRoot, ))`, exactly, both sides * canonicalised, no basename matching and no case folding. * - * ⛔ What it is NOT, quoted from #15045's triage because it predicted a dev + * ⛔ What it is NOT, quoted from the triage commit 288fe9c34 landed, because it predicted a dev * would reach for it: *"skip the check when the specifier is a location. That * accepts any directory sitting at the key — the looser finder #4719 and * #14041 exist to prevent — and trades a confidently-wrong remedy for a wrong @@ -2172,7 +2172,7 @@ describe('a location install whose manifest differs states the LIMIT, not a fals * nothing to compare and the refusal stands. * - **the #13330 leg is untouched.** A dual-published `link:` target still * resolves through CommonJS and still keeps its `require` entry — pinned by - * the #15044 BOUNDARY above. Extending there would change a load that + * the BOUNDARY commit 088f761e5 pinned above. Extending there would change a load that * already succeeds; this axis only ever fires inside `hostRequire.resolve`'s * catch, so nothing that loads today changes. * - **case-insensitive filesystems are NOT covered by a test**, and the @@ -2314,7 +2314,7 @@ describe('a correctly LINKED package is verified by the LOCATION its host declar it('`file:` and `portal:` are location protocols too, and verify the same way', async () => { // npm installs a directory `file:` dependency AS a symlink, which is this // shape. (pnpm routes `file:` through its virtual store instead — a copy, - // covered by the negative below and by the #15045 suite's wording pins.) + // covered by the negative below and by the wording pins of commit 288fe9c34's suite.) for (const specifier of ['file:../linked', 'portal:../linked']) { const root = linkFixture(`proto-${specifier.slice(0, 4)}`, 'linked-key', { specifier }); expect((await createHostImporter(root)('linked-key')).BUILD, specifier).toBe('the-linked-directory'); @@ -2416,8 +2416,8 @@ describe('a correctly LINKED package is verified by the LOCATION its host declar it('the load stays inside the FALLBACK — a package with a `require` entry never reaches it', async () => { // The property that makes this strictly additive: the axis fires only in // `hostRequire.resolve`'s catch. A dual-published linked package resolves - // through CommonJS and keeps today's behaviour, which the #15044 BOUNDARY - // above pins from the other side (#13330's leg is deliberately untouched). + // through CommonJS and keeps today's behaviour, which the BOUNDARY commit 088f761e5 + // added above pins from the other side (#13330's leg is deliberately untouched). const root = linkFixture('dual', 'linked-key', { specifier: 'link:../linked', exportsField: { '.': { require: './dist/index.cjs', import: './dist/index.js' } }, diff --git a/packages/types/src/node.ts b/packages/types/src/node.ts index 67bebb32295..2c13223987e 100644 --- a/packages/types/src/node.ts +++ b/packages/types/src/node.ts @@ -43,7 +43,7 @@ * The fix is to resolve from the host app's root and import the resolved * absolute path. The importing package's own resolution stays as the fallback, * for the framework-owned packages it depends on and the host does not declare - * — and since #10943 that fallback is the base the CALLER hands in + * — and since commit 46d34ab7c that fallback is the base the CALLER hands in * ({@link HostImporterOptions.fallbackImport}), because a fallback written here * resolved from `@objectstack/types` and could only ever see * `@objectstack/spec`. Same defect class as the paragraph above, one level up: @@ -293,7 +293,7 @@ export function isDeclaredByHost(specifier: string, hostRoot?: string): boolean * - `declared-unresolvable` — the app declares it and it still would not * resolve. Remedy: fix the INSTALL. Re-reading the manifest is wasted effort. * ⚠️ One sub-case under this kind is NOT an install problem and does not say - * it is (#15045): a `link:` / `file:` (or git / tarball) declaration names a + * it is (commit 288fe9c34): a `link:` / `file:` (or git / tarball) declaration names a * LOCATION rather than a package, so the fallback cannot verify the directory * by NAME. #17046 gave it the second axis — the declared path — so a * correctly linked package now LOADS; what still lands here is the residue @@ -365,7 +365,7 @@ function hostImportError( * ({@link HostImporterOptions.fallbackImport})? When it did not, the fallback * ran from `@objectstack/types`, which sees only `@objectstack/spec` — so the * absence being reported may be an artefact of the missing base rather than a - * real one. #10943 kept that default for out-of-tree callers; saying so here is + * real one. Commit 46d34ab7c kept that default for out-of-tree callers; saying so here is * what stops it being silent, because the alternative is a reader re-deriving * the whole measurement from a `MODULE_NOT_FOUND` that names nothing. */ @@ -632,7 +632,7 @@ const ALIAS_DECLARATION_PROTOCOLS = [ * directory it consults, `/node_modules/`; * - the #13330 succeeding leg ({@link packageRootOf}) recognises the package * root while walking up from the entry the CJS resolver already returned - * (#15044). + * (commit 088f761e5). * * ⚠️ This moves each leg's EXPECTATION, never its strictness. The * manifest-name check is what keeps the fallback strictly tighter than the CJS @@ -657,7 +657,7 @@ const ALIAS_DECLARATION_PROTOCOLS = [ * directory is what gets verified when the name cannot be. On the #13330 leg * the residue is still a load rather than a refusal: a `link:` target whose * manifest names something else keeps today's `require`-condition entry, - * unchanged by #15044 and by #17046, and pinned as such. + * unchanged by commit 088f761e5 and by #17046, and pinned as such. */ function declaredManifestName(declaration: HostDeclaration): string { const { packageName, specifier } = declaration; @@ -675,7 +675,7 @@ function declaredManifestName(declaration: HostDeclaration): string { /** * Declaration value prefixes that name a LOCATION on disk or a REMOTE ARTEFACT - * instead of a package (#15045). + * instead of a package (commit 288fe9c34). * * The complement of {@link ALIAS_DECLARATION_PROTOCOLS} on the axis that * matters to the FALLBACK's diagnostic: an alias protocol names a package, and @@ -715,7 +715,7 @@ const NAMELESS_DECLARATION_PREFIXES = [ /** * Does the host's declaration leave this key's manifest name UNKNOWABLE from - * the declaration alone (#15045)? See {@link NAMELESS_DECLARATION_PREFIXES}. + * the declaration alone (commit 288fe9c34)? See {@link NAMELESS_DECLARATION_PREFIXES}. */ function declarationNamesNoPackage(declaration: HostDeclaration): boolean { const { specifier } = declaration; @@ -740,7 +740,7 @@ function declarationNamesNoPackage(declaration: HostDeclaration): boolean { * * ⚠️ This list exists because the two questions are NOT the same question. * `NAMELESS_…` asks *"does the declaration name a package?"* (a WORDING - * question, #15045); this one asks *"does the declaration name a directory I + * question, commit 288fe9c34); this one asks *"does the declaration name a directory I * can compare against?"* — the question that decides whether a load happens. * Merging them would license `github:acme/bar` to be verified against a path * nobody wrote. @@ -750,7 +750,7 @@ const LOCATION_DECLARATION_PREFIXES = ['link:', 'file:', 'portal:'] as const; /** * What {@link declaredLocationAxis} measured — kept as a record rather than a * boolean because the REFUSAL has to be able to say what it compared, exactly - * as #15045 made the name axis say what it read. + * as commit 288fe9c34 made the name axis say what it read. */ interface DeclaredLocationAxis { /** The declared path, resolved against `hostRoot` — as written, not canonicalised. */ @@ -888,7 +888,7 @@ function declaredLocationAxis( * framework. * * ⚠️ `manifestName` is what {@link declaredManifestName} reads out of the - * host's declaration, NOT the declaration key (#15044). For an aliased install + * host's declaration, NOT the declaration key (commit 088f761e5). For an aliased install * — `{"foo": "npm:bar@1"}` — the realpath this walk climbs is `bar`'s own * package directory, whose manifest is named `bar`; matching the key `foo` * never succeeded, so the caller fell back to the CJS resolver's answer and an @@ -922,7 +922,7 @@ function packageRootOf(resolvedFile: string, manifestName: string): string | und * The file the `import` condition names for `specifier`, or `undefined` when * this seam has nothing to change — see the narrowness list in the #13330 note. * - * ⚠️ The two names here are different questions and only look alike (#15044). + * ⚠️ The two names here are different questions and only look alike (commit 088f761e5). * The package ROOT is recognised by the name the DECLARATION promises * ({@link declaredManifestName}); the exports SUBPATH is cut from the * declaration KEY, because the key is what the specifier is spelled with — @@ -1002,7 +1002,7 @@ function esmEntryForDeclared( * asks neither question, which is what "strictly tighter" means here. * * `import.meta.resolve` with a parent URL is NOT the mechanism, on the same - * measurement the #10943 note below records: without + * measurement the note below records for commit 46d34ab7c: without * `--experimental-import-meta-resolve` the parent argument is SILENTLY * IGNORED, so it answers from the WRONG base with full confidence — the exact * failure class this card removes. @@ -1029,7 +1029,7 @@ type DeclaredCjsResolveFallback = | { outcome: 'absent' } /** * Present at the key, holding a package named something ELSE, under a - * declaration that names no package to expect (#15045) — and, when that + * declaration that names no package to expect (commit 288fe9c34) — and, when that * declaration DID name a directory, not that directory either (#17046). * Refused exactly as `absent` is — same kind, same throw — but it is a * different measurement and gets its own wording: nothing about the install @@ -1099,8 +1099,8 @@ function hasInvalidExportsSubpathSegments(subpath: string): boolean { * * ⚠️ Absent and PRESENT-BUT-NAMED-OTHERWISE both answer `undefined` to the * check that consults it, which is correct — neither is the declared package's - * install. They are different FACTS about the app, though, and #15045 is the - * card about telling an operator which one was measured. + * install. They are different FACTS about the app, though, and commit 288fe9c34 is the + * change that tells an operator which one was measured. */ function manifestNameAt(dir: string): string | undefined { try { @@ -1148,7 +1148,7 @@ function hostNodeModulesEntry(declaration: HostDeclaration): string { function hostInstalledPackageDir(declaration: HostDeclaration): string | undefined { const linked = hostNodeModulesEntry(declaration); // Unreadable, unparseable, or named something else — all `undefined`, exactly - // as before #15045; the CALLER is what now distinguishes them, and only to + // as before commit 288fe9c34; the CALLER is what now distinguishes them, and only to // pick the wording. const namedAsDeclared = manifestNameAt(linked) === declaredManifestName(declaration); if (!namedAsDeclared && declaredLocationAxis(declaration, linked)?.verified !== true) { @@ -1173,7 +1173,7 @@ function declaredCjsResolveFallback( const { packageName } = declaration; const packageDir = hostInstalledPackageDir(declaration); if (packageDir === undefined) { - // #15045: the finder has REFUSED. Re-read the one directory it consulted so + // Commit 288fe9c34: the finder has REFUSED. Re-read the one directory it consulted so // the failure can say which of the two absences it measured. A cold error // path that was already about to build a multi-line message, so the second // read costs nothing anyone can observe. @@ -1239,11 +1239,11 @@ function declaredCjsResolveFallback( /** * The wording for {@link DeclaredCjsResolveFallback} `unverifiable-location` - * (#15045) — a `link:` / `file:` (or git / tarball) install whose linked + * (commit 288fe9c34) — a `link:` / `file:` (or git / tarball) install whose linked * manifest names something other than the key, and which #17046's location * axis could not tie to the declaration either. * - * The refusal it explains is deliberate; what #15045 changed is that it no + * The refusal it explains is deliberate; what commit 288fe9c34 changed is that it no * longer prescribes {@link unresolvableMessage}'s remedies, every one of which * is measurably false here: the package IS on disk, so it was neither "never * installed" nor pruned away, and its `import` target exists. An operator @@ -1258,7 +1258,7 @@ function declaredCjsResolveFallback( * compared and came back DIFFERENT — pnpm's `file:` virtual-store copy being * the measured example. Both facts are now stated rather than assumed, because * a message asserting a limit the finder no longer has is the same defect - * #15045 removed. + * commit 288fe9c34 removed. * * The closing remedy is one fact stated from both ends, and it was MEASURED, * not reasoned: make the key and the linked manifest's `name` agree — rename @@ -1378,7 +1378,7 @@ function noLoadableEntryMessage( * surface; a package that RESOLVES and then throws while evaluating is a * genuine crash and propagates untouched, as before. * - * ── The caller supplies that base, and why it is a FUNCTION (#10943) ───────── + * ── The caller supplies that base, and why it is a FUNCTION (commit 46d34ab7c) ─ * * Step 3 said "the importing package's own resolution" long before anything * made it true. The fallback was a bare `import()` written HERE, and ESM @@ -1425,8 +1425,8 @@ function noLoadableEntryMessage( * because a `NodeRequire` cannot be asked where it was anchored and the manifest * has to be read from there. * @param options {@link HostImporterOptions.fallbackImport} carries the caller's - * resolution base. Omitting it keeps the pre-#10943 behaviour (this package's - * own resolution) so no out-of-tree caller changes under its feet. + * resolution base. Omitting it keeps the behaviour before commit 46d34ab7c + * (this package's own resolution) so no out-of-tree caller changes under its feet. */ export function createHostImporter( hostRoot: string = process.cwd(), @@ -1440,16 +1440,16 @@ export function createHostImporter( // Not a bare package name (a path, a URL, a `node:` builtin) — nothing a // manifest could declare. Hand it to the normal resolver untouched. // - // ⚠️ Deliberately NOT re-based onto `fallbackImport` (#10943). Every + // ⚠️ Deliberately NOT re-based onto `fallbackImport` (commit 46d34ab7c). Every // base-INDEPENDENT spelling here — `file://`, `node:`, `data:`, an absolute // path — means the same module whoever imports it, so the base is not a // question they can even ask. The one spelling it WOULD move is a RELATIVE - // one, and where that should resolve from is an open policy question owned - // by #10944 (`serve` refuses a relative `plugins: [...]` entry rather than + // one, and where that should resolve from is the policy question commit e598b1cbc + // settled for `serve` (it refuses a relative `plugins: [...]` entry rather than // silently re-basing it) — with a measured consumer count of zero here: // `serve` handles non-package specifiers before this helper is reached, and // `bootStack` / the dogfood probe pass package names only. Answering half - // of another card's undecided question, for nobody, is not a repair. + // of another change's question, for nobody, is not a repair. if (packageNameFromSpecifier(pkg) === undefined) { return import(/* webpackIgnore: true */ pkg); } @@ -1471,9 +1471,9 @@ export function createHostImporter( return import(pathToFileURL(fallback.entry).href); } if (fallback.outcome === 'unverifiable-location') { - // #15045: the SAME kind and the SAME throw as every other unrescued + // Commit 288fe9c34: the SAME kind and the SAME throw as every other unrescued // outcome below — this branch decides WORDING only. Turning this into - // a load is the second verification axis the card holds open, and is + // a load is the second verification axis that commit left unbuilt, and is // a contract change, not a diagnostic one. throw hostImportError( 'declared-unresolvable', @@ -1504,7 +1504,7 @@ export function createHostImporter( // which entry an `import()` gets, so the caller's ESM chain and this // load share one instance of everything the package brings with it. // - // #15044: the whole DECLARATION goes in, not just the key. Recognising + // Commit 088f761e5: the whole DECLARATION goes in, not just the key. Recognising // the package root by the key made an aliased install unrecognisable to // its own re-decision — the walk failed, the `?? resolved` here caught // it, and the load silently stayed on the `require` build #13330 exists diff --git a/packages/types/src/response-envelope.test.ts b/packages/types/src/response-envelope.test.ts index 606522cf416..545c871d43f 100644 --- a/packages/types/src/response-envelope.test.ts +++ b/packages/types/src/response-envelope.test.ts @@ -247,7 +247,7 @@ describe('sendError — the `declaredCode` open channel', () => { }); /** - * The #9934 user-facing marking on the NESTED envelope (maintainer ruling + * Commit 79c46da90's user-facing marking on the NESTED envelope (maintainer ruling * 2026-08-19 on objectui#5210, option 1). * * `ApiErrorSchema` declares `userMessage` — the text a producer marked AT THROW diff --git a/packages/types/src/response-envelope.ts b/packages/types/src/response-envelope.ts index 6838a6a0141..40af54b0696 100644 --- a/packages/types/src/response-envelope.ts +++ b/packages/types/src/response-envelope.ts @@ -161,7 +161,7 @@ export function sendOk(res: EnvelopeResponse, data: unknown, status = 200): void * * ## `userMessage` — the second declared channel, and why this `Pick` stays explicit * - * #9934's producer-side opt-in (maintainer ruling 2026-08-19 on objectui#5210, + * Commit 79c46da90's producer-side opt-in (maintainer ruling 2026-08-19 on objectui#5210, * option 1) declares `ApiError.userMessage`: the text a producer marked, AT * THROW TIME, as addressed to the END USER. Presence IS the marking — a * consumer that sees the field renders it verbatim and keeps its generic diff --git a/packages/types/src/thrown-http-error.test.ts b/packages/types/src/thrown-http-error.test.ts index dde2b17dda2..110eed29b58 100644 --- a/packages/types/src/thrown-http-error.test.ts +++ b/packages/types/src/thrown-http-error.test.ts @@ -1,6 +1,6 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. // -// [#9934] `declaredUserMessage` — the ONE read for "did the producer mark this +// [commit 79c46da90] `declaredUserMessage` — the ONE read for "did the producer mark this // refusal's message user-facing?", and the resolver limb that carries it. // // The marking is the producer-side opt-in the objectui#5210 ruling asked for: diff --git a/packages/types/src/thrown-http-error.ts b/packages/types/src/thrown-http-error.ts index df27e00d340..ad4842f44bc 100644 --- a/packages/types/src/thrown-http-error.ts +++ b/packages/types/src/thrown-http-error.ts @@ -151,7 +151,7 @@ export interface ThrownHttpError { message: string; /** * The producer's user-facing refusal text, verbatim — present exactly when - * the throw carried a non-empty string `userMessage` (#9934). + * the throw carried a non-empty string `userMessage` (commit 79c46da90). * * This is the producer-side opt-in the objectui#5210 ruling asked for * (maintainer, 2026-08-19, option 1): an application hook's refusal has no @@ -255,7 +255,7 @@ export function resolveThrownHttpError(error: unknown, fallbackStatus = 500): Th /** * The user-facing refusal text a thrown error DECLARED, or `undefined` when it - * declared none (#9934). See {@link ThrownHttpError.userMessage} for what the + * declared none (commit 79c46da90). See {@link ThrownHttpError.userMessage} for what the * declaration means and why it is a text-carrying field rather than a flag. * * The ONE read every boundary applies — the REST classification door, the @@ -312,11 +312,11 @@ export function declaredUserMessage(error: unknown): string | undefined { * heuristic misses — the ceiling `sendThrownError`'s note records. The 5xx * sanitisation REGIME is the condition, not one of its two outcomes. * - * ⭐ #12281 — the prose axis of the same 2026-08-27 ruling — is the - * `'declared'` limb of this same function: the dispatcher door withholds the - * message of EVERY declared 5xx, aligning to `/data`. It is a separate card - * with its own measurement-first step, so nothing here applies it; this - * function is the shape it will read rather than a second copy it would have + * ⭐ Commit 0783d7b80 — the prose axis of the same 2026-08-27 ruling — reads + * the `'declared'` limb of this same function: the dispatcher door withholds + * the message of EVERY declared 5xx, aligning to `/data`. It landed separately, + * after its own measurement-first step, so nothing here applies it; this + * function is the shape it reads rather than a second copy it would have had * to grow. */ export type ServerFaultProvenance = 'declared' | 'undeclared'; diff --git a/packages/types/src/unique-violation.test.ts b/packages/types/src/unique-violation.test.ts index 933400f23b6..305a1b64aa3 100644 --- a/packages/types/src/unique-violation.test.ts +++ b/packages/types/src/unique-violation.test.ts @@ -45,7 +45,7 @@ describe('isUniqueViolationError — input shapes', () => { }); /** - * [#13197] The platform's OWN registered code, on the `code` channel. + * [commit 56c093c4d] The platform's OWN registered code, on the `code` channel. * * Not a dialect and not a heuristic — `UNIQUE_VIOLATION` is the value * `error-code-ledger.zod.ts` registers for this exact condition and the one @@ -74,7 +74,7 @@ describe('isUniqueViolationError — input shapes', () => { }); /** - * [#13197] The column question is answered `undefined` for that refusal, + * [commit 56c093c4d] The column question is answered `undefined` for that refusal, * and that is the CORRECT answer rather than a gap: the driver names no * column in a dialect spelling this module parses, and inventing one would * mean imitating SQLite or Postgres prose. `undefined` is the documented diff --git a/packages/types/src/unique-violation.ts b/packages/types/src/unique-violation.ts index 1e63ff6b569..8d54c193666 100644 --- a/packages/types/src/unique-violation.ts +++ b/packages/types/src/unique-violation.ts @@ -119,12 +119,12 @@ interface UniqueViolationSignature { * (from `service-messaging`). * - `1062` — the same MySQL condition on the channel mysql2 *also* sets. The * one addition, and not a new dialect: `@objectstack/metadata`'s - * `driver-error-classification.ts` (this package since #13279; it was + * `driver-error-classification.ts` (this package since commit 6a180e42d; it was * `metadata/src/utils/schema-sync-errors.ts`) already reads `errno` * alongside `code` for exactly * these drivers, so a code-only read is a known gap rather than a decision. * - `UNIQUE_VIOLATION` — the PLATFORM's own registered code - * (`error-code-ledger.zod.ts`), added by #13197 when `driver-memory` grew + * (`error-code-ledger.zod.ts`), added by commit 56c093c4d when `driver-memory` grew * field-level uniqueness. It is not a dialect and not a heuristic: it is * the value the platform already uses to MEAN "unique violation", so a * limb reading it is a tautology, with none of the false-positive risk the @@ -189,7 +189,7 @@ interface UniqueViolationSignature { * path. A dialect added later needs its violation spelling added HERE, measured * off a thrown error — not a loosened limb. * - * ## Why an in-process driver's refusal had to be recognised here (#13197) + * ## Why an in-process driver's refusal had to be recognised here (commit 56c093c4d) * * A driver that raises a conflict this predicate does not recognise is not * merely "less well mapped" — it WEDGES the engine's autonumber resync. @@ -197,7 +197,7 @@ interface UniqueViolationSignature { * the store and re-issues only when `isUniqueViolationError` says the rejection * was a conflict; when it says no, the error propagates with the counter still * warm, so the next insert collides too, one number at a time — #5495's PROBE3 - * storm, which that branch exists to eliminate. Before #13197 `driver-memory` + * storm, which that branch exists to eliminate. Before commit 56c093c4d `driver-memory` * enforced no uniqueness at all and the question never arose; the moment it * refuses a duplicate, an unrecognised refusal would trade a silent duplicate * for a non-converging insert loop. Recognising the platform's own code is what