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