From 9d6a0a8d61030bb7d3ec94e919204254f6ebf628 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 1 Oct 2026 23:10:16 +0000 Subject: [PATCH 1/2] docs(objectql): re-anchor the dead tracker citations in comments to the commits and ADRs that decided them Comment and docblock prose only, in packages/objectql: every site citing a tracker number that answers 404 now cites an object this repository controls (ruling C+D, form C), an ADR where one records the decision, otherwise the commit that made it. Each file keeps its line count; no code token, string literal or live citation moves. Claude-Session: https://claude.ai/code/session_017xfMoEjKUuSh2xYB8sCozp Co-authored-by: Claude --- .../objectql/src/action-activation.test.ts | 2 +- packages/objectql/src/action-activation.ts | 2 +- .../action-governance-keyed-identity.test.ts | 2 +- packages/objectql/src/action-governance.ts | 18 +-- .../action-owner-key-single-source.test.ts | 8 +- .../adr0104-file-columns-moved-supply.test.ts | 2 +- .../src/core-boundary.ratchet.test.ts | 2 +- .../src/driver-fault-redaction.test.ts | 10 +- .../objectql/src/driver-fault-redaction.ts | 24 ++-- .../objectql/src/duplicate-record-error.ts | 6 +- .../src/engine-author-state-query.test.ts | 10 +- .../src/engine-autonumber-resync.test.ts | 16 +-- .../src/engine-cascade-delete.test.ts | 4 +- .../src/engine-file-hydrate-outage.test.ts | 6 +- .../objectql/src/engine-filter-alias.test.ts | 2 +- .../src/engine-filter-array-lowering.test.ts | 4 +- ...ngine-find-missing-table-log-level.test.ts | 2 +- .../engine-insert-duplicate-record.test.ts | 4 +- .../src/engine-kind-registration-log.test.ts | 2 +- .../engine-post-hook-undeclared-field.test.ts | 2 +- .../src/engine-readonly-hook-input.test.ts | 2 +- ...ngine-readonly-when-derived-writes.test.ts | 2 +- .../src/engine-seed-required-deferral.test.ts | 8 +- .../engine-undeclared-update-field.test.ts | 2 +- .../engine-update-duplicate-record.test.ts | 4 +- packages/objectql/src/engine.test.ts | 2 +- packages/objectql/src/engine.ts | 120 +++++++++--------- .../objectql/src/find-hook-result-shape.ts | 2 +- .../objectql/src/hook-exclude-objects.test.ts | 12 +- .../src/hook-withheld-readonly-fault.test.ts | 2 +- .../src/hook-withheld-readonly-fault.ts | 4 +- .../objectql/src/in-memory-aggregation.ts | 2 +- .../src/lifecycle/lifecycle-service.test.ts | 10 +- .../src/lifecycle/lifecycle-service.ts | 30 ++--- packages/objectql/src/metadata-facade.test.ts | 8 +- packages/objectql/src/metadata-facade.ts | 6 +- ...data-service-getobject-equivalence.test.ts | 10 +- ...data-service-roundtrip-conformance.test.ts | 6 +- .../src/metadata-validation-sweep.test.ts | 4 +- .../objectql/src/overlay-precedence.test.ts | 2 +- .../plugin-governance-scoped-metadata.test.ts | 2 +- packages/objectql/src/plugin.ts | 6 +- packages/objectql/src/protocol-meta.test.ts | 40 +++--- ...protocol-org-overlay-registry-gate.test.ts | 2 +- .../src/protocol-recorded-by-null.test.ts | 2 +- .../src/protocol-registry-shadow.test.ts | 4 +- .../src/query-expression-conformance.test.ts | 8 +- .../src/register-object-authored-shape.pin.ts | 2 +- .../registry-artifact-co-ownership.test.ts | 2 +- ...egistry-cross-package-item-classes.test.ts | 2 +- .../registry-namespace-install-gate.test.ts | 2 +- ...egistry-ownership-refusal-envelope.test.ts | 2 +- packages/objectql/src/registry.ts | 22 ++-- ...scoped-repository-return-narrowing.test.ts | 6 +- ...panion-read-projection-conformance.test.ts | 2 +- .../objectql/src/search-companion.test.ts | 2 +- packages/objectql/src/search-companion.ts | 8 +- ...ema-sync-registers-object-metadata.test.ts | 4 +- .../src/sys-metadata-repository.test.ts | 4 +- .../src/system-write-organization.test.ts | 4 +- .../tenancy-by-object-classification.test.ts | 6 +- .../src/tenancy/platform-object-tenancy.ts | 16 +-- .../src/tenancy/system-write-organization.ts | 2 +- packages/objectql/src/validate-only.test.ts | 2 +- .../objectql/src/validation/rule-validator.ts | 2 +- ...ontainer-divergent-name-registrars.test.ts | 28 ++-- packages/objectql/vitest.config.ts | 2 +- 67 files changed, 275 insertions(+), 275 deletions(-) diff --git a/packages/objectql/src/action-activation.test.ts b/packages/objectql/src/action-activation.test.ts index 4234a40ce91..19147605586 100644 --- a/packages/objectql/src/action-activation.test.ts +++ b/packages/objectql/src/action-activation.test.ts @@ -20,7 +20,7 @@ // would switch off an entire installation's actions on its first boot. // 4. **The write is durable BEFORE it is local.** A store that throws must // leave the projection untouched, or the engine reports an activation state -// the ledger does not carry — the #10243 shape with persistence bolted on, +// the ledger does not carry — the env-wide toggle leak's shape with persistence bolted on, // which ADR-0126 §7.2 exists to remove. // 5. **Survives re-registration**, which is the in-process half of "survives a // restart": `resyncAuthoredActions` re-registers handlers on every diff --git a/packages/objectql/src/action-activation.ts b/packages/objectql/src/action-activation.ts index 851cfe2ee1a..1eb59976a8a 100644 --- a/packages/objectql/src/action-activation.ts +++ b/packages/objectql/src/action-activation.ts @@ -182,7 +182,7 @@ export class ObjectStoreActionActivationStore extends ObjectStoreMetadataActivat * written from exactly two places — {@link hydrate} (boot, from the ledger) and * {@link setActive} (which writes the durable row FIRST and updates the set only * after that write returns) — so it cannot drift into being an independent, - * process-local off-switch, which is the #10243 mechanism ADR-0126 retires. + * process-local off-switch, which is the env-wide toggle leak's mechanism ADR-0126 §7.2 retires. * * ⚠️ It is deliberately NOT re-read per `metadata:reloaded`: a reload * re-registers HANDLERS, and a re-registered handler must stay disabled. The diff --git a/packages/objectql/src/action-governance-keyed-identity.test.ts b/packages/objectql/src/action-governance-keyed-identity.test.ts index f12ae432703..e002d308c36 100644 --- a/packages/objectql/src/action-governance-keyed-identity.test.ts +++ b/packages/objectql/src/action-governance-keyed-identity.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * #14423 — the audit and the router, defined on ONE identity and ONE set of + * Commit a56baa2bd — the audit and the router, defined on ONE identity and ONE set of * sources. * * --------------------------------------------------------------------------- diff --git a/packages/objectql/src/action-governance.ts b/packages/objectql/src/action-governance.ts index 720a6fa15ca..b33652b57e9 100644 --- a/packages/objectql/src/action-governance.ts +++ b/packages/objectql/src/action-governance.ts @@ -45,7 +45,7 @@ * undeclared only when EVERY source the router resolves through answered * nothing for it. * - * [#14423] EXISTENCE is settled now too, on both halves of the D5 bijection + * [commit a56baa2bd] EXISTENCE is settled now too, on both halves of the D5 bijection * and in both of the ways the two sides could disagree: * * - IDENTITY — the metadata plane is read KEYED @@ -264,7 +264,7 @@ export function reconcileActionRegistrations( /** * One declaration the engine can dispatch against. * - * ## [#14423] `storeKey` — the identity a body is not required to carry + * ## [commit a56baa2bd] `storeKey` — the identity a body is not required to carry * * `action` is the declaration BODY, exactly as its source hands it over. * `storeKey` is the key the metadata plane holds that body under, present @@ -317,7 +317,7 @@ export interface GovernanceLogger { * with the object-embedded copy winning, mirroring the execution layer's * artifact-wins rule. * - * ## [#14423] Two spellings for the metadata source, and why the keyed one wins + * ## [commit a56baa2bd] Two spellings for the metadata source, and why the keyed one wins * * `loadStandaloneActionsKeyed` reads the plane under the identity the STORE * holds each row by (`MetadataManager.loadManyKeyed`); `loadStandaloneActions` @@ -336,7 +336,7 @@ export interface GovernanceLogger { * So when the keyed source is present it REPLACES the unkeyed one — they read * the same population, and reading both would only re-admit the guess. The * unkeyed parameter stays for callers that have no keyed read to offer; it is - * the pre-#14423 behaviour verbatim, nameless rows dropped and all. + * the behaviour before commit a56baa2bd, verbatim, nameless rows dropped and all. */ export async function collectEngineActionDeclarations( objects: any[], @@ -394,7 +394,7 @@ export async function collectEngineActionDeclarations( /** * The router's BY-NAME rungs, applied to the handlers the declaration set did - * not cover — `registry.getItem('action', )` (rung 2) and, since #14423, + * not cover — `registry.getItem('action', )` (rung 2) and, since commit a56baa2bd, * `meta.loadDiagnosed('action', )` / `meta.load(…)` (rung 3) — each * accepted on the router's own ownership test. * @@ -403,7 +403,7 @@ export async function collectEngineActionDeclarations( * The router never enumerates either source: it asks for ONE name. Mirroring * it means asking for one name. And enumeration is not a substitute here even * where it exists — a plural read and a by-name read of the same plane can - * disagree, which is the whole subject of #14423: one loader fault is + * disagree, which is the whole subject of the card commit a56baa2bd closed: one loader fault is * swallowed by the plural read and served by the by-name read, so a handler * whose declaration lives on the faulted loader reads "undeclared" from the * enumeration alone. The keyed enumeration closes the IDENTITY half of that @@ -474,7 +474,7 @@ function fingerprint(r: ReturnType): string * (`metadata:reloaded` re-runs this; a re-sync that changed nothing should * not repeat the same warning). * - * ## [#14423] Both halves of the bijection read what the router reads + * ## [commit a56baa2bd] Both halves of the bijection read what the router reads * * The two findings used to stand on different sources, which is how the audit * could contradict the router about whether a declaration exists: @@ -522,7 +522,7 @@ export async function runActionGovernanceInventory(args: { */ loadStandaloneActions?: () => Promise; /** - * [#14423] The metadata plane's `action` rows KEYED by the store's own key + * [commit a56baa2bd] The metadata plane's `action` rows KEYED by the store's own key * (`meta.loadManyKeyed('action')`). This is the source the declaration * half of the bijection is defined on, so that the audit and the router * share ONE identity — the store key (#14205) — instead of the audit @@ -538,7 +538,7 @@ export async function runActionGovernanceInventory(args: { */ lookupRegistryAction?: (actionName: string) => unknown; /** - * [#14423] The router's rung 3, injected the same way: + * [commit a56baa2bd] The router's rung 3, injected the same way: * `meta.loadDiagnosed('action', name)?.data`, falling back to * `meta.load('action', name)` — the caller unwraps, so this returns the * declaration or nothing, exactly like {@link lookupRegistryAction}. diff --git a/packages/objectql/src/action-owner-key-single-source.test.ts b/packages/objectql/src/action-owner-key-single-source.test.ts index e965ad6ad2d..da94fd6f554 100644 --- a/packages/objectql/src/action-owner-key-single-source.test.ts +++ b/packages/objectql/src/action-owner-key-single-source.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * This package spells the standalone-action owner-key ladder ONCE (#14422). + * This package spells the standalone-action owner-key ladder ONCE (commit dc7c226b9). * * `ObjectQLPlugin` carried a private `actionObjectKey` that repeated * {@link standaloneActionOwnerKey}'s three rungs, and the only thing holding @@ -73,7 +73,7 @@ describe('standalone-action owner key — one spelling in @objectstack/objectql expect(plugin, 'plugin.ts is missing from the scan').toBeDefined(); // The negative that used to live here — "plugin.ts does not name the // deleted member" — moved to the TREE-scoped section at the bottom of - // this file (#14878). Its scope was the defect, not its subject. What + // this file (commit 29db3cd2a). Its scope was the defect, not its subject. What // stays here is the positive half: the plugin still derives owner keys, // it just does it through the canonical helper now. expect(plugin!.text).toContain('standaloneActionOwnerKey('); @@ -95,7 +95,7 @@ describe('standalone-action owner key — one spelling in @objectstack/objectql }); /** - * ── [#14878] The absence assertion is TREE-scoped, not FILE-scoped ────────── + * ── [commit 29db3cd2a] The absence assertion is TREE-scoped, not FILE-scoped ────────── * * The negative that used to sit in the plugin test above read `plugin.ts` and * nothing else, and THAT SCOPE was the defect. A pin written by the deleting PR @@ -165,7 +165,7 @@ describe('standalone-action owner key — one spelling in @objectstack/objectql */ /** - * The member PR #14667 deleted from `ObjectQLPlugin`. Held as DATA: naming a + * The member commit dc7c226b9 deleted from `ObjectQLPlugin`. Held as DATA: naming a * symbol in a string cannot resurrect it, and this file is excluded from its own * scan precisely so it may carry the name. */ diff --git a/packages/objectql/src/adr0104-file-columns-moved-supply.test.ts b/packages/objectql/src/adr0104-file-columns-moved-supply.test.ts index f5a88f7db1f..0bc05bfafd7 100644 --- a/packages/objectql/src/adr0104-file-columns-moved-supply.test.ts +++ b/packages/objectql/src/adr0104-file-columns-moved-supply.test.ts @@ -2,7 +2,7 @@ /** * [#15989] The kernel→driver supply seam for the ADR-0104 media arm, from the - * ENGINE's side — the ruling on #15041 step 2, as amended by the director + * ENGINE's side — sequencing step 2 of ADR-0104's 2026-09-05 addendum, as amended by the director * ruling (decision batch #120 item 1). * * The driver has accepted `SqlDriverConfig.fileColumnsMoved` since PR #17403, diff --git a/packages/objectql/src/core-boundary.ratchet.test.ts b/packages/objectql/src/core-boundary.ratchet.test.ts index 4723601872b..c2e64ecfe37 100644 --- a/packages/objectql/src/core-boundary.ratchet.test.ts +++ b/packages/objectql/src/core-boundary.ratchet.test.ts @@ -49,7 +49,7 @@ // What this file does NOT see, and what does (#15347) // // This is a SOURCE SCAN over two hard-coded names. Both limits are by -// construction, and #14680 is what they cost: a heavyweight arriving through +// construction, and the leak commit 3bd9b3498 closed is what they cost: a heavyweight arriving through // any other specifier is outside FORBIDDEN_PACKAGES, and a scan of this // package's own sources cannot follow one that arrives three packages deep — // which is how that one arrived, invisible to every gate for the whole time it diff --git a/packages/objectql/src/driver-fault-redaction.test.ts b/packages/objectql/src/driver-fault-redaction.test.ts index 3b47198b7e8..1b41453fdc3 100644 --- a/packages/objectql/src/driver-fault-redaction.test.ts +++ b/packages/objectql/src/driver-fault-redaction.test.ts @@ -106,7 +106,7 @@ describe('redactStatementFromMessage', () => { }); }); -// #8823 — the tail is kept because it names IDENTIFIERS, and on MySQL's +// Commit 4dfa369a9 — the tail is kept because it names IDENTIFIERS, and on MySQL's // duplicate-entry family it does not: `ER_DUP_ENTRY` prints the conflicting // VALUE in the diagnostic itself. These cases pin both halves of the remedy — // the value goes, the index name stays — because a fix that blanked the tail @@ -136,7 +136,7 @@ describe('#8823 — a caller value inlined in the diagnostic itself', () => { }); it('redacts a BARE diagnostic too — the shape that reaches us without a statement', () => { - // Before #9030 the shared leak predicate did not recognise this phrasing, + // Before commit 27a567dd8 the shared leak predicate did not recognise this phrasing, // so a bare `Duplicate entry …` was turned away at the door and kept its // value. That limb landed for a different reason; the two compose here. const out = redactStatementFromMessage(`Duplicate entry '${EMAIL}' for key 'crm_account.email'`); @@ -284,7 +284,7 @@ describe('#9160 — the value-bearing families the live probe measured', () => { }); describe('postgres invalid_text_representation (22P02) / invalid_datetime_format (22007)', () => { - // ⛔ The family the #8823 note was waiting for. Postgres' UNIQUE violation is + // ⛔ The family the commit 4dfa369a9 note was waiting for. Postgres' UNIQUE violation is // saved only because its value sits on `error.detail`, which // `ObjectLogger.write` never serializes — "coincidence, not a defence". This // family puts the caller's value on `error.message`, which IS serialized, so @@ -761,7 +761,7 @@ describe('#8682 half B — the write-path loggers', () => { } /** - * The one driver double in this file. #8823 needed a MySQL-shaped fault and + * The one driver double in this file. Commit 4dfa369a9 needed a MySQL-shaped fault and * the shape is a PARAMETER rather than a second double — one fake engine per * file keeps the contract the double implements reviewable in one place. */ @@ -864,7 +864,7 @@ describe('#8682 half B — the write-path loggers', () => { }); /** - * [#8823] The same write path, with the fault MySQL raises instead — where + * [commit 4dfa369a9] The same write path, with the fault MySQL raises instead — where * the caller's value is in the DIAGNOSTIC and not only in the statement, so * the statement cut alone never reached it. */ diff --git a/packages/objectql/src/driver-fault-redaction.ts b/packages/objectql/src/driver-fault-redaction.ts index 7b1728e8e31..9594cdd593c 100644 --- a/packages/objectql/src/driver-fault-redaction.ts +++ b/packages/objectql/src/driver-fault-redaction.ts @@ -44,7 +44,7 @@ * Nothing else about it moved: the same redacted `message`/`stack` reach the * same `error` key of the same meta bag (`ObjectQL.writeFailureLogMeta`). * - * ## [#8823] …but "the tail names identifiers" is not true of every dialect + * ## [commit 4dfa369a9] …but "the tail names identifiers" is not true of every dialect * * The paragraph above was written with a premise attached: that whatever the * database prints after the separator names IDENTIFIERS — a column, a table, a @@ -60,7 +60,7 @@ * ``` * * Three keep an identifier; the second keeps a caller's value. Measured through - * this function, not predicted — and re-measured byte-identical after #9030 + * this function, not predicted — and re-measured byte-identical after commit 27a567dd8 * taught the shared leak predicate this phrasing, which moves the VERDICT but * not the cut. * @@ -81,7 +81,7 @@ * * ## [#9160] The list is now MEASURED, and there is a way to notice a gap * - * #8823 left one entry and no instrument: nothing measured whether a diagnostic + * Commit 4dfa369a9 left one entry and no instrument: nothing measured whether a diagnostic * a driver produced carried a value, so the next entry needed the same accident * that found the first. `sql-driver-diagnostic-value-probe.test.ts` is that * instrument. It plants a canary value, raises each candidate family against @@ -108,7 +108,7 @@ * ``` * * ¹ on `error.message`. Both put the caller's row on `error.detail`, which - * `ObjectLogger.write` does not serialize — the coincidence #8823 recorded, and + * `ObjectLogger.write` does not serialize — the coincidence commit 4dfa369a9 recorded, and * it is still only a coincidence. **The three Postgres families marked VALUE put * the caller's value on `message`, the field that IS serialized**, so nothing * covers them but the entries below. That was the open question #9160 asked and @@ -140,7 +140,7 @@ * ``` * pg 22P02/22007 value runs to end of message → head-anchored cut (below) * mysql 1292 value runs to end of message → head-anchored cut (below) - * pg 22003 value "…" is out of range … → `tail`, the #8823 mechanism + * pg 22003 value "…" is out of range … → `tail`, the commit 4dfa369a9 mechanism * ``` * * `22003` was assumed unreachable on the reasoning that its value slot holds a @@ -266,11 +266,11 @@ const STATEMENT_SEPARATOR = ' - '; /** What replaces a statement that carried nothing but values. */ const REDACTED_STATEMENT = '[statement and bound values redacted]'; -/** [#8823] What replaces one caller value inlined in the database's own diagnostic. */ +/** [commit 4dfa369a9] What replaces one caller value inlined in the database's own diagnostic. */ const REDACTED_VALUE = '[value redacted]'; /** - * [#8823] MySQL/MariaDB `ER_DUP_ENTRY` (1062), whole: the template's own head, + * [commit 4dfa369a9] MySQL/MariaDB `ER_DUP_ENTRY` (1062), whole: the template's own head, * the conflicting VALUE, and the `for key ` tail that anchors it. * * `Duplicate entry '%-.192s' for key '%-.192s'` — the first slot is whatever the @@ -295,7 +295,7 @@ const REDACTED_VALUE = '[value redacted]'; const DUPLICATE_ENTRY = /(duplicate entry\s+)["'`][\s\S]*["'`](\s+for key\s+["'`][^"'`]+["'`])/gi; /** - * [#8823] The same template with its head already gone — what the statement cut + * [commit 4dfa369a9] The same template with its head already gone — what the statement cut * leaves behind when the conflicting VALUE itself contained ` - `. * * Measured: `insert into … values ('2026 - Q3 plan') - Duplicate entry '2026 - @@ -352,7 +352,7 @@ const MYSQL_INCORRECT_VALUE_TAIL = /'(\s+for column\s+'[^']*'\s+at row\s+\d+)/gi * invalid input syntax for type timestamp with time zone: "CANARY-notadate" * ``` * - * **This is the family the #8823 note was waiting for.** Postgres' unique + * **This is the family the commit 4dfa369a9 note was waiting for.** Postgres' unique * violation is saved only because its value sits on `error.detail`, which * `ObjectLogger.write` does not serialize — recorded there as "coincidence, not * a defence". Here the value is on `error.message`, the field that IS @@ -405,7 +405,7 @@ const PG_VALUE_OUT_OF_RANGE = /(value\s+)"[\s\S]*"(\s+is out of range for type [ * logged: Q3" is out of range for type integer ← `Q3` is caller data * ``` * - * This family keeps its right anchor, so it takes the #8823 recovery and NOT a + * This family keeps its right anchor, so it takes the commit 4dfa369a9 recovery and NOT a * `head`: everything before ` is out of range for type` is value residue by * construction and is dropped whole. ⛔ It must not be given a `head` — its * diagnostic continues past the value, which is exactly the shape the head @@ -678,7 +678,7 @@ export function redactStatementFromMessage(message: string): string { if (!message || !looksLikeInternalErrorLeak(message)) return message; const cut = statementCut(message); // No statement to cut — but a dialect may still have inlined a value in the - // diagnostic itself, and since #9030 taught the shared predicate this + // diagnostic itself, and since commit 27a567dd8 taught the shared predicate this // phrasing, a BARE `Duplicate entry …` now reaches this line instead of // being turned away above. if (cut === -1) return redactDiagnosticValues(message); @@ -716,7 +716,7 @@ function statementCut(message: string): number { } /** - * [#8823] Drop the caller values a dialect inlines into its OWN diagnostic, + * [commit 4dfa369a9] Drop the caller values a dialect inlines into its OWN diagnostic, * keeping every identifier around them. * * Runs on the tail the statement cut already produced, never on the whole diff --git a/packages/objectql/src/duplicate-record-error.ts b/packages/objectql/src/duplicate-record-error.ts index 6b214302e4b..1de209bf13c 100644 --- a/packages/objectql/src/duplicate-record-error.ts +++ b/packages/objectql/src/duplicate-record-error.ts @@ -3,7 +3,7 @@ import { isUniqueViolationError, uniqueViolationColumn } from '@objectstack/types'; /** - * The ADR-0112 envelope `engine.insert` (#14095) and `engine.update` (#14390) + * The ADR-0112 envelope `engine.insert` (#14095) and `engine.update` (commit 9d7f7259f) * raise when a driver refuses a row as a unique-constraint violation. * * ## The defect this retires @@ -36,7 +36,7 @@ import { isUniqueViolationError, uniqueViolationColumn } from '@objectstack/type * caller of `engine.insert` / `engine.update` (a hook, a flow node, a * script holding the engine) branches on, on every driver. ⛔ It is not * the WIRE spelling: every REST route — the single-record door, the - * whole-request bulk / import doors, and since #14723 the per-row reports + * whole-request bulk / import doors, and since commit 65846bc46 the per-row reports * of `POST /data/:object/batch` and the import runner alike — reports a * unique-constraint refusal as `UNIQUE_VIOLATION`, the standard-catalog * member the published protocol docs give for the 409 constraint-violation @@ -134,7 +134,7 @@ function buildDuplicateMessage(object: string, field?: string): string { } /** - * A write door's driver-error exit — `insert` (#14095) and `update` (#14390), + * A write door's driver-error exit — `insert` (#14095) and `update` (commit 9d7f7259f), * by-id and predicate alike: the platform envelope for a unique violation, or * the caller's own error unchanged for anything else. * diff --git a/packages/objectql/src/engine-author-state-query.test.ts b/packages/objectql/src/engine-author-state-query.test.ts index 5d51f4de362..bacdd15d72d 100644 --- a/packages/objectql/src/engine-author-state-query.test.ts +++ b/packages/objectql/src/engine-author-state-query.test.ts @@ -1,18 +1,18 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * #6300 — `find`/`findOne` take the AUTHOR state (`z.input`), and the engine + * Commit 74155c735 — `find`/`findOne` take the AUTHOR state (`z.input`), and the engine * fills the defaults the schemas declare before the AST leaves it. * * ADR-0122's core argument is "the first key an author writes must default * correctly". `engine.find(obj, { orderBy: [{ field: 'updated_at' }] })` is * the natural spelling of "newest-ish first" — and until this card it did not - * compile: #6083 pinned `find`/`findOne` back to `EngineQueryOptionsParsed` + * compile: commit 53068c130 pinned `find`/`findOne` back to `EngineQueryOptionsParsed` * (`z.infer`) because the engine built its `QueryAST` by bare spread and * filled no default, so admitting the author state would have sent * `order: undefined` to the driver. * - * The measured driver-side status quo (part of #6300's own premise): every + * The measured driver-side status quo (part of commit 74155c735's own premise): every * driver coalesces a missing `order` to `'asc'` — `sql-driver.ts` * (`s.order || 'asc'`), `memory-driver.ts`, `mongodb-driver.ts`, * `mongodb-aggregation.ts`, `remote-transport.ts`. So the filled `'asc'` @@ -150,7 +150,7 @@ describe('find/findOne accept the author state and the engine fills the declared }); // ── (1) The contract flip, pinned by the compiler ──────────────────────── - // Every call in this block is UNCAST. Under #6083's `...Parsed` parameter + // Every call in this block is UNCAST. Under commit 53068c130's `...Parsed` parameter // none of them compiled — `orderBy[].order` was required to write. The // `IDataEngine`-typed alias pins the spec contract, not just the class. @@ -213,7 +213,7 @@ describe('find/findOne accept the author state and the engine fills the declared // ── (4) The schema's strictness rides with its defaulting parse ────────── // These callers bypass the type (`as unknown as EngineQueryOptions` — the // #4918 spelling for a DELIBERATELY off-contract probe), which is the only - // way these shapes can occur. Before #6300 the engine forwarded them + // way these shapes can occur. Before commit 74155c735 the engine forwarded them // verbatim and each driver decided alone: memory honored `direction`, // SQL/Mongo silently dropped it and sorted ascending — one query, two // orders (#4721's class). diff --git a/packages/objectql/src/engine-autonumber-resync.test.ts b/packages/objectql/src/engine-autonumber-resync.test.ts index ef6e196f56e..e19feb9209c 100644 --- a/packages/objectql/src/engine-autonumber-resync.test.ts +++ b/packages/objectql/src/engine-autonumber-resync.test.ts @@ -50,9 +50,9 @@ * * ⚠️ **Both of the two that do can now raise.** driver-mongodb raises a * single-field unique index's `E11000` when the field declares `unique`; since - * #13197 driver-memory refuses a declared-unique collision too, in the ADR-0112 + * commit 56c093c4d driver-memory refuses a declared-unique collision too, in the ADR-0112 * envelope (`code: 'UNIQUE_VIOLATION'`, `status: 409`), with `driver-sql`'s - * ADR-0120 D1/D3 scoping. Until #13197 it never could — `create` was a + * ADR-0120 D1/D3 scoping. Until commit 56c093c4d it never could — `create` was a * `table.push()` storing no constraints at all (#4065) — so a duplicate landed * SILENTLY and this branch was unreachable there. Section (3b) carries the * pin, INVERTED in place rather than deleted, so the change of fact stays @@ -65,7 +65,7 @@ * as `ruled-permanent` («#6664 A, maintainer 2026-08-08 — inherits #5704 * Q2 = B») — "InMemoryDriver declares `supports = {}`, so the ENGINE's * autonumber seeding owns the counter. No SQL backend can stand in". What - * #13197 moved is which store can REJECT, never who issues the number, so that + * commit 56c093c4d moved is which store can REJECT, never who issues the number, so that * ruling is untouched. Section (3b) pins the consequence rather than authoring * a second answer to the same question (#6832's one-contract-two-numbers * shape). Adoption still covers the drift no store can report, and still waits @@ -171,7 +171,7 @@ function matches(row: Row, where: any): boolean { * `uniqueViolationColumn` answers `undefined`. That combination is exactly why * the resync treats an unnamed column as attributable: neither in-repo fallback * driver names a column this predicate can read — MongoDB names the INDEX, and - * driver-memory (since #13197) raises a coded envelope with no dialect prose in + * driver-memory (since commit 56c093c4d) raises a coded envelope with no dialect prose in * it — so demanding a named column would make the resync unreachable on both. */ const mongoDuplicate = (field: string, value: string) => @@ -183,7 +183,7 @@ const mongoDuplicate = (field: string, value: string) => ); /** - * [#13197] `driver-memory`'s duplicate refusal — the ADR-0112 envelope, not a + * [commit 56c093c4d] `driver-memory`'s duplicate refusal — the ADR-0112 envelope, not a * dialect. It carries `code: 'UNIQUE_VIOLATION'` (the platform's own registered * code) and `status: 409`, and names no column in any spelling * `uniqueViolationColumn` parses. So, exactly like the MongoDB shape above, @@ -723,7 +723,7 @@ describe('ObjectQL autonumber resync (#6806)', () => { /* ====================================================================== * * (3b) The collision half is STORAGE-DEPENDENT — name which driver gives * which guarantee, rather than implying one that is not delivered. - * #13197 changed the ANSWER for driver-memory (it constrains now); the + * Commit 56c093c4d changed the ANSWER for driver-memory (it constrains now); the * question, and the duty to answer it by driver name, are unchanged. * ==================================================================== */ @@ -731,7 +731,7 @@ describe('ObjectQL autonumber resync (#6806)', () => { const SCHEMA = schemaWith('doc_no', 'D-{0000}'); it('the duplicate is REFUSED and the number re-issued — it used to land silently', async () => { - // ⚠️ INVERTED IN PLACE by #13197. Until then this test asserted the + // ⚠️ INVERTED IN PLACE by commit 56c093c4d. Until then this test asserted the // DEFECT as correct behaviour — `written.doc_no === 'D-0005'` and // `rows.filter(…D-0005).toHaveLength(2)`, over a comment calling two rows // carrying one business identifier "the honest outcome". It was honest: @@ -750,7 +750,7 @@ describe('ObjectQL autonumber resync (#6806)', () => { // `driver-sql`'s ADR-0120 D1/D3 scoping, and raises the ADR-0112 // envelope `code: 'UNIQUE_VIOLATION'` / `status: 409` — the shape // `memoryDuplicate` below reproduces. `isUniqueViolationError` reads that - // code (#13197 added the limb), so the collision branch is REACHABLE on + // code (commit 56c093c4d added the limb), so the collision branch is REACHABLE on // this driver for the first time: the stale counter is dropped, the // counter re-seeds from the store's real max, and the number is re-issued. // diff --git a/packages/objectql/src/engine-cascade-delete.test.ts b/packages/objectql/src/engine-cascade-delete.test.ts index fe81f59cff8..d259e862b57 100644 --- a/packages/objectql/src/engine-cascade-delete.test.ts +++ b/packages/objectql/src/engine-cascade-delete.test.ts @@ -634,13 +634,13 @@ describe('cascadeDeleteRelations — [#9689] authored set_null on master_detail }); }); -// [#13644] The DECLARED referential-cleanup marker — `HookContext. +// [commit 34ce8e7db] The DECLARED referential-cleanup marker — `HookContext. // referentialFieldClear` — populated on EVERY reference-cleanup write the // engine issues, as the read-only projection of the operation-private // `__referentialFieldClear` the #3023 pin above holds on the envelope. // // Why this pin exists, and why its caller context carries a full identity: the -// filer's corrected measurement (#13644) showed the engine builds the cleanup +// filer's corrected measurement (on the card commit 34ce8e7db closed) showed the engine builds the cleanup // write as `{ ...callerContext, transaction, __referentialFieldClear: true }` // — it INHERITS whatever identity the caller supplied — so on the path a real // request takes (a REST DELETE carrying a userId) `ctx.user`, `ctx.session` diff --git a/packages/objectql/src/engine-file-hydrate-outage.test.ts b/packages/objectql/src/engine-file-hydrate-outage.test.ts index 808cc79cf61..702e9ce49cf 100644 --- a/packages/objectql/src/engine-file-hydrate-outage.test.ts +++ b/packages/objectql/src/engine-file-hydrate-outage.test.ts @@ -18,7 +18,7 @@ * `the generic line separates the two causes but still cannot name the loss` * block below pins why it does not satisfy the acceptance: it describes the * sub-read only — never the parent object, the fields left un-hydrated, or the - * consequence. ⚠️ [#13273] That block was rewritten when the generic frame + * consequence. ⚠️ [commit 3a86a65e7] That block was rewritten when the generic frame * stopped being `error` for every cause: it is `debug` for the benign * "table was never provisioned" class now, and — [#17212], because `find` * rethrows and so tells its caller — `warn` for everything else. @@ -296,7 +296,7 @@ describe('sys_file hydrate read fault — distinguishable from "no file" (#6116) * failed `sys_file` sub-read before rethrowing into this catch. That line is * real and this fix neither removes nor duplicates it. * - * ⚠️ [#13273] What HAS moved since #6116, and why this block was rewritten + * ⚠️ [commit 3a86a65e7] What HAS moved since #6116, and why this block was rewritten * rather than deleted. That generic frame used to be `error` for every cause * — which is what made it useless as a discriminator, and is the sentence * this block used to pin. `engine.ts` now asks `isMissingTableError` and puts @@ -304,7 +304,7 @@ describe('sys_file hydrate read fault — distinguishable from "no file" (#6116) * line. The re-pinned facts below are therefore: * * 1. the generic frame DOES now separate the two causes by channel — the - * benign read reaches `debug` only (#13273's own acceptance, + * benign read reaches `debug` only (commit 3a86a65e7's own acceptance, * re-measured from this file's fake driver), the outage the loud * branch, which is `warn` since [#17212] (`find` rethrows into this * seam's catch, so its caller was told) — and neither reaches `error`; diff --git a/packages/objectql/src/engine-filter-alias.test.ts b/packages/objectql/src/engine-filter-alias.test.ts index 3e7e02a81a8..b993ab04d87 100644 --- a/packages/objectql/src/engine-filter-alias.test.ts +++ b/packages/objectql/src/engine-filter-alias.test.ts @@ -217,7 +217,7 @@ describe('filter → where folds on every engine method (#4346)', () => { const repo = ctx.object('task'); const viaWhere = await repo.findOne({ where: { status: 'done' } }); const viaFilter = await repo.findOne({ filter: { status: 'done' } }); - // [#16786] `repo.findOne` declares `Record | null`, so the + // [commit 5c8f5af50] `repo.findOne` declares `Record | null`, so the // null both spellings could return is asserted away rather than read // through — the same `expect(row).not.toBeNull()` / `row!` idiom this // file already uses above. Under the old `Promise` this pair diff --git a/packages/objectql/src/engine-filter-array-lowering.test.ts b/packages/objectql/src/engine-filter-array-lowering.test.ts index 94f7c641244..9c2bc627b02 100644 --- a/packages/objectql/src/engine-filter-array-lowering.test.ts +++ b/packages/objectql/src/engine-filter-array-lowering.test.ts @@ -42,7 +42,7 @@ import { ObjectQL } from './engine.js'; * (#5285). So a test that hands the engine one has to say so, and * `as unknown as EngineQueryOptions` is how: it names the contract being * bypassed, keeps the rest of the call type-checked, and greps as an - * intentional act — none of which a bare `as any` does. (#6300 flipped the + * intentional act — none of which a bare `as any` does. (Commit 74155c735 flipped the * find/findOne parameter from `EngineQueryOptionsParsed` to the author-state * `EngineQueryOptions`; the cast target follows the contract it names.) * @@ -90,7 +90,7 @@ interface SeenRead { ast: DriverQuery } * signature moves. * * `aggregate` included: the engine reaches it by duck-typing - * (`typeof drv.aggregate === 'function'`, `engine.ts`), and until #14345 the + * (`typeof drv.aggregate === 'function'`, `engine.ts`), and until commit e89fa9233 the * interface did not declare it, so this file carried a local extension for * the one verb. `IDataDriver.aggregate?` now spells the signature the engine * calls, so the double's `aggregate` is checked by the same annotation as diff --git a/packages/objectql/src/engine-find-missing-table-log-level.test.ts b/packages/objectql/src/engine-find-missing-table-log-level.test.ts index 173e606ace0..9d761db15fd 100644 --- a/packages/objectql/src/engine-find-missing-table-log-level.test.ts +++ b/packages/objectql/src/engine-find-missing-table-log-level.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * #13273 — a `find` that failed because the table was never created is not the + * Commit 3a86a65e7 — a `find` that failed because the table was never created is not the * same fact as a `find` that FAILED, and the two must not share a log level. * * ## What was measured, and where diff --git a/packages/objectql/src/engine-insert-duplicate-record.test.ts b/packages/objectql/src/engine-insert-duplicate-record.test.ts index ad3934a5a31..bb810f77971 100644 --- a/packages/objectql/src/engine-insert-duplicate-record.test.ts +++ b/packages/objectql/src/engine-insert-duplicate-record.test.ts @@ -101,7 +101,7 @@ const mysqlDuplicate = () => errno: 1062, }); -/** driver-memory (#13197): already an ADR-0112 envelope, in the platform's own vocabulary. */ +/** driver-memory (commit 56c093c4d): already an ADR-0112 envelope, in the platform's own vocabulary. */ const memoryDuplicate = () => Object.assign( new Error('Unique constraint violated on `doc.email`: a record with that value already exists.'), @@ -264,7 +264,7 @@ describe('engine.insert — a driver unique violation is a DUPLICATE_RECORD enve }); it('normalises a driver that already speaks an envelope — one code, not two', async () => { - // driver-memory raises `UNIQUE_VIOLATION` / 409 (#13197). It is a platform + // driver-memory raises `UNIQUE_VIOLATION` / 409 (commit 56c093c4d). It is a platform // envelope, but it is a DIFFERENT one, so an application branching on the // insert door would still need two spellings. The door answers one. const raw = memoryDuplicate(); diff --git a/packages/objectql/src/engine-kind-registration-log.test.ts b/packages/objectql/src/engine-kind-registration-log.test.ts index c8dede5d31c..81618b754d0 100644 --- a/packages/objectql/src/engine-kind-registration-log.test.ts +++ b/packages/objectql/src/engine-kind-registration-log.test.ts @@ -1,5 +1,5 @@ /** - * [#10729] `contributes.kinds` — the registration site's debug line must name + * [commit 10485009a] `contributes.kinds` — the registration site's debug line must name * fields that EXIST. * * `registerApp()` logs one `'Registered Kind'` line per contributed kind. It diff --git a/packages/objectql/src/engine-post-hook-undeclared-field.test.ts b/packages/objectql/src/engine-post-hook-undeclared-field.test.ts index 31552e297e0..dd224dea854 100644 --- a/packages/objectql/src/engine-post-hook-undeclared-field.test.ts +++ b/packages/objectql/src/engine-post-hook-undeclared-field.test.ts @@ -1,6 +1,6 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. // -// #13657 — the declared-field door's POST-HOOK half. +// Commit b003cf2e8 — the declared-field door's POST-HOOK half. // // #8682 / #8738 put the door in and PR #8737 moved it AHEAD of the `before*` // hooks and ahead of statement construction, so that no work (above all, no diff --git a/packages/objectql/src/engine-readonly-hook-input.test.ts b/packages/objectql/src/engine-readonly-hook-input.test.ts index 81865776994..cadebb3ecad 100644 --- a/packages/objectql/src/engine-readonly-hook-input.test.ts +++ b/packages/objectql/src/engine-readonly-hook-input.test.ts @@ -409,7 +409,7 @@ describe('#16344 — caller-forged readonly values are hidden from beforeUpdate' }); /** - * [#17219] The OTHER half of the same hide pass: what an author is told when a + * [commit 706ad0fcc] The OTHER half of the same hide pass: what an author is told when a * hook reaches THROUGH a key #16344 withheld. * * ⛔ The refusal itself is not under test here and is not moved: a body's diff --git a/packages/objectql/src/engine-readonly-when-derived-writes.test.ts b/packages/objectql/src/engine-readonly-when-derived-writes.test.ts index 5bf7397a447..e4792812735 100644 --- a/packages/objectql/src/engine-readonly-when-derived-writes.test.ts +++ b/packages/objectql/src/engine-readonly-when-derived-writes.test.ts @@ -241,7 +241,7 @@ describe('readonlyWhen strips CALLER-submitted values only (#9107)', () => { // frozen paid-invoice lines). That same blindness would let this exact // line — or a normalisation that is the identity for canonical input — // hand the CALLER's value hook ownership and silently unlock the lock. - // So this seam keeps VALUE EQUALITY, on purpose. Measured on #14472's + // So this seam keeps VALUE EQUALITY, on purpose. Measured on commit 00ff228fe's // branch: threading the record into `isCallerSuppliedValue` turned this // very test red (`closed_note` committed the forgery where the lock had // stripped it to `null`). diff --git a/packages/objectql/src/engine-seed-required-deferral.test.ts b/packages/objectql/src/engine-seed-required-deferral.test.ts index b7dfe02810b..a710be59110 100644 --- a/packages/objectql/src/engine-seed-required-deferral.test.ts +++ b/packages/objectql/src/engine-seed-required-deferral.test.ts @@ -7,7 +7,7 @@ import type { IDataEngine, IMetadataService } from '@objectstack/spec/contracts' /** * Seed deferral vs `required: true` — measured against the REAL engine - * (#11674, the card's "Second, NOT measured" question). + * (the "Second, NOT measured" question on the card commit 9a884c6e4 fixed). * * The seed loader defers an unresolvable reference to pass 2 by DELETING the * column from the row. The seed-loader suite's engine double does not @@ -22,7 +22,7 @@ import type { IDataEngine, IMetadataService } from '@objectstack/spec/contracts' * 1. REQUIRED id half (`sys_approval_request` / `sys_record_share` / * `sys_share_link` shape): the deferred insert — its required `record_id` * deleted — is REJECTED by required-validation. Loud, counted, the row - * never lands, and pass 2 has nothing to write back onto. So #11674's + * never lands, and pass 2 has nothing to write back onto. So commit 9a884c6e4's * internal-id write-back does NOT make these three objects * order-independent: their datasets must still seed the target first. * 2. Same object, target seeded FIRST: the pointer resolves in pass 1, the @@ -32,7 +32,7 @@ import type { IDataEngine, IMetadataService } from '@objectstack/spec/contracts' * 3. OPTIONAL id half (`sys_audit_log` shape), keyless dataset, target * seeded after: pass 1 inserts without the column (nothing requires it), * and pass 2 back-fills through the internal id captured at insert time — - * #11674's fix, holding end-to-end against the engine that really + * commit 9a884c6e4's fix, holding end-to-end against the engine that really * validates. This is what makes `sys_audit_log` genuinely * order-independent while its three required-half siblings are not. */ @@ -136,7 +136,7 @@ function silentLogger() { /** * Every line in the ORDER it was emitted, across levels — which is how the * author reads a seed run, and the only shape in which "the loader said it - * BEFORE the engine did" (#11674's B half) is a measurable claim rather than + * BEFORE the engine did" (commit 1cba33f16, the B half) is a measurable claim rather than * an assertion about two unrelated arrays. */ const lines: Array<{ level: string; message: string }> = []; diff --git a/packages/objectql/src/engine-undeclared-update-field.test.ts b/packages/objectql/src/engine-undeclared-update-field.test.ts index f3bc28a9478..d3e64757bf5 100644 --- a/packages/objectql/src/engine-undeclared-update-field.test.ts +++ b/packages/objectql/src/engine-undeclared-update-field.test.ts @@ -328,7 +328,7 @@ describe('#8738 — the declared-field door on update()', () => { // inject `created_at` / `updated_at` itself and the case would prove // nothing about the door. `id` is the one name the registry does NOT // inject, so it is the door's tolerance being read here, and only its. - // [#13657] `description` is declared alongside `name` because this + // [commit b003cf2e8] `description` is declared alongside `name` because this // harness's own `beforeUpdate` hook STAMPS it (`derived-for-…`), and the // post-hook door now judges the hook's output too. Without the // declaration the fixture would be refused for the hook's key and this diff --git a/packages/objectql/src/engine-update-duplicate-record.test.ts b/packages/objectql/src/engine-update-duplicate-record.test.ts index 1051914d894..653371e2ee4 100644 --- a/packages/objectql/src/engine-update-duplicate-record.test.ts +++ b/packages/objectql/src/engine-update-duplicate-record.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * #14390 — the update door's ONE error contract for a driver's unique-constraint + * Commit 9d7f7259f — the update door's ONE error contract for a driver's unique-constraint * refusal: the insert door's (#14095), one verb over. * * ## What was measured, and why it is a defect rather than a preference @@ -109,7 +109,7 @@ const mysqlDuplicate = () => }); /** - * driver-memory (#13197 / #13239): already an ADR-0112 envelope, in the + * driver-memory (commit 56c093c4d / #13239): already an ADR-0112 envelope, in the * platform's own vocabulary — the declared-index sentence measured on a real * `InMemoryDriver` for this card, which names the KEY COLUMNS in parentheses * and no single column, so `uniqueViolationColumn` answers `undefined` for it. diff --git a/packages/objectql/src/engine.test.ts b/packages/objectql/src/engine.test.ts index 7ff7307060a..a8858480fb1 100644 --- a/packages/objectql/src/engine.test.ts +++ b/packages/objectql/src/engine.test.ts @@ -411,7 +411,7 @@ describe('ObjectQL Engine', () => { beforeEach(async () => { engine.registerDriver(mockDriver, true); await engine.init(); - // [#13657] `stamped` is declared because this suite's own + // [commit b003cf2e8] `stamped` is declared because this suite's own // `beforeInsert` hook writes it, and the post-hook door now judges // the hook's output against this map. The subject — one dispatch // per row, single-record context shape — is untouched. diff --git a/packages/objectql/src/engine.ts b/packages/objectql/src/engine.ts index 02fe46a5248..71f6c9268ae 100644 --- a/packages/objectql/src/engine.ts +++ b/packages/objectql/src/engine.ts @@ -2,7 +2,7 @@ import { AsyncLocalStorage } from 'node:async_hooks'; import { QueryAST, QueryInput, HookContext, ServiceObject } from '@objectstack/spec/data'; -// [#6300] The defaulting node schema `fillQueryAstDefaults` runs author input +// [commit 74155c735] The defaulting node schema `fillQueryAstDefaults` runs author input // through — the declared `.default()` stays in `packages/spec`, the engine // only invokes it. import { SortNodeSchema } from '@objectstack/spec/data'; @@ -22,7 +22,7 @@ import { type DroppedFieldsEvent } from '@objectstack/spec/data'; import type { WriteObservabilityOptions } from '@objectstack/spec/contracts'; -// The validate-only result IS the protocol's response shape (#6037): the +// The validate-only result IS the protocol's response shape (commit 18189983d): the // engine is what `metadata-protocol.validateData` returns, so letting the two // drift would put a translation layer between a verdict and its contract. import type { ValidateDataIssue, ValidateDataResponse } from '@objectstack/spec/api'; @@ -247,9 +247,9 @@ import { AssembledViewArtifactSchema, isViewContainerShaped, } from '@objectstack/spec'; -// [#14399] The ONE spelling of "which object does an aggregated `defineView` +// [commit 3c1bbd2a8] The ONE spelling of "which object does an aggregated `defineView` // container bind to", imported rather than re-spelled — from the LEAF subpath, -// for the reason the `/errors` import above states (#14680). See +// for the reason the `/errors` import above states (commit 3bd9b3498). See // `resolveMetadataItemName` below for why this registrar lost its fourth copy. import { deriveViewContainerObject } from '@objectstack/metadata/view-container'; // [#20331] The divergent view-container `name` refusal — the ONE judge this @@ -265,7 +265,7 @@ import { collectPredicateRelationships, evaluateValidationRules, optionVisibilit // SAME value. Armed and sealed in `update()`; the module owns the argument for // why neither end may move. import { recordHookPayloadWrites } from './hook-write-provenance.js'; -// [#17219] The hide pass's other half: when a hook faults reaching THROUGH a +// [commit 706ad0fcc] The hide pass's other half: when a hook faults reaching THROUGH a // key that pass withheld, this names the key, says the platform withheld it, // and points at `ctx.previous` — the module owns the measurement and the // reason the explanation cannot be composed any further downstream. @@ -1640,7 +1640,7 @@ function assertOrderByIsMaterializable( // doors: a caller refused at the REST boundary and a caller refused here // must not be sent two different ways. // - // [#8648] With the SEARCH axis the agreement is in SUBSTANCE, not in + // [commit e5eeb499c] With the SEARCH axis the agreement is in SUBSTANCE, not in // words, and saying otherwise here was simply false — measured from the // running doors, #6673's correction emits "Mirror the computed value onto // a stored text field on '' and search that instead." All three @@ -2370,7 +2370,7 @@ export interface HookEntry { * ⚠️ That idiom is deliberately stated WITHOUT naming a live registration. * It used to name one: `sys_attachment` declared #4757's delete refusal on * `beforeDelete` and on no update registration — true when this paragraph was - * written (#9974), false since #10091 gave that guard's update verb a refusal + * written (#9974), false since commit da891e0ef gave that guard's update verb a refusal * of its own. A replacement exemplar would only be the next referent free to * move, so none is named: the past-tense sentence cannot be falsified by the * tree moving on, because it is a claim about what those two cards did rather @@ -2430,7 +2430,7 @@ function hookTargetList(target: string | string[] | undefined): string[] { * The allow half keeps the TRUTHINESS test both copies used verbatim, rather * than the `!== undefined` that reads more precisely. They differ on exactly one * input, `object: ''`, which reads here as a GLOBAL hook (falsy ⇒ no filter). - * That read is deliberately UNCHANGED, and #6573 is why: flipping it would turn + * That read is deliberately UNCHANGED, and commit 708431313 says why: flipping it would turn * a hook firing on everything into one firing on nothing, silently — the same * class of defect pointing the other way. The shape is closed at the * registration door instead ({@link assertValidHookObject}), so no live entry @@ -2514,7 +2514,7 @@ function assertValidHookExcludeObjects( } /** - * [#6573] Registration-time refusal for the `object` (ALLOW) face, closing + * [commit 708431313] Registration-time refusal for the `object` (ALLOW) face, closing * #4281 / #4001's "an empty target is not *no* target" ruling on the path that * ruling never reached. * @@ -2568,7 +2568,7 @@ function assertValidHookObject( } /** - * [#6573] Refuse a scope whose two faces cancel each other out — + * [commit 708431313] Refuse a scope whose two faces cancel each other out — * `{ object: 'account', excludeObjects: 'account' }` and its list forms. * * The exclusion face subtracts from the allow face, so when the allow face is a @@ -2797,7 +2797,7 @@ export interface OperationContext { */ tenantLayer0Verdict?: TenantLayer0Verdict; /** - * [#16608] The INSERT post-image seam — where an enforcement layer gets to + * [commit a016f08b8] The INSERT post-image seam — where an enforcement layer gets to * judge the row that will actually be stored. * * An `insert` has no pre-image, so a middleware's only image of the write is @@ -2838,7 +2838,7 @@ export interface OperationContext { } /** - * [#16608] The judgement {@link OperationContext.postHookWriteImageCheck} + * [commit a016f08b8] The judgement {@link OperationContext.postHookWriteImageCheck} * carries, and the acknowledgement its installer reads back. * * `evaluate` receives the images the driver is about to store, and REFUSES by @@ -2910,7 +2910,7 @@ export type EngineMiddleware = ( /** * "Which of these tombstoned `sys_file` rows is something still holding?" - * (#11427). + * (commit c3c72a4bc). * * Takes the whole tombstoned set from ONE record read and returns the subset * still held, as a set of stringified ids. Batched rather than per-row on @@ -3022,7 +3022,7 @@ const METADATA_ARRAY_KEYS = [ * `/api/v1/meta/views/:object`, `getViewsByObject()` and * `GET /meta/view?object=` all address it by. * - * ⚠️ [#14399] The sentence that used to stand here — "per spec, `ViewSchema` + * ⚠️ [commit 3c1bbd2a8] The sentence that used to stand here — "per spec, `ViewSchema` * does NOT have a top-level `name` field" — is measurably false and was the * premise for consulting `item.name` first. `ViewSchema` declares an optional * `name` (`view.zod.ts`), described there as "supplied by the metadata door; @@ -3033,7 +3033,7 @@ const METADATA_ARRAY_KEYS = [ */ function resolveMetadataItemName(key: string, item: any): string | undefined { if (!item) return undefined; - // [#14399] The aggregated `views` CONTAINER branch, taken FIRST and answered + // [commit 3c1bbd2a8] The aggregated `views` CONTAINER branch, taken FIRST and answered // by the shared derivation. Everything below is unchanged. // // This registrar used to consult `item.name` before anything else, for every @@ -3775,9 +3775,9 @@ export class ObjectQL implements IObjectQLEngine { // first, so the combined check below can assume well-formed names. // [#5928] An exclusion face that subtracts nothing (`''`) or everything (`'*'`). assertValidHookExcludeObjects(options?.excludeObjects, event); - // [#6573] An allow face that names nothing (`''` → global, `[]`/`['']` → never fires). + // [commit 708431313] An allow face that names nothing (`''` → global, `[]`/`['']` → never fires). assertValidHookObject(options?.object, event); - // [#6573] Two well-formed faces that cancel out (`'account'` minus `'account'`). + // [commit 708431313] Two well-formed faces that cancel out (`'account'` minus `'account'`). assertHookScopeNotSelfCancelling(options?.object, options?.excludeObjects, event); // [#9719/#9974] The unscoped-multi-write flag on an event whose dispatch never reads it. assertValidUnscopedMultiWriteFlag(options?.dispatchUnscopedMultiWrite, event); @@ -4642,7 +4642,7 @@ export class ObjectQL implements IObjectQLEngine { /** * "Which of these tombstoned `sys_file` rows is something still holding?" - * (#11427) — supplied by the storage plugin, never derived here. + * (commit c3c72a4bc) — supplied by the storage plugin, never derived here. * * File-field hydration must answer the same question the download path * answers (#10246) or one row gets two answers. That question has exactly one @@ -4658,7 +4658,7 @@ export class ObjectQL implements IObjectQLEngine { private _heldFileResolver?: HeldFileResolver; /** - * Wire the batched holder question (#11427). Last registration wins; leaving + * Wire the batched holder question (commit c3c72a4bc). Last registration wins; leaving * it unwired keeps tombstoned files un-hydrated, which is what this engine * did before the seam existed. */ @@ -5268,7 +5268,7 @@ export class ObjectQL implements IObjectQLEngine { } /** - * [#13644] Build the declared `HookContext.referentialFieldClear` marker — + * [commit 34ce8e7db] Build the declared `HookContext.referentialFieldClear` marker — * the read-only hook-context projection of the operation-private * `__referentialFieldClear` that {@link ObjectQL.cascadeDeleteRelations} * stamps on the cleanup write's ExecutionContext (#3023). @@ -5447,7 +5447,7 @@ export class ObjectQL implements IObjectQLEngine { // reading (2026-08-31 ruling, execution point 1). // // It used to mute EVERY elevated write, whatever the object was. The - // #13178 census measured what that cost: 135 of 175 write call sites + // census cited in commit e49d98896's message measured what that cost: 135 of 175 write call sites // (77%) were silenced here — at the control's LARGEST gate, sitting // ahead of the condition the control is about — and the control has // never produced a finding, while all five known instances of the defect @@ -5625,7 +5625,7 @@ export class ObjectQL implements IObjectQLEngine { // [#13491] Platform-namespace objects are excluded PER OBJECT, not // wholesale. The 2026-08-31 ruling withdrew the blanket // `isPlatformNamespaceObject(object)` exemption that used to stand here: - // #8672's "an org-less row is defensible for `sys_permission_set`" + // commit ff08691e6's "an org-less row is defensible for `sys_permission_set`" // inherits per object, and the namespace also holds objects whose org-less // rows are a defect — five instances of that class, all found by hand. // `unclassified` keeps the old exclusion so an unadjudicated object's @@ -6330,14 +6330,14 @@ export class ObjectQL implements IObjectQLEngine { * * | driver | `supports.autonumber` | fallback path? | uniqueness on the column | a collision appears as | * |:---|:---|:---|:---|:---| - * | driver-memory | `supports = {}` | **yes** | field-level `unique`, since #13197 (ADR-0120 D1/D3 scoping) | `UNIQUE_VIOLATION` / 409 → re-seed + re-issue, here | + * | driver-memory | `supports = {}` | **yes** | field-level `unique`, since commit 56c093c4d (ADR-0120 D1/D3 scoping) | `UNIQUE_VIOLATION` / 409 → re-seed + re-issue, here | * | driver-mongodb | absent (`{ batchSchemaSync: true }`) | **yes** | single-field unique index when the field declares `unique` | `E11000 duplicate key` → re-seed + re-issue, here | * | driver-sql | `autonumber: true` | no | — | — | * | driver-sqlite-wasm | inherited (`extends SqlDriver`, no `supports` override) | no | — | — | * | driver-turso | inherited (`...super.supports`) | no | — | — | * * So the retry protects the TWO fallback backends — and it protected only one - * of them until #13197, because `driver-memory` enforced no uniqueness at all + * of them until commit 56c093c4d, because `driver-memory` enforced no uniqueness at all * and had nothing to reject with. Which driver ISSUES the number is a * separate question and is unmoved by that: it is the reading the repo * already ruled and gates, in @@ -6351,12 +6351,12 @@ export class ObjectQL implements IObjectQLEngine { * a second answer to "who owns the autonumber counter" is the same * one-contract-two-numbers defect this lane keeps closing (#6832). * - * ⚠️ **This paragraph used to record a live defect; #13197 closed it, and the + * ⚠️ **This paragraph used to record a live defect; commit 56c093c4d closed it, and the * ⛔ below is why the closure went where it did.** `InMemoryDriver.create` was * a `table.push()` storing no constraints of any kind (#4065's WEAK-oracle * docstring), so an out-of-process duplicate raised nothing for this method to * catch and the number landed twice in the rendered field with no error - * anywhere. Since #13197 that driver enforces field-level `unique` + * anywhere. Since commit 56c093c4d that driver enforces field-level `unique` * (`driver-memory`'s `memory-unique-constraint.ts`, with `driver-sql`'s * ADR-0120 D1/D3 scoping) and refuses the collision in the ADR-0112 envelope, * which `isUniqueViolationError` reads — so the branch below is reachable @@ -6372,7 +6372,7 @@ export class ObjectQL implements IObjectQLEngine { * driver, NOT a pre-issue existence probe here: a probe costs a query on every * insert (the cost this resync was designed to avoid) and is still racy, so it * would trade a silent duplicate for a rarer silent duplicate at double the - * read cost. That argument is UNCHANGED by #13197 and is not a historical + * read cost. That argument is UNCHANGED by commit 56c093c4d and is not a historical * note — it is the standing reason no probe is added here, and it is what the * driver-side fix was chosen over. (`packages/drivers/**` was under the #5499 * investment freeze when this comment was first written, which is why the work @@ -6672,7 +6672,7 @@ export class ObjectQL implements IObjectQLEngine { // widens its values to `unknown`. State the contract once, on the // entries, rather than casting the argument at the call: the map // values ARE authored `ServiceObject`s — the INPUT shape, which is - // what `registerObject` takes since ADR-0122 phase 2 (#6083). + // what `registerObject` takes since ADR-0122 phase 2 (commit 53068c130). for (const [name, objDef] of Object.entries(manifest.objects) as [string, ServiceObject][]) { // Ensure name in definition matches key objDef.name = name; @@ -6762,7 +6762,7 @@ export class ObjectQL implements IObjectQLEngine { this.logger.debug('Registering kinds from manifest', { id, kindCount: manifest.contributes.kinds.length }); for (const kind of manifest.contributes.kinds) { this._registry.registerKind(kind); - // [#10729] Name the kind by its declared `id`. `contributes.kinds` + // [commit 10485009a] Name the kind by its declared `id`. `contributes.kinds` // items are `{ id, description? }` (`manifest.zod.ts`; `globs` was // retired unread, #11169) and // `registerKind` keys the item on `id` (`registerItem('kind', kind, 'id')`), @@ -6940,7 +6940,7 @@ export class ObjectQL implements IObjectQLEngine { this.logger.warn(`Skipping ${pluralToSingular(key)} without a derivable name`, { id: ownerId }); continue; } - // [#14666] The DIVERGENT-container refusal (maintainer ruling + // [commit d0ee598e6] The DIVERGENT-container refusal (maintainer ruling // 2026-09-03, direction 2). This seam used to reconcile a // container's own `name` to the derived key silently, one line // below: the author's field discarded with no diagnostic, while @@ -7161,7 +7161,7 @@ export class ObjectQL implements IObjectQLEngine { /** * Hand a freshly-registered driver the ADR-0104 media arm — the kernel→driver - * supply seam (#15989, the ruling on #15041 step 2). + * supply seam (#15989, sequencing step 2 of ADR-0104's 2026-09-05 addendum). * * ## Why here, and why a closure rather than a value * @@ -9857,7 +9857,7 @@ export class ObjectQL implements IObjectQLEngine { /** * Have this deployment's file-family COLUMNS moved to the bare-id encoding - * (#15989 — the ruling on #15041, step 2)? + * (#15989 — sequencing step 2 of ADR-0104's 2026-09-05 addendum)? * * The kernel-side half of the arm a SQL driver writes on. The driver cannot * ask this itself: the fact lives in a `sys_migration` row, which is a row @@ -11099,7 +11099,7 @@ export class ObjectQL implements IObjectQLEngine { referenceObject, { where, - // [#6300] The `as any` these two carried is gone: `find` takes the + // [commit 74155c735] The `as any` these two carried is gone: `find` takes the // author state now, and the parsed nodes a `QueryAST` holds are // valid author input (a present `order` is legal to write). ...(nestedAST.fields @@ -11282,7 +11282,7 @@ export class ObjectQL implements IObjectQLEngine { } const fileMap = new Map(); - // [#11427] `committed` is servable and always was. A TOMBSTONE + // [commit c3c72a4bc] `committed` is servable and always was. A TOMBSTONE // (`status: 'deleted'` + `deleted_at`) is recoverable state, not a delete: // it is a claim about the future (this row is reapable once the grace // window ends) that the sweep re-checks and often withdraws. #10246 already @@ -11318,7 +11318,7 @@ export class ObjectQL implements IObjectQLEngine { } } catch (error) { // Unreadable evidence is not evidence of a holder. Keep the ids - // un-hydrated — the answer this pass gave before #11427, and the same + // un-hydrated — the answer this pass gave before commit c3c72a4bc, and the same // direction the download path fails in (`isServableForDownload`) and // the reap guard fails in (it vetoes rather than reaps when it cannot // tell). Distinct from the #6116 catch above, which covers the @@ -11624,13 +11624,13 @@ export class ObjectQL implements IObjectQLEngine { } /** - * [#6300] Fill the author-state defaults the query schemas declare, so the + * [commit 74155c735] Fill the author-state defaults the query schemas declare, so the * AST handed to middlewares, hooks and drivers is the PARSED state * `QueryAST` (a `z.infer` type) promises. * * ADR-0122 made `EngineQueryOptions` the author state (`z.input`): a key * with a declared `.default()` is optional to write. `find`/`findOne` kept - * demanding the parsed state anyway (#6083 pinned them back) because the + * demanding the parsed state anyway (commit 53068c130 pinned them back) because the * engine built its AST by bare spread and filled no default — `order: * undefined` would have ridden straight to the driver. This is the filling. * Each defaulting node is run through ITS OWN schema rather than @@ -11763,7 +11763,7 @@ export class ObjectQL implements IObjectQLEngine { // ADR-0122 the caller-supplied `context` is the AUTHOR state (every key // optional) while `QueryAST` carries the parsed one, so spreading it in and // removing it a line later would type the AST with a context it never holds. - // [#6300] The rest of the bag is author state too now — the defaults its + // [commit 74155c735] The rest of the bag is author state too now — the defaults its // schemas declare are filled here, before anything downstream reads the AST. const { context: _findContext, ...findQuery } = query ?? {}; const ast: QueryAST = { ...this.fillQueryAstDefaults(findQuery), object }; @@ -11925,7 +11925,7 @@ export class ObjectQL implements IObjectQLEngine { * ## The two facts this frame used to merge * * "The table has not been created yet" and "the read failed" are different - * facts, and until #13273 this line reported both at `error`, with a stack. + * facts, and until commit 3a86a65e7 this line reported both at `error`, with a stack. * The first one is the ordinary state of a database nobody has migrated yet, * and every caller on that path already treats it as a normal answer and says * so in its own code: {@link readMigrationFlagVerified} ("an unreadable table @@ -12057,7 +12057,7 @@ export class ObjectQL implements IObjectQLEngine { // last — findOne is single-row by contract. // Same reason as find(): the caller's `context` is the author state and the // AST carries the parsed one, so it leaves before the AST is typed. - // [#6300] And the same default-filling as find(), for the same reason. + // [commit 74155c735] And the same default-filling as find(), for the same reason. const { context: _findOneContext, ...findOneQuery } = query ?? {}; const ast: QueryAST = { ...this.fillQueryAstDefaults(findOneQuery), object: objectName, limit: 1 }; @@ -12302,7 +12302,7 @@ export class ObjectQL implements IObjectQLEngine { // site under its own `computed` reason (`insertDrops`) — in every context, // `isSystem` included, since a `formula` value has no column to land in. /** - * Validate-only (#6037, #4633 ruling D) — run the write path's own verdict + * Validate-only (commit 18189983d, #4633 ruling D) — run the write path's own verdict * over candidate rows and report it, WITHOUT persisting anything. * * ## Why this exists @@ -12941,7 +12941,7 @@ export class ObjectQL implements IObjectQLEngine { rowHookWrittenKeys[i] = sealed?.hookWrittenKeys; } - // ── [#13657] The POST-hook half of the declared-field door ─────────── + // ── [commit b003cf2e8] The POST-hook half of the declared-field door ─────────── // // #8737 moved the door above ahead of the hooks so that no work — no // autonumber, no secret row — is done for a payload about to be refused. @@ -13008,10 +13008,10 @@ export class ObjectQL implements IObjectQLEngine { if (postRefusal) throw postRefusal; } - // ── [#16608] EVERY VALUE-CHANGING PASS, AHEAD OF THE SEAM ────────── + // ── [commit a016f08b8] EVERY VALUE-CHANGING PASS, AHEAD OF THE SEAM ────────── // // The two strips below used to run AFTER the seam, and the contract - // review of PR #16805 measured what that cost: a static-`readonly` + // review commit a016f08b8 records measured what that cost: a static-`readonly` // scoping field — the natural shape for a server-stamped column, and // exactly what an RLS `check` compares (ADR-0055) — was judged by the // seam with the CALLER’s value still on the row, then stripped and @@ -13196,7 +13196,7 @@ export class ObjectQL implements IObjectQLEngine { } } - // ── [#16608] The INSERT POST-IMAGE seam ────────────────────────────── + // ── [commit a016f08b8] The INSERT POST-IMAGE seam ────────────────────────────── // // The enforcement layer's write `check` used to be evaluated in its // middleware, against `opCtx.data` — the caller's payload as it arrived. @@ -13207,7 +13207,7 @@ export class ObjectQL implements IObjectQLEngine { // the same objects `rows` is built from below and the driver is handed. // // Placement obeys the rule #8682 wrote for the declared-field door and - // #13657 restated for its post-hook half: a refusal must cost nothing. + // commit b003cf2e8 restated for its post-hook half: a refusal must cost nothing. // This sits after that door and BEFORE every producer — // `resolveSystemInsertOrganization`, `encryptSecretFields` (which writes // a `sys_secret` row), `applyAutonumbers` (which CONSUMES a sequence @@ -13215,7 +13215,7 @@ export class ObjectQL implements IObjectQLEngine { // // ## What runs between here and the driver — stated, not waved at // - // The contract review of PR #16805 measured the version of this comment + // The contract review commit a016f08b8 records measured the version of this comment // that said "nothing between here and the driver adds a value the caller // could have steered" and then let TWO caller-steerable passes run after // the seam. Both now run ABOVE (`stripRuntimeOwnedFields` and the static @@ -13706,7 +13706,7 @@ export class ObjectQL implements IObjectQLEngine { /** * Update one record by id, or every record a predicate selects. * - * # The error contract on a unique violation (#14390) + * # The error contract on a unique violation (commit 9d7f7259f) * * A driver's unique-constraint refusal leaves this door as the ADR-0112 * envelope `DuplicateRecordError` — `code: 'DUPLICATE_RECORD'`, `status: 409`, @@ -14183,7 +14183,7 @@ export class ObjectQL implements IObjectQLEngine { submitted: Object.freeze({ ...suppliedValues }) as Record, session: this.buildSession(opCtx.context), provenance: this.buildProvenance(opCtx.context), - // [#13644] The declared referential-cleanup marker. Conditional + // [commit 34ce8e7db] The declared referential-cleanup marker. Conditional // spread, not a bare assignment: the contract is "absent unless // true", and an explicit `undefined` member would survive the // per-row context spreads as a present-but-undefined key. @@ -14363,7 +14363,7 @@ export class ObjectQL implements IObjectQLEngine { // permanently true here: it states the invariant, and the invariant // outlives this call site. if (priorRecord) hookContext.previous = coerceBooleanFields(updateSchema as any, priorRecord as any) as any; - // [#17219] All three `beforeUpdate` dispatch sites inside the hide + // [commit 706ad0fcc] All three `beforeUpdate` dispatch sites inside the hide // window share one wrapper, so a hook that faults reaching THROUGH a // key this pass withheld names that key instead of surfacing the // platform's own contract enforcement as the author's crash. It @@ -14483,7 +14483,7 @@ export class ObjectQL implements IObjectQLEngine { // ── [#14088] SEAL the hook-write recording ─────────────────────────── // - // The same CONFLUENCE #13657 uses one comment down, and for the same + // The same CONFLUENCE commit b003cf2e8 uses one comment down, and for the same // reason: on either branch this is the line at which // `hookContext.input.data` is the final POST-hook payload and nothing // engine-owned has written to it yet. One seal covers both branches, so @@ -14578,7 +14578,7 @@ export class ObjectQL implements IObjectQLEngine { } } - // ── [#13657] The POST-hook half of the declared-field door ────────── + // ── [commit b003cf2e8] The POST-hook half of the declared-field door ────────── // // The insert path's twin, applied to the second write verb — same // function, same envelope, same reason (see the long-form note at the @@ -14959,7 +14959,7 @@ export class ObjectQL implements IObjectQLEngine { updateSchema, hookContext.input.data as Record, opCtx.data as Record, opCtx.context, updateMsgCtx, ); - // [#14390] The by-id driver exit — where a driver's refusal + // [commit 9d7f7259f] The by-id driver exit — where a driver's refusal // leaves this door, and where a recognised unique violation // stops being the driver's error. `envelopeUniqueViolation` // returns everything else untouched (a NOT NULL, a deadlock, a @@ -15260,7 +15260,7 @@ export class ObjectQL implements IObjectQLEngine { opCtx.data as Record, opCtx.context, updateMsgCtx, ); // `updateMany` presence is part of the ladder verdict resolved above. - // [#14390] The predicate driver exit, enveloped on the same + // [commit 9d7f7259f] The predicate driver exit, enveloped on the same // terms as the by-id exit above. A multi-row write names no // row: `field` is whatever `uniqueViolationColumn` reads off // the driver's error, and NOTHING is invented about which of @@ -15418,7 +15418,7 @@ export class ObjectQL implements IObjectQLEngine { // redaction, same one argument — the message, the level and the // `object` are unchanged. // - // [#14390] …and, as on the insert door (#14095), the line still + // [commit 9d7f7259f] …and, as on the insert door (#14095), the line still // carries what the DATABASE said now that the caller receives an // envelope: the platform logger serializes `message` and `stack` // only, so logging the envelope would silently drop the failing @@ -16372,7 +16372,7 @@ export class ObjectQL implements IObjectQLEngine { // — same trust model as `__expandRead`), so it cannot be forged from // a request to bypass the guard on an ordinary write. // - // [#13644] This same marker is what `update()`'s hook-context + // [commit 34ce8e7db] This same marker is what `update()`'s hook-context // assembly projects onto the DECLARED `HookContext. // referentialFieldClear` (see buildReferentialFieldClear), so an // app guard can recognise the cleanup without reading an @@ -18227,10 +18227,10 @@ export class ObjectRepository implements IScopedObjectRepository { } /** - * [#16786] Declared `Promise | null>`, not `Promise`. + * [commit 5c8f5af50] Declared `Promise | null>`, not `Promise`. * * `IScopedObjectRepository.findOne` has declared that shape since #16231's - * ruling A landed (PR #16783), and `IDataEngine.findOne` — the call this + * ruling A landed (commit 854639b31), and `IDataEngine.findOne` — the call this * method forwards to, one line down — declares it too. This method sat * between two narrow declarations and re-widened the value back to `any` on * the way out, so `implements IScopedObjectRepository` stayed satisfied (a @@ -18261,7 +18261,7 @@ export class ObjectRepository implements IScopedObjectRepository { } /** - * [#16786] Declared `Promise | number | null>`, the same + * [commit 5c8f5af50] Declared `Promise | number | null>`, the same * re-widening as {@link findOne} and repaired the same way: the record for * the single-record form, the affected-row count for the predicate form * (`{ where, multi: true }`), `null` when the write matched nothing. @@ -18269,7 +18269,7 @@ export class ObjectRepository implements IScopedObjectRepository { * ⛔ `updateById` is deliberately NOT touched here. Its `Promise` is * what `IScopedObjectRepository.updateById` itself declares, so the class * matches its contract and there is no drift to repair on this side; that - * member is `packages/spec`'s to narrow and stays open on #16786. + * member is `packages/spec`'s to narrow (its spec half: commit 6059b29c0). */ async update(data: any, options: any = {}): Promise | number | null> { return this.engine.update(this.objectName, data, { diff --git a/packages/objectql/src/find-hook-result-shape.ts b/packages/objectql/src/find-hook-result-shape.ts index 89c7f11fcc6..a2d5eff3c83 100644 --- a/packages/objectql/src/find-hook-result-shape.ts +++ b/packages/objectql/src/find-hook-result-shape.ts @@ -27,7 +27,7 @@ * * The fork was real and pointed both ways — either the engine guarantees the * array, or `find()`'s declaration is wrong and the ~70 array-or-envelope - * normalizer limbs the #15094 census counted are load-bearing rather than dead. + * normalizer limbs a census counted (commit 901773b21 records its band) are load-bearing rather than dead. * The maintainer ruled the first (2026-09-06): the protocol is the baseline and * the declaration IS the contract, so the seam that can break it is closed * rather than the contract widened. `packages/spec/src/data/hook.zod.ts` backs diff --git a/packages/objectql/src/hook-exclude-objects.test.ts b/packages/objectql/src/hook-exclude-objects.test.ts index a71258ef332..de5d4060684 100644 --- a/packages/objectql/src/hook-exclude-objects.test.ts +++ b/packages/objectql/src/hook-exclude-objects.test.ts @@ -35,7 +35,7 @@ * 3. the two refused EXCLUSION shapes (`''`/`['']`, `'*'`), following #4281's * ruling on empty hook targets, plus the `[]` that is deliberately accepted * on that face; - * 3b. [#6573] the refused ALLOW shapes — `''`, `[]`, `['']` — and the scope + * 3b. [commit 708431313] the refused ALLOW shapes — `''`, `[]`, `['']` — and the scope * whose two faces cancel out. #4281 closed these on the metadata path only; * `registerHook` is the code path it never reached. Refused at the door, * with `hookMatchesObject`'s reading left deliberately unchanged; @@ -217,7 +217,7 @@ describe('[#5928] refused exclusion faces (#4281 / ADR-0078 lineage)', () => { }); /* - * ── [#6573] The allow face gets #4281's door too ──────────────────────────── + * ── [commit 708431313] The allow face gets #4281's door too ──────────────────────────── * * #4281 ("an empty target is not *no* target") was closed in two places, both * on the METADATA path: `HookSchema.object`'s refine in `packages/spec`, and @@ -413,7 +413,7 @@ describe('[#5928] property: hasHooksFor is never tighter than triggerHooks', () { object: '*', excludeObjects: ['account', 'sys_job'] }, { object: ['account', 'contact'], excludeObjects: 'contact' }, // `{ object: ['account','contact'], excludeObjects: ['account','contact'] }` - // used to sit here. #6573 refuses a fully-cancelled scope at registration, + // used to sit here. Commit 708431313 refuses a fully-cancelled scope at registration, // so it can no longer be registered at all — and a scope that cannot exist // cannot violate the gate/dispatch property. Its refusal is pinned below. { object: 'account', excludeObjects: 'lead' }, @@ -498,14 +498,14 @@ describe('[#5928] hookMatchesObject — the one shared rule', () => { }); it("keeps the truthiness read of `object: ''` — #6573 closed the door, not the matcher", () => { - // #5928 pinned this reading as preserved-not-endorsed and filed #6573. - // #6573's ruling: refuse `''` at REGISTRATION, and leave this read alone — + // #5928 pinned this reading as preserved-not-endorsed and filed the card commit 708431313 closed. + // The decision commit 708431313 records: refuse `''` at REGISTRATION, and leave this read alone — // flipping it would silently convert a fires-on-everything hook into a // fires-on-nothing one, the same defect pointing the other way. So the // matcher still answers "global" for a hand-built entry... expect(hookMatchesObject({ object: '' }, 'account')).toBe(true); // ...and no live entry can carry `''`, because registration refuses it. - // (The refusal itself is pinned in the #6573 block below.) + // (The refusal itself is pinned in the commit 708431313 block below.) const engine = makeEngine(); expect(() => register(engine, 'blank', { object: '' })).toThrow(); }); diff --git a/packages/objectql/src/hook-withheld-readonly-fault.test.ts b/packages/objectql/src/hook-withheld-readonly-fault.test.ts index 823da17ed67..aa6a38b3e44 100644 --- a/packages/objectql/src/hook-withheld-readonly-fault.test.ts +++ b/packages/objectql/src/hook-withheld-readonly-fault.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * [#17219] The composer's contract, at the seam rather than through a driver. + * [commit 706ad0fcc] The composer's contract, at the seam rather than through a driver. * * The three DECLINE conditions carry as much weight as the accept case, and for * the reason the card is about: a diagnostic that fires on the wrong error is diff --git a/packages/objectql/src/hook-withheld-readonly-fault.ts b/packages/objectql/src/hook-withheld-readonly-fault.ts index 4fac03314cf..691abb0972a 100644 --- a/packages/objectql/src/hook-withheld-readonly-fault.ts +++ b/packages/objectql/src/hook-withheld-readonly-fault.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * [#17219] Name the withheld key when a `before*` hook faults reaching THROUGH + * [commit 706ad0fcc] Name the withheld key when a `before*` hook faults reaching THROUGH * one — instead of letting the platform's own contract enforcement surface as * the author's crash. * @@ -46,7 +46,7 @@ * ⛔ Not by marshalling `ctx.submitted` onto the sandbox face: that face is * assembled key by key, `dispatch.scope` is the standing precedent for the * assembly discipline, and the shape was measured and refused on its merits in - * PR #17195. Nothing here adds a key to any authoring face or to any wire + * commit d2c1d1980. Nothing here adds a key to any authoring face or to any wire * payload. * * ## The classification this restores diff --git a/packages/objectql/src/in-memory-aggregation.ts b/packages/objectql/src/in-memory-aggregation.ts index c65412761a9..0f76950de77 100644 --- a/packages/objectql/src/in-memory-aggregation.ts +++ b/packages/objectql/src/in-memory-aggregation.ts @@ -282,7 +282,7 @@ function aggregateBucket( // booleans aggregate as NUMBERS on every face, with no per-aggregate // exception, so the order statistics answer in the same numeric domain // `sum`/`avg` already answer in (`toNumber`, `Number(true) === 1`). The - // coercion is BOOLEAN-ONLY, exactly like driver-memory's (#11065): + // coercion is BOOLEAN-ONLY, exactly like driver-memory's (commit 20950404c): // strings, dates and numbers reach the same raw comparison they always // did — widening it would change `min` over a text column. case 'min': { diff --git a/packages/objectql/src/lifecycle/lifecycle-service.test.ts b/packages/objectql/src/lifecycle/lifecycle-service.test.ts index 4c9d58a323f..7ca7213ee6f 100644 --- a/packages/objectql/src/lifecycle/lifecycle-service.test.ts +++ b/packages/objectql/src/lifecycle/lifecycle-service.test.ts @@ -764,7 +764,7 @@ describe('LifecycleService.sweep — unguarded reap batching (#5194)', () => { }); it('ttl.onlyWhen {$null: true} spares tombstones and still reaps ordinary expired rows (#10165)', async () => { - // The #10165 acceptance criterion, both halves, against rows that really + // The acceptance criterion behind commit 801296050, both halves, against rows that really // disappear. A sys_session tombstone BACKDATES expires_at (#7732 stamps // `now - 1000`), so it looks maximally expired — without the filter it is // reaped first and hardest. Predicate-honouring store: the exclusion below @@ -981,7 +981,7 @@ describe('LifecycleService.sweep — Archiver (P3)', () => { }); /* ------------------------------------------------------------------ * - * [#10347] The Archiver honours a declared `ttl`. + * [commit 530c1df65] The Archiver honours a declared `ttl`. * * The property under test is "the declared ttl cutoff GOVERNED which rows * moved", and it is invisible to a suite that only asserts rows were @@ -1145,7 +1145,7 @@ describe('LifecycleService.sweep — Archiver (P3)', () => { }); /* ==================================================================== * - * [#10528] The Archiver resolves its window through ADR-0057 P4 + * [commit 7d483e1e5] The Archiver resolves its window through ADR-0057 P4 * governance — the same `effectiveWindowMs` resolver the Reaper uses. * * Before this card the three legs below were not "partly wired", they were @@ -1189,7 +1189,7 @@ describe('LifecycleService.sweep — Archiver governance (#10528)', () => { } as any, }; - /** `ttl` + `archive` (no `retention`) — the pair #10347 made executable. + /** `ttl` + `archive` (no `retention`) — the pair commit 530c1df65 made executable. * Its due window is `ttl.expireAfter` on `ttl.field`, so the governance * key that governs it is `expireAfter`, not `maxAge`. */ const TTL_ARCHIVE_OBJ: LifecycleObjectLike = { @@ -1452,7 +1452,7 @@ describe('LifecycleService.sweep — Archiver governance (#10528)', () => { it('DEFECT CONTROL (override): with ttl declared it is `expireAfter` that governs — on the ttl field', async () => { // Which override key applies follows which window SELECTION picks - // (#10347). A fix that always consulted `maxAge` would leave this red. + // (commit 530c1df65). A fix that always consulted `maxAge` would leave this red. const stores = governedStores({ sys_audit_log: [ { id: 'expired-400d', created_at: at(-2 * DAY), expires_at: at(-400 * DAY), organization_id: null }, diff --git a/packages/objectql/src/lifecycle/lifecycle-service.ts b/packages/objectql/src/lifecycle/lifecycle-service.ts index 789a83f1759..34b1dd7989b 100644 --- a/packages/objectql/src/lifecycle/lifecycle-service.ts +++ b/packages/objectql/src/lifecycle/lifecycle-service.ts @@ -22,7 +22,7 @@ import type { * rotation falls back to an age-based reap bounded by `shards × unit`. * - **Archiver** (P3): copies audit-class cold rows to the declared archive * datasource, then deletes them from the hot store. Cold is `created_at` - * past `archive.after`, or [#10347] `ttl.field` past `ttl.expireAfter` + * past `archive.after`, or [commit 530c1df65] `ttl.field` past `ttl.expireAfter` * when the object declares a `ttl` beside its `archive`. **Safety rule:** an * object that declares `archive` is never hot-deleted unless the archive * copy succeeded — a compliance ledger must not be dropped unarchived. @@ -109,7 +109,7 @@ export interface LifecycleObjectLike { lifecycle?: Lifecycle; fields?: Record; /** - * [#16729] The object's tenancy posture, DECLARED here because the Archiver + * [commit 0f38ab084] The object's tenancy posture, DECLARED here because the Archiver * hands this very object to a driver that reads the key * (`cold.syncSchema(object, obj)` below), and every driver resolves a * uniqueness partition from it: `tenancy.enabled: false` means one row per @@ -122,7 +122,7 @@ export interface LifecycleObjectLike { * `tenancy` and therefore omits it. The object then reaches `syncSchema` as * the `{ name, fields }` shape, which is exactly the partial re-registration * `SqlDriver.computeAndRecordTenantField`'s sticky record exists to survive. - * Declaring the key is the same correction #16711 made where the shard leaf + * Declaring the key is the same correction commit 7862fb711 made where the shard leaf * narrowed `indexes` and `tenancy` off the object it was handed: a type must * not refuse a key the code below it reads. */ @@ -1005,7 +1005,7 @@ export class LifecycleService { // store; when the archive datasource isn't registered, rows are retained // (never dropped unarchived) and the object is reported as skipped. // - // [#10347] This return is not a policy DROP. A lifecycle may declare `ttl` + // [commit 530c1df65] This return is not a policy DROP. A lifecycle may declare `ttl` // beside `archive` — that pair parses — and until this card the ttl branch // below was simply unreachable for it, so the declared per-row expiry never // ran anywhere. {@link archiveObject} now applies that window itself (see @@ -1028,7 +1028,7 @@ export class LifecycleService { 'global', report, ); - // [#10165] `ttl.onlyWhen` rides the same argument `retention.onlyWhen` + // [commit 801296050] `ttl.onlyWhen` rides the same argument `retention.onlyWhen` // does below — one reap path, one scope spread (see `reap()`'s `scope`). outcomes.push(await this.reap(engine, object, lc, 'ttl', lc.ttl.field, windowMs, report, lc.ttl.onlyWhen)); } @@ -1225,7 +1225,7 @@ export class LifecycleService { /** * Archiver (ADR-0057 §3.3 / P3): copy rows past `archive.after` from the * hot store to the archive datasource, then delete the copied rows hot. - * [#10347] When the object ALSO declares `ttl`, the declared per-row expiry + * [commit 530c1df65] When the object ALSO declares `ttl`, the declared per-row expiry * is what selects candidates — `ttl.field` past its `expireAfter` window — * instead of `created_at` past `archive.after`. * Batched (500 × 20 per sweep) so a large backlog drains across sweeps @@ -1262,7 +1262,7 @@ export class LifecycleService { await cold.syncSchema(object, obj); } - // [#10347] WHICH ROWS ARE DUE. `archive` alone moves rows by age from + // [commit 530c1df65] WHICH ROWS ARE DUE. `archive` alone moves rows by age from // `created_at`, bounded by `archive.after` — unchanged. But a lifecycle may // also declare `ttl` beside `archive`: ADR-0057 §3.5's refine is satisfied // (`ttl` IS a bounding policy) and the `archive.after === retention.maxAge` @@ -1290,8 +1290,8 @@ export class LifecycleService { // author has not decided yet — against the retain-first posture that makes // this method refuse to hot-delete anything the cold store has not taken. // - // [#10643] `retention` declared beside `ttl` + `archive`: once an open - // question at this line (#10527), since decided — and decided at parse + // [commit 5649efbf9] `retention` declared beside `ttl` + `archive`: once an open + // question at this line, since decided by that commit — and decided at parse // time rather than here. `LifecycleSchema` (`packages/spec`, the // superRefine on the lifecycle block) refuses that triple unless the ttl // restates the age bound exactly: `ttl.field` must be `created_at` and @@ -1309,10 +1309,10 @@ export class LifecycleService { // straight back on this line, so it is not a spec-local change. Which // WINDOW governs is a separate leg either way: with `ttl` declared it is // the `expireAfter` override key that applies, not `maxAge` (see the - // #10528 block below). + // commit 7d483e1e5 block below). const dueField = lc.ttl ? lc.ttl.field : 'created_at'; - // [#10528] WHICH WINDOW IS DUE — resolved through ADR-0057 P4 governance, + // [commit 7d483e1e5] WHICH WINDOW IS DUE — resolved through ADR-0057 P4 governance, // the same {@link effectiveWindowMs} every window on the reap path goes // through. Until this card the cutoff below was read straight off the // declaration, and that was not one forgotten call: `reapObject` RETURNS @@ -1325,7 +1325,7 @@ export class LifecycleService { // // Resolved HERE rather than in `reapObject` before it delegates, because // the selection above is what decides WHICH window is governed and that - // decision lives in this method by the 2026-08-20 ruling (#10347). + // decision lives in this method by the 2026-08-20 ruling (commit 530c1df65). // Resolving in the caller would mean either duplicating the selection or // splitting one decision across two methods — and the per-tenant leg is a // pass over this method's own hot/cold batch loop, which cannot leave it @@ -1411,7 +1411,7 @@ export class LifecycleService { return moved; }; - // [#10528] Per-tenant windows (ADR-0057 §3.2), in the shape `reap()` uses: + // [commit 7d483e1e5] Per-tenant windows (ADR-0057 §3.2), in the shape `reap()` uses: // each overriding tenant gets its own cutoff on its own rows, then one // global pass covers everyone else INCLUDING rows with no organization — // a bare `$nin` would silently skip NULL-org rows, since a value that is @@ -1458,7 +1458,7 @@ export class LifecycleService { // Cold-side retention: `keep` bounds the archive itself. // - // [#10528] Governance deliberately does NOT reach this line. `keep` bounds + // [commit 7d483e1e5] Governance deliberately does NOT reach this line. `keep` bounds // the ARCHIVE — how long cold rows survive — not which hot rows are due, // and the `lifecycle` settings namespace has no key for it // (`retention_overrides` carries `maxAge` / `expireAfter` only). It also @@ -1504,7 +1504,7 @@ export class LifecycleService { const tenantWindows = (this.governance.tenantOverrides.get(object) ?? []).filter( (t) => typeof t[overrideKey] === 'string', ); - // `retention.onlyWhen` / `ttl.onlyWhen` [#10165] narrow every delete to + // `retention.onlyWhen` / `ttl.onlyWhen` [commit 801296050] narrow every delete to // the declared row filter — rows outside it (live workflow state, audit // tombstones) are retained regardless of age/expiry. const scope = onlyWhen ?? {}; diff --git a/packages/objectql/src/metadata-facade.test.ts b/packages/objectql/src/metadata-facade.test.ts index f8b2957d0dc..75deb4146f9 100644 --- a/packages/objectql/src/metadata-facade.test.ts +++ b/packages/objectql/src/metadata-facade.test.ts @@ -51,7 +51,7 @@ describe('MetadataFacade provenance passthrough', () => { // getItem('object', …) routes to the merged-object path, so read the // generic collection directly to inspect what register() stored. // - // [#6725] The direct read is STILL the right instrument here, and for + // [commit 1507ba356] The direct read is STILL the right instrument here, and for // the same reason as before: this pin is about the STORED document, and // the two object reads answer the contributor copy — which now exists, // and which deliberately does carry the `'sys_metadata'` sentinel (see @@ -87,7 +87,7 @@ describe('MetadataFacade provenance passthrough', () => { }); /** - * [#6725] The write/read pin. + * [commit 1507ba356] The write/read pin. * * `MetadataFacade.register('object', …)` wrote through `registerItem` into the * generic `metadata` map, while every one of this class's object reads resolves @@ -98,7 +98,7 @@ describe('MetadataFacade provenance passthrough', () => { * `register('object', …)` through both members; this file is the gate for the * facade's half of that. * - * Refs #6725, #6505 / PR #6723, #6808, ADR-0010, ADR-0029. + * Refs commit 1507ba356, #6505 / commit 8ad609c69, #6808, ADR-0010, ADR-0029. */ describe('MetadataFacade object write/read round-trip', () => { let registry: SchemaRegistry; @@ -147,7 +147,7 @@ describe('MetadataFacade object write/read round-trip', () => { }); it('serves the runtime-effective object, as the contract says it does', async () => { - // #6505 / PR #6723: `getObject` answers the object as the engine runs + // #6505 / commit 8ad609c69: `getObject` answers the object as the engine runs // it, not the document its author wrote. The materialization seam is // `registerObject`'s, so it only runs now that the write reaches it. const multiTenantRegistry = new SchemaRegistry({ multiTenant: true }); diff --git a/packages/objectql/src/metadata-facade.ts b/packages/objectql/src/metadata-facade.ts index 082ea91ed1f..012a16b98db 100644 --- a/packages/objectql/src/metadata-facade.ts +++ b/packages/objectql/src/metadata-facade.ts @@ -14,7 +14,7 @@ import { SchemaRegistry } from './registry.js'; * never reaches this predicate — `'objects'` arrives here as `'object'`. * `SchemaRegistry.getItem` / `listItems` still special-case BOTH spellings to * the contributor path (their own callers are not all folded), which is the - * read-side alias #6725's write fix had to match; the fold upstream makes the + * read-side alias commit 1507ba356's write fix had to match; the fold upstream makes the * two layers agree instead of merely overlapping. */ function isObjectType(type: string): boolean { @@ -124,7 +124,7 @@ export class MetadataFacade { } /** - * [#6725] An `object` lives in TWO places in a `SchemaRegistry`, and this + * [commit 1507ba356] An `object` lives in TWO places in a `SchemaRegistry`, and this * write has to reach both of them. * * `SchemaRegistry.unregisterObject`'s header states the invariant directly: @@ -260,7 +260,7 @@ export class MetadataFacade { /** * Unregister a metadata item * - * [#6725] An object leaves both places it was written into, for the same + * [commit 1507ba356] An object leaves both places it was written into, for the same * reason {@link register} writes both: `unregisterItem` only empties the * generic `metadata` map, which no object read consults. Removing one half is * the exact shape of #6808 — the row was gone and `metadata['object']` was diff --git a/packages/objectql/src/metadata-service-getobject-equivalence.test.ts b/packages/objectql/src/metadata-service-getobject-equivalence.test.ts index 984c90a8b9d..148e532cbe4 100644 --- a/packages/objectql/src/metadata-service-getobject-equivalence.test.ts +++ b/packages/objectql/src/metadata-service-getobject-equivalence.test.ts @@ -1,11 +1,11 @@ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license. /** - * Conformance pin — `getObject(name)` ≡ `get('object', name)` (#6745). + * Conformance pin — `getObject(name)` ≡ `get('object', name)` (commit 7a5ef0008). * * `IMetadataService.getObject` (`packages/spec/src/contracts/metadata-service.ts`) * DECLARES that the pair resolves through one lookup in every implementation this - * repo ships, and that both members hand back the identical object. PR #6723 (for + * repo ships, and that both members hand back the identical object. commit 8ad609c69 (for * #6505) wrote that down after measuring it with a throwaway probe, which left the * statement declared-but-ungated: nothing failed if a later edit made the pair * diverge, and the contract TSDoc would then simply be lying. This file is the gate. @@ -26,7 +26,7 @@ * `registry.getObject`). An object written the first way was readable back * through neither member — measured, both `undefined` — so a pin seeded that * way would have compared `undefined` to `undefined` and called it - * equivalence. #6725 has since closed that split (`facade.register('object', + * equivalence. Commit 1507ba356 has since closed that split (`facade.register('object', * …)` performs the contributor write too, and pins the round-trip in * `metadata-facade.test.ts`), so either seeding would work here now; this one * is kept because it seeds the registry directly, the way a registry-backed @@ -48,7 +48,7 @@ * converge on `SchemaRegistry.getObject`, whose merge result is memoized in * `mergedObjectCache`, so both members hand back the same instance. * - * Refs #6745, #6505, PR #6723, #6725. + * Refs #6505; commits 7a5ef0008 (the getObject pin), 8ad609c69 (getObject's declared answer), 1507ba356 (the facade split fix). */ import { describe, it, expect } from 'vitest'; @@ -167,7 +167,7 @@ const IMPLEMENTATIONS: readonly PinnedImplementation[] = [ for (const object of objects) { // Seeded on the registry, not through `facade.register('object', …)` // — see the header. That write reached neither object read until - // #6725 closed the split; it now would, but this seeding is the + // commit 1507ba356 closed the split; it now would, but this seeding is the // one a registry-backed host actually performs. registry.registerObject(object.definition as never, 'com.example.pin'); } diff --git a/packages/objectql/src/metadata-service-roundtrip-conformance.test.ts b/packages/objectql/src/metadata-service-roundtrip-conformance.test.ts index 52df7424d5a..bcaed2d4fee 100644 --- a/packages/objectql/src/metadata-service-roundtrip-conformance.test.ts +++ b/packages/objectql/src/metadata-service-roundtrip-conformance.test.ts @@ -14,7 +14,7 @@ * three implementations at once: it depends on `@objectstack/metadata` * (`MetadataManager`) and `@objectstack/core` (`createMemoryMetadata`) and owns * `MetadataFacade`. That is the same argument - * `metadata-service-getobject-equivalence.test.ts` (#6745) already makes for + * `metadata-service-getobject-equivalence.test.ts` (commit 7a5ef0008) already makes for * living here, and it is why `packages/spec` cannot host this half. * * ## The four subjects, and why four for three implementations @@ -38,7 +38,7 @@ * full verbatim ruling text and the row-2 convergence rationale (the * direction is `check:meta-type-normalized`'s: normalize once at the entry, * decide on the normalized value — the gate's header carries - * #3984/#5881/#6241). + * #3984, #5881 and the third bypass, fixed in commit 83a3b1f2e). * * The shared table states the same ruling as `expected` answers — `refused` * rows carry the ADR-0112 envelope contract, the plural row is `readable` @@ -65,7 +65,7 @@ * drifted off a decided contract, and the fix belongs in the implementation; * update the pin only in the PR that changes the ruling. * - * Refs #7223, #7378, #6725, PR #7211, #6745. + * Refs #7223, #7378; commits 1507ba356 (the facade split fix, PR #7211), 7a5ef0008 (the getObject pin). */ import { describe, it, expect } from 'vitest'; diff --git a/packages/objectql/src/metadata-validation-sweep.test.ts b/packages/objectql/src/metadata-validation-sweep.test.ts index a9f40f14c53..e4364c98c6a 100644 --- a/packages/objectql/src/metadata-validation-sweep.test.ts +++ b/packages/objectql/src/metadata-validation-sweep.test.ts @@ -18,7 +18,7 @@ * Types without a Zod schema in the central registry (today only * `rag_pipeline` among the URL-map kinds — `theme`/`webhook` and their * siblings all resolve schemas via `UNREGISTERED_KIND_SCHEMAS` since - * #6245/#10194) are still expected to pass through unvalidated — that is + * #6245 / commit 2306a765c) are still expected to pass through unvalidated — that is * the documented fall-through, not a regression. We pin it explicitly so any * future coverage gap is visible in the report. * @@ -195,7 +195,7 @@ const FIXTURES: Record = { app: { valid: { name: 'sweep_app', label: 'Sweep' }, // The invalid probe breaks `label`, not `name`: an ungrammatical item - // name is refused by the #12194 grammar door (INVALID_REQUEST 400) + // name is refused by the grammar door (commit 311433f6b, INVALID_REQUEST 400) // BEFORE the central Zod registry runs, so a bad name can no longer // prove the schema gate this sweep exists to prove. The name-grammar // refusal has its own pins in metadata-protocol. diff --git a/packages/objectql/src/overlay-precedence.test.ts b/packages/objectql/src/overlay-precedence.test.ts index 7f2f04c7daf..0bbd9f1876b 100644 --- a/packages/objectql/src/overlay-precedence.test.ts +++ b/packages/objectql/src/overlay-precedence.test.ts @@ -403,7 +403,7 @@ describe('overlay whitelist enforcement (shared-DB invariant)', () => { // allowOrgOverride:false (no per-org agent fork). The kernel ships // exactly two platform agents; tenants extend via skills + tools. expect(allowedFromRegistry.has('agent')).toBe(false); - // #6483 — `permission`/`position` rolled BACK to + // Commit ee58392e1 — `permission`/`position` rolled BACK to // allowOrgOverride:false (with page/app/action/dataset/book/ // tool/skill; the whole nine-type divergence family). ADR-0005's // security row has always said ❌: "Authorization correctness; diff --git a/packages/objectql/src/plugin-governance-scoped-metadata.test.ts b/packages/objectql/src/plugin-governance-scoped-metadata.test.ts index 8a895bb8dc9..a2ef259f546 100644 --- a/packages/objectql/src/plugin-governance-scoped-metadata.test.ts +++ b/packages/objectql/src/plugin-governance-scoped-metadata.test.ts @@ -2,7 +2,7 @@ /** * [#15252] The boot-time action-governance audit reaches a SCOPED metadata - * service — the C4 cell #14423's ruling left open. + * service — the C4 cell commit a56baa2bd left open. * * ## What was broken * diff --git a/packages/objectql/src/plugin.ts b/packages/objectql/src/plugin.ts index b5e39e9cd0a..f2969e51e7e 100644 --- a/packages/objectql/src/plugin.ts +++ b/packages/objectql/src/plugin.ts @@ -1540,7 +1540,7 @@ export class ObjectQLPlugin implements Plugin { * hides all of it behind a dialect-local bind-safety net, which is why the * SQLite/Turso suites never saw it. * - * The split is the same ruling #7737/#10629 made for federated objects — + * The split is the same ruling #7737 made for federated objects (commit 199ec4712) — * that flag is about DDL, and a binding that is DDL-free must not ride on it * — applied to the managed ones. */ @@ -2634,14 +2634,14 @@ export class ObjectQLPlugin implements Plugin { if (meta && typeof loadMany === 'function') { loadStandaloneActions = () => loadMany.call(meta, 'action'); } - // [#14423] The KEYED plural read, preferred over `loadMany` — see + // [commit a56baa2bd] The KEYED plural read, preferred over `loadMany` — see // `collectEngineActionDeclarations`. A plane that predates it (or a test // double) simply does not offer it and the unkeyed read above stands. const loadManyKeyed = meta?.loadManyKeyed; if (meta && typeof loadManyKeyed === 'function') { loadStandaloneActionsKeyed = () => loadManyKeyed.call(meta, 'action'); } - // [#14423] The router's THIRD rung, injected the same way its second one + // [commit a56baa2bd] The router's THIRD rung, injected the same way its second one // is. `resolveRouteActionDeclaration` prefers `loadDiagnosed` and falls // back to `load`; this mirrors that branch and unwraps, so the audit // receives a declaration-or-nothing exactly like `lookupRegistryAction`. diff --git a/packages/objectql/src/protocol-meta.test.ts b/packages/objectql/src/protocol-meta.test.ts index f62eee1f31f..4d0bb5e4907 100644 --- a/packages/objectql/src/protocol-meta.test.ts +++ b/packages/objectql/src/protocol-meta.test.ts @@ -67,7 +67,7 @@ describe('ObjectStackProtocolImplementation - Metadata Persistence', () => { // save stamps `organization_id` on the row — is unchanged, but since // the 2026-08-08 ruling only types that DECLARE a per-org channel may // carry one, and `app` rolled back to `allowOrgOverride: false` in - // #6483. `view` is the whitelisted specimen, so this now measures the + // commit ee58392e1. `view` is the whitelisted specimen, so this now measures the // stamping on a row the platform can actually read back. mockEngine.findOne.mockResolvedValue(null); await protocol.saveMetaItem({ @@ -86,7 +86,7 @@ describe('ObjectStackProtocolImplementation - Metadata Persistence', () => { }), expect.anything()); }); - // [#14770] Re-spelled from `app` to `view`, and its sibling below with + // [commit d5cbb44f3] Re-spelled from `app` to `view`, and its sibling below with // it. The CLAIM is unchanged — an org row and an env-wide row of the // same `(type, name)` both exist, and the org row is the one SERVED, // whole, by precedence rather than a merge. It just has to be measured @@ -95,12 +95,12 @@ describe('ObjectStackProtocolImplementation - Metadata Persistence', () => { // `getMetaItem` now resolves its own read scope through // `organizationIdForMetaRead` — the read-side twin of the predicate // `saveMetaItem` already gates on — so on `app`, which rolled back to - // `allowOrgOverride: false` in #6483, `organizationId` is gated to + // `allowOrgOverride: false` in commit ee58392e1, `organizationId` is gated to // `undefined` and the org partition is never queried. On `app` this - // case was pinning the phantom read #14770 removes: a pre-#6190 + // case was pinning the phantom read commit d5cbb44f3 removed: a pre-#6190 // org-scoped row served INSTEAD OF the live env-wide document. `view` // is the whitelisted specimen — the same re-spelling #6190 made one - // case up and #14683 made one case down. + // case up and commit 96326040f made one case down. it('getMetaItem returns org-specific overlay when both org and env-wide rows exist', async () => { // findOverlay calls: first attempts org=org_alpha (returns row), // env-wide fallback should be skipped. @@ -149,7 +149,7 @@ describe('ObjectStackProtocolImplementation - Metadata Persistence', () => { // ⚠️ NON-VACUITY, and the reason this case had to move too. A // fall-through only states something if the org partition was // actually read FIRST. Left on `app` this case kept passing after - // #14770 while measuring nothing at all: the gate resolves `app` to + // commit d5cbb44f3 while measuring nothing at all: the gate resolves `app` to // `undefined`, so the only read ever issued was the env-wide one and // the assertion could no longer fail. expect(mockEngine.findOne).toHaveBeenCalledWith('sys_metadata', { @@ -157,28 +157,28 @@ describe('ObjectStackProtocolImplementation - Metadata Persistence', () => { }); }); - // [#14683] Re-spelled from `app` to `view`, the READ-side twin of the + // [commit 96326040f] Re-spelled from `app` to `view`, the READ-side twin of the // `[#6190]` re-spelling three cases up — same reason, one verb over. // `getMetaItems` now resolves its own read scope through // `organizationIdForMetaRead`, so an `organizationId` handed in for a // type the registry declares NON-overridable is gated to `undefined` // and the org partition is never queried. `app` rolled back to - // `allowOrgOverride: false` in #6483, so on `app` this case was + // `allowOrgOverride: false` in commit ee58392e1, so on `app` this case was // asserting a union the platform must NOT perform: the org rows it // seeded are the pre-#6190 phantoms `loadMetaFromDb` walks past, and - // reading them back is the resurrection #14683 closes. + // reading them back is the resurrection commit 96326040f closed. // // The CLAIM is unchanged and is what this case still pins — env-wide // and org rows union, org winning on collision. It just has to be // measured on a type that has an org partition to union. // - // ⚠️ SUPERSEDED, 2026-09-03 (#14770). This paragraph used to read "Its + // ⚠️ SUPERSEDED, 2026-09-03 (commit d5cbb44f3). This paragraph used to read "Its // two `getMetaItem` (SINGULAR) siblings above keep `app` deliberately: - // that verb is untouched here." That was true when #14683 landed and is - // the sentence #14770 falsified: the singular verb now gates too, so + // that verb is untouched here." That was true when commit 96326040f landed and is + // the sentence commit d5cbb44f3 falsified: the singular verb now gates too, so // both siblings moved to `view` in the same edit. The reasoning it gave // — a singular caller CAN be right about its scope, and its REST door - // already gates — held for the DOOR and not for the VERB: `#14770` + // already gates — held for the DOOR and not for the VERB: commit d5cbb44f3 // measured four runtime callers that reach the verb with a raw active // organization, and on a `??` precedence read an ungated organization // does not merely ADD a row, it SUBSTITUTES the served document. @@ -280,7 +280,7 @@ describe('ObjectStackProtocolImplementation - Metadata Persistence', () => { }); describe('saveMetaItem', () => { - // [#8818] WAS `rejects.toThrow('Item data is required')` — a bare + // [commit fd6bdf89f] WAS `rejects.toThrow('Item data is required')` — a bare // message match that stayed green while the refusal declared no // ADR-0112 envelope at all, so `clientFacingFailureText` withheld the // sentence and the REST boundary served `500 INTERNAL_ERROR`. The @@ -415,7 +415,7 @@ describe('ObjectStackProtocolImplementation - Metadata Persistence', () => { // given, and `sampleApp` is shared by every case in this file. registry.registerItem('app', { ...sampleApp }, 'name', 'com.acme.showcase'); - // #6483 rolled `app`'s `allowOrgOverride` back to `false` + // Commit ee58392e1 rolled `app`'s `allowOrgOverride` back to `false` // (ADR-0005 table: ❌ for page/app/action), so overriding this // packaged app needs the one documented door that remains — the // `OS_METADATA_WRITABLE` operator escape hatch. The receipt @@ -666,7 +666,7 @@ describe('ObjectStackProtocolImplementation - Metadata Persistence', () => { // Every overlay-allowed built-in type now has a canonical Zod // schema registered in `getMetadataTypeSchema()`. The probe // breaks `label`, not `name`: an ungrammatical item name is - // refused by the #12194 grammar door (INVALID_REQUEST 400) + // refused by the grammar door (commit 311433f6b, INVALID_REQUEST 400) // before the registry runs, so a bad name can no longer reach // — and therefore cannot prove — the schema gate under test. let caught: any; @@ -1634,7 +1634,7 @@ describe('ObjectStackProtocolImplementation - Metadata Persistence', () => { // here it would have flipped this test red for a reason that has // nothing to do with what it proves. // - // [#10194] `theme` left it by exactly the webhook rule: it gained a + // [commit 2306a765c] `theme` left it by exactly the webhook rule: it gained a // SCHEMA (not a registry entry), and the old specimen body // (`tokens: {}` — an alias of `customVars`, with the required `colors` // missing) is spec-INVALID and now 422s. `analytics_cube` was bound in @@ -1644,7 +1644,7 @@ describe('ObjectStackProtocolImplementation - Metadata Persistence', () => { // no-schema fall-through control below. Each newly-bound type's own // behaviour, door and 422 both, is pinned in the tests below. // - // [#10485] `theme` then left the CONTRACT ITSELF (ADR-0049 — the + // [commit 35ad101bc] `theme` then left the CONTRACT ITSELF (ADR-0049 — the // `themes` carrier and `ThemeSchema` retired; the `themes: 'theme'` // fold left `PLURAL_TO_SINGULAR`), so it is no longer a URL-map-only // kind at all: both halves of its old pair now earn the #8421 @@ -1843,14 +1843,14 @@ describe('ObjectStackProtocolImplementation - Metadata Persistence', () => { }); // ─────────────────────────────────────────────────────────────── - // [#10194] `theme` / `analytics_cube` — the two doors #6245 left + // [commit 2306a765c] `theme` / `analytics_cube` — the two doors #6245 left // open, closed the same way and pinned the same way: the write door // is UNCHANGED (no-static-entry authorization fall-through, verdict // byte-identical), the shape check is new. Both halves per type, so a // change that quietly CLOSED the door fails the "accepts" half. // ─────────────────────────────────────────────────────────────── - // [#10485] `theme` left this pair: the carrier retired out of the + // [commit 35ad101bc] `theme` left this pair: the carrier retired out of the // spelling contract, so BOTH halves now earn the #8421 unrecognised // refusal before any schema is consulted — pinned once below. The // still-bound `webhook` door keeps the two-halves pin alive for the diff --git a/packages/objectql/src/protocol-org-overlay-registry-gate.test.ts b/packages/objectql/src/protocol-org-overlay-registry-gate.test.ts index fd23a4b18eb..a90c39fcd57 100644 --- a/packages/objectql/src/protocol-org-overlay-registry-gate.test.ts +++ b/packages/objectql/src/protocol-org-overlay-registry-gate.test.ts @@ -168,7 +168,7 @@ describe('#6602 — the premise, read from the registry rather than restated', ( allowOrgOverride: true, }); // `flow` reaches the same seam through the OTHER write tier: not - // per-org overridable (#6283 / PR #6478) but still runtime-creatable, + // per-org overridable (#6283 / commit 474f131cf) but still runtime-creatable, // which is the tier a Studio-authored flow uses. expect(DEFAULT_METADATA_TYPE_REGISTRY.find((e) => e.type === 'flow')).toMatchObject({ allowOrgOverride: false, diff --git a/packages/objectql/src/protocol-recorded-by-null.test.ts b/packages/objectql/src/protocol-recorded-by-null.test.ts index 97f1dbea343..db5916e634b 100644 --- a/packages/objectql/src/protocol-recorded-by-null.test.ts +++ b/packages/objectql/src/protocol-recorded-by-null.test.ts @@ -20,7 +20,7 @@ * matched. With the sentinel gone the ordinary authoring paths must still * pass — that is the regression #4441 was bitten by. * - * [#14535] "The real thing" is a claim about the TARGET KEY too, and it was + * [commit 1aba3159a] "The real thing" is a claim about the TARGET KEY too, and it was * false here until this change. The declaration spelled `referenceTo` — an * alias `FieldSchema` refuses by name (#11567) and `referenceTargetOf`, the * single arbiter the write-path guard resolves through, does not read at all. diff --git a/packages/objectql/src/protocol-registry-shadow.test.ts b/packages/objectql/src/protocol-registry-shadow.test.ts index 5007cd94344..abde1591f61 100644 --- a/packages/objectql/src/protocol-registry-shadow.test.ts +++ b/packages/objectql/src/protocol-registry-shadow.test.ts @@ -190,7 +190,7 @@ function findByName(items: any[], name: string): any { return (items as any[]).find((it) => it?.name === name); } -// #6483 rolled `app`'s `allowOrgOverride` back to `false` (ADR-0005 — the +// Commit ee58392e1 rolled `app`'s `allowOrgOverride` back to `false` (ADR-0005 — the // amendment table says ❌ for `page`/`app`/`action`), so overriding the // PACKAGED app these suites are built around now needs the ONE documented // door that remains: the `OS_METADATA_WRITABLE` operator escape hatch, which @@ -296,7 +296,7 @@ describe('registry shadow — control-plane PUT → GET → DELETE keeps the art }); describe('registry shadow — scoped-kernel lock enforcement is shadow-immune', () => { - // Same #6483 door as above: with `app` no longer allowOrgOverride, the + // Same commit ee58392e1 door as above: with `app` no longer allowOrgOverride, the // save would 403 NOT_OVERRIDABLE at the type gate and never reach the // L3 lock this case exists to prove is shadow-immune. Behind the hatch // the type gate passes and the LOCK is what refuses — the ordering the diff --git a/packages/objectql/src/query-expression-conformance.test.ts b/packages/objectql/src/query-expression-conformance.test.ts index 6751c8fc48b..baee7a054de 100644 --- a/packages/objectql/src/query-expression-conformance.test.ts +++ b/packages/objectql/src/query-expression-conformance.test.ts @@ -1029,7 +1029,7 @@ describe('#4226 — sort / select / expand on the list path (real ObjectQL engin // refused on two axes must not be sent two different ways, which is // exactly how #4256 and #6673 drifted apart in the first place. // - // [#8648] It used to assert only that the four SORT/FILTER doors share + // [commit e5eeb499c] It used to assert only that the four SORT/FILTER doors share // one stem — which left the claim unpinned in the one place where // reading it as word-identity was FALSE. The SEARCH axis cannot match // that stem and never did; measured from the running doors on this @@ -1067,7 +1067,7 @@ describe('#4226 — sort / select / expand on the list path (real ObjectQL engin // actionable. // // ⛔ Unifying the SEARCH wording onto the shared stem is route 3 of - // #8648 and was NOT taken: it changes a shipped error message and + // the card commit e5eeb499c fixed, and was NOT taken: it changes a shipped error message and // needs somewhere for the `text` narrowing to live. Layer 2 is what // makes that a decision someone takes on purpose instead of a silent // edit — if you are here because it went red, that is the pin working. @@ -1114,7 +1114,7 @@ describe('#4226 — sort / select / expand on the list path (real ObjectQL engin emit: () => engine.find('showcase_task', { orderBy: [{ field: 'sort_key', order: 'asc' }] }), }, { - // [#8648] The door the claim was missing. SEARCH has no engine + // [commit e5eeb499c] The door the claim was missing. SEARCH has no engine // twin to pair with: `search` is expanded at ingress into the // `$or` of `$icontains` the engine receives (ADR-0061), so // this axis has exactly one door — which is why "the three @@ -1388,7 +1388,7 @@ describe('#4226 — sort / select / expand on the list path (real ObjectQL engin expect(err.message).toMatch(/ObjectQL\.find\('showcase_task'\)/); expect(err.message).toMatch(/follows the relationship 'project_id' into another object/); // The one-vocabulary discipline, emitted-vs-emitted: both doors close - // with the SAME remedy sentence the #8648 agreement pin protects. + // with the SAME remedy sentence the commit e5eeb499c agreement pin protects. const ingressErr: any = await protocol .findData({ object: 'showcase_task', query: { where: { 'project_id.name': 'Apollo' } } }) .then(() => null, (e: unknown) => e); diff --git a/packages/objectql/src/register-object-authored-shape.pin.ts b/packages/objectql/src/register-object-authored-shape.pin.ts index 9f329be96c8..74da0d31ba2 100644 --- a/packages/objectql/src/register-object-authored-shape.pin.ts +++ b/packages/objectql/src/register-object-authored-shape.pin.ts @@ -4,7 +4,7 @@ * #5543 — compile-time pin for the shape `registerObject` accepts. * * Both doors (`ObjectQL.registerObject` and `SchemaRegistry.registerObject`) - * are annotated `ServiceObject`. Since ADR-0122 phase 2 (#6083) that bare spec + * are annotated `ServiceObject`. Since ADR-0122 phase 2 (commit 53068c130) that bare spec * alias means the **authored** (`z.input`) shape — defaulted keys optional, * pre-transform — which is what the registry actually receives: `registerObject` * runs no `parse`, so nothing on that path materializes a `.default(...)`. diff --git a/packages/objectql/src/registry-artifact-co-ownership.test.ts b/packages/objectql/src/registry-artifact-co-ownership.test.ts index d05f5007d98..55a91323757 100644 --- a/packages/objectql/src/registry-artifact-co-ownership.test.ts +++ b/packages/objectql/src/registry-artifact-co-ownership.test.ts @@ -199,7 +199,7 @@ describe('ADR-0130 D1 + D3 — the gate relaxation and the object-name check are expect(err.namespace).toBe('crm'); expect(err.existingPackageId).toBe('com.acme.crm'); expect(err.incomingPackageId).toBe('com.acme.crm.billing'); - // [#14474] The ADR-0112 envelope, asserted the same way this file already + // [commit df657d9df] The ADR-0112 envelope, asserted the same way this file already // asserts its D3 sibling's (`caught?.code` / `caught?.status` below). The // instance check above is NOT a substitute: it stayed green through every // year this class carried no `code` and no `status` at all, which is diff --git a/packages/objectql/src/registry-cross-package-item-classes.test.ts b/packages/objectql/src/registry-cross-package-item-classes.test.ts index 6ac4d644413..40bdd082804 100644 --- a/packages/objectql/src/registry-cross-package-item-classes.test.ts +++ b/packages/objectql/src/registry-cross-package-item-classes.test.ts @@ -46,7 +46,7 @@ * for all of them, and a single refusal can carry findings from several * classes at once). `ENVELOPE PRESENCE` then asserts the envelope itself, in * one place. Repaired the same way as #14367 (`registerObject`'s bare `Error`) - * and #14474 (`NamespaceConflictError`), one door over. + * and commit df657d9df (`NamespaceConflictError`), one door over. * * ⛔ If `ENVELOPE PRESENCE` below goes red, the envelope has been REMOVED or * its code renamed — a regression, not a cleanup. Restore it rather than diff --git a/packages/objectql/src/registry-namespace-install-gate.test.ts b/packages/objectql/src/registry-namespace-install-gate.test.ts index fe36a63340e..584f3eae2ac 100644 --- a/packages/objectql/src/registry-namespace-install-gate.test.ts +++ b/packages/objectql/src/registry-namespace-install-gate.test.ts @@ -57,7 +57,7 @@ describe('SchemaRegistry — namespace install gate (ADR-0048 Phase 1)', () => { }); it('carries the ADR-0112 envelope: code NAMESPACE_CONFLICT + status 422', () => { - // [#14474] The assertion the instance checks above cannot make, and the + // [commit df657d9df] The assertion the instance checks above cannot make, and the // reason this defect survived: `toThrowError(NamespaceConflictError)` and // `toBeInstanceOf(NamespaceConflictError)` are TRUE of a class carrying no // `code` and no `status`, so both stayed green while `POST /api/v1/packages` diff --git a/packages/objectql/src/registry-ownership-refusal-envelope.test.ts b/packages/objectql/src/registry-ownership-refusal-envelope.test.ts index c155694f22c..1c1fb2a1beb 100644 --- a/packages/objectql/src/registry-ownership-refusal-envelope.test.ts +++ b/packages/objectql/src/registry-ownership-refusal-envelope.test.ts @@ -8,7 +8,7 @@ * * The refusal (ADR-0029 D3, single owner per object name) used to be a bare * `Error`. Measured while reverse-verifying the install-time - * `DUPLICATE_ARTIFACT_OBJECT_NAME` check one layer up (#14163): with that + * `DUPLICATE_ARTIFACT_OBJECT_NAME` check one layer up (ADR-0130 D3, commit 1dcb995f2): with that * check ablated, `expect(refused).toBeDefined()` STAYED GREEN, because this * refusal fired one step later and looked, to a throw-shaped assertion, * exactly like the check that had just been deleted. Only the envelope diff --git a/packages/objectql/src/registry.ts b/packages/objectql/src/registry.ts index bbf2a1b3773..74cf3cdefca 100644 --- a/packages/objectql/src/registry.ts +++ b/packages/objectql/src/registry.ts @@ -16,7 +16,7 @@ import { // from one place. Re-exported below under its original name. ITEM_KEY_DISCRIMINATORS, readDiscriminatorValue as discriminatorValue, - // [#10062] The ADR-0029 D9.6 provenance pair, sunk into metadata-core for the + // [commit fa5d137ab] The ADR-0029 D9.6 provenance pair, sunk into metadata-core for the // same reason as the table above: `@objectstack/service-automation`'s flow // precedence asks the same question ("does a code package ship this name?") // and reached it by importing this package, which it does not declare — so @@ -36,7 +36,7 @@ import { type ObjectFieldTypeRefusal, type ObjectFieldTypeViolation, } from '@objectstack/metadata-core'; -// [#8460] `scalarOverridesPackagedBase` is the #8284 comparison, imported rather +// [ADR-0029 D9.2a] `scalarOverridesPackagedBase` is the #8284 comparison, imported rather // than re-spelled: the object FOLD asks the same question one layer down (has // this scalar been authored away from the packaged default?), and the ruling // required the same mechanism, not a second comparison shape. @@ -171,7 +171,7 @@ export function parseFQN(fqn: string): { namespace: string | undefined; shortNam /** * The three SCALAR props {@link mergeObjectDefinitions} resolves last-writer-wins - * — the exact set the #8284 and #8460 rulings both cover, and the same three + * — the exact set the #8284 ruling and ADR-0029 D9.2a both cover, and the same three * {@link scalarOverridesPackagedBase} answers for. */ const OBJECT_FOLD_SCALAR_KEYS = ['label', 'pluralLabel', 'description'] as const; @@ -220,7 +220,7 @@ type ObjectFoldScalarKey = (typeof OBJECT_FOLD_SCALAR_KEYS)[number]; * priority 140 does not become the base layer") fails if this merge set is * widened to copy it through. * - * [#8460] …the SCALAR override above is conditional. `tenantAuthored` names + * [ADR-0029 D9.2a] …the SCALAR override above is conditional. `tenantAuthored` names * the scalars the fold's BASE has authored away from the packaged owner's * value; an extender yields on those. See * {@link SchemaRegistry.tenantAuthoredScalars} for why the set is computed once @@ -248,7 +248,7 @@ function mergeObjectDefinitions( merged.indexes = [...(base.indexes || []), ...extension.indexes]; } - // Override scalar props (last writer wins) — [#8460] unless the base has been + // Override scalar props (last writer wins) — [ADR-0029 D9.2a] unless the base has been // authored by the tenant, in which case the extender's packaged default yields. const yields = (key: ObjectFoldScalarKey): boolean => tenantAuthored?.has(key) === true; if (extension.label !== undefined && !yields('label')) merged.label = extension.label; @@ -1510,7 +1510,7 @@ export const OBJECT_OWNERSHIP_CONFLICT_CODE = 'OBJECT_OWNERSHIP_CONFLICT' as con * install blow up later at table creation. Shareable platform namespaces * (`base`/`system`/`sys`) are exempt. * - * [#14474] Carries the ADR-0112 envelope (`code` + `status`), like its sibling + * [commit df657d9df] Carries the ADR-0112 envelope (`code` + `status`), like its sibling * {@link ArtifactObjectNameConflictError} below. Unlike that sibling, this * refusal IS reachable from a wire: `POST /api/v1/packages` * (`packages/runtime/src/domains/packages.ts`) calls `installPackage` with no @@ -1727,7 +1727,7 @@ export class ObjectOwnershipConflictError extends Error { } } -// [#10062] `isTenantAuthored` and `isCodeArtifactBody` used to be defined here. +// [commit fa5d137ab] `isTenantAuthored` and `isCodeArtifactBody` used to be defined here. // They now live in `@objectstack/metadata-core` // (`code-artifact-provenance.ts`), imported at the top of this file and // re-exported immediately below, so every caller's spelling — including @@ -2448,7 +2448,7 @@ export class SchemaRegistry { contributors: ObjectContributor[], baseDefinition: ServiceObject, ): ServiceObject { - // [#8460] Computed ONCE, over the base the fold starts from — never + // [ADR-0029 D9.2a] Computed ONCE, over the base the fold starts from — never // re-derived from the running `merged`, which would make an extender's own // scalar look "authored" to the next extender and silently invert // extender-vs-extender precedence (D9.3: declared numbers order peers). @@ -2466,7 +2466,7 @@ export class SchemaRegistry { } /** - * [#8460] Which of the three fold scalars the BASE layer carries a + * [ADR-0029 D9.2a] Which of the three fold scalars the BASE layer carries a * TENANT-AUTHORED value for — i.e. one that no longer equals the packaged * owner's. * @@ -2505,11 +2505,11 @@ export class SchemaRegistry { * {@link getPackagedObjectOwner} — whose extra `isCodeArtifactBody` test * (D9.8) would make this decline to protect a RUNTIME-authored object, i.e. * exactly the object whose owner row the tenant wrote by hand. The two agree - * wherever a packaged owner exists, which is every shape #8460 measured; they + * wherever a packaged owner exists, which is every shape the ADR-0029 D9.2a amendment records; they * differ only on a tenant-authored owner, and there the ruled sentence still * reads the same way — the tenant's own row is the explicit override and a * package's `objectExtensions` entry is the packaged default. The rejected - * alternative is the trap PR #8454 named one layer up, in its own form: + * alternative is the trap commit 427344c26 named one layer up, in its own form: * comparing against a body that already has extenders folded onto it * ({@link resolveOwnerLayer}) would report every extender's scalar as * "unchanged" and yield nothing, ever. diff --git a/packages/objectql/src/scoped-repository-return-narrowing.test.ts b/packages/objectql/src/scoped-repository-return-narrowing.test.ts index 88d269d9b7c..46aa68e1ced 100644 --- a/packages/objectql/src/scoped-repository-return-narrowing.test.ts +++ b/packages/objectql/src/scoped-repository-return-narrowing.test.ts @@ -5,12 +5,12 @@ import ts from 'typescript'; import { dirname, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; -// ─── [#16786] the repository a CLASS-typed call site reaches is declared ──── +// ─── [commit 5c8f5af50] the repository a CLASS-typed call site reaches is declared ──── // // `IScopedObjectRepository` (`packages/spec/src/contracts/scoped-context.ts`) // declares `findOne` as `Promise | null>` and `update` as // `Promise | number | null>` — ruling A on #16231, landed -// as PR #16783. `IDataEngine`, the call each `ObjectRepository` member forwards +// as commit 854639b31. `IDataEngine`, the call each `ObjectRepository` member forwards // to, declares the same shapes. `ObjectRepository` sat between those two narrow // declarations and re-widened the result back to `Promise`. // @@ -34,7 +34,7 @@ import { fileURLToPath } from 'node:url'; // // ⚠️ The first line is why the probes below are written through the CLASS and // the exported engine door rather than through `HookContext`. `HookContext.api` -// was narrowed to `IScopedContext` by #5945/#6311, so a handler typed +// was narrowed to `IScopedContext` by #5945 / commit 59b794f71, so a handler typed // `(ctx: HookContext) => …` reads the narrow type today and read it before this // fix too — a probe written that way is GREEN on both sides and pins nothing. // The `any` lives on the class-typed doors, so that is where the probes go. diff --git a/packages/objectql/src/search-companion-read-projection-conformance.test.ts b/packages/objectql/src/search-companion-read-projection-conformance.test.ts index a0e55b1c36a..53f5050e8d9 100644 --- a/packages/objectql/src/search-companion-read-projection-conformance.test.ts +++ b/packages/objectql/src/search-companion-read-projection-conformance.test.ts @@ -240,7 +240,7 @@ async function makeEngine(declared: boolean): Promise { /** * The `plugin-pinyin-search` write hook, in miniature. * - * [#13657] Carries `stampCompanion`'s DECLARATION GUARD + * [commit b003cf2e8] Carries `stampCompanion`'s DECLARATION GUARD * (`companion-projection.ts`: `if (!schema?.fields?.[SEARCH_COMPANION_FIELD]) * return;`). It was missing here, which made this double LOOSER than the hook * it stands in for — the #4550 failure shape one layer down: in the diff --git a/packages/objectql/src/search-companion.test.ts b/packages/objectql/src/search-companion.test.ts index fe0470e4bb3..1d88799f834 100644 --- a/packages/objectql/src/search-companion.test.ts +++ b/packages/objectql/src/search-companion.test.ts @@ -199,7 +199,7 @@ describe('containsCJK / isCompanionMatchableTerm', () => { }); // ───────────────────────────────────────────────────────────────────────────── -// [#10290] The primary key is never a companion source. +// [commit 2570ab05c] The primary key is never a companion source. // // The two blocks below are a matched pair and are meant to be read together: // the first is the NEGATIVE control (the defect — it fails on the pre-fix diff --git a/packages/objectql/src/search-companion.ts b/packages/objectql/src/search-companion.ts index 8d39ac91b3a..b7985174934 100644 --- a/packages/objectql/src/search-companion.ts +++ b/packages/objectql/src/search-companion.ts @@ -94,7 +94,7 @@ function isCompanionSourceType(type: string | undefined): boolean { } /** - * [#10290] Field names that carry the record's PRIMARY KEY — its address — + * [commit 2570ab05c] Field names that carry the record's PRIMARY KEY — its address — * rather than any human-authored text. * * Keyed on the NAME because that is where the role lives: the driver @@ -111,7 +111,7 @@ function isCompanionSourceType(type: string | undefined): boolean { const RECORD_ADDRESS_FIELD_NAMES: ReadonlySet = new Set([SystemFieldName.ID, '_id']); /** - * [#10290] Is `fieldName` the object's primary key? + * [commit 2570ab05c] Is `fieldName` the object's primary key? * * Exported so the refusal in {@link resolveSearchCompanionSources} is one * named judgement a caller can ask about, rather than a literal buried in a @@ -149,7 +149,7 @@ export function isCompanionSourceEligible(fieldMeta: CompanionFieldMeta | undefi * hook — deriving both from the same function means there is no stored * mapping to drift. * - * ## [#10290] The PRIMARY KEY is never a source + * ## [commit 2570ab05c] The PRIMARY KEY is never a source * * ADR-0079's derivation ends at "first title-eligible field by declaration * order", and on a table whose only text column IS its primary key — system @@ -201,7 +201,7 @@ export function resolveSearchCompanionSources(schema: CompanionObjectMeta | unde if (!schema?.fields) return []; const display = resolveDisplayField(schema as any); if (!display) return []; - // [#10290] Before the metadata gate: the primary key's METADATA is a + // [commit 2570ab05c] Before the metadata gate: the primary key's METADATA is a // perfectly ordinary readable text column, so only its name can refuse it. if (isPrimaryKeyField(display)) return []; const meta = schema.fields[display]; diff --git a/packages/objectql/src/skip-schema-sync-registers-object-metadata.test.ts b/packages/objectql/src/skip-schema-sync-registers-object-metadata.test.ts index 3c58361f7fb..5e1a2d09c66 100644 --- a/packages/objectql/src/skip-schema-sync-registers-object-metadata.test.ts +++ b/packages/objectql/src/skip-schema-sync-registers-object-metadata.test.ts @@ -19,7 +19,7 @@ * pins the encoding half against a live Postgres; this file pins the boot half: * that the flag routes to the DDL-FREE registration instead of to nothing. * - * It is the same ruling #7737/#10629 already made for FEDERATED objects — that + * It is the same ruling #7737 already made for FEDERATED objects (commit 199ec4712) — that * flag is about DDL, and a binding that is DDL-free must not ride on it — * extended to the managed ones. */ @@ -150,7 +150,7 @@ describe('OS_SKIP_SCHEMA_SYNC boot registers object metadata without DDL (#10995 const { driver, calls } = recordingDriver(); await install(true, [PREF, external], driver); - // The managed one only — #7737/#10629 already bind the federated one at + // The managed one only — #7737 and commit 199ec4712 already bind the federated one at // `kernel:ready`, and handing it to the managed route would register it // under its OBJECT name instead of its remote table. expect(calls.registerObjectMetadata[0]).toEqual(['sys_user_preference']); diff --git a/packages/objectql/src/sys-metadata-repository.test.ts b/packages/objectql/src/sys-metadata-repository.test.ts index 4ae485ce951..7bd5497f04c 100644 --- a/packages/objectql/src/sys-metadata-repository.test.ts +++ b/packages/objectql/src/sys-metadata-repository.test.ts @@ -701,7 +701,7 @@ describe('SysMetadataRepository', () => { const ref = { org: 'org_alpha', type: 'app' as const, name: 'ticket_service_app' }; // `intent: 'runtime-only'` — a whole-app build stages a BRAND-NEW app // (nothing artifact-backed under this name), which is exactly the - // intent the protocol layer computes for it. Required since #6483 + // intent the protocol layer computes for it. Required since commit ee58392e1 // rolled `app`'s `allowOrgOverride` back to `false` (ADR-0005): the // repository's default `override-artifact` intent now 403s for `app`, // while the runtime-create tier this write actually belongs to stays @@ -714,7 +714,7 @@ describe('SysMetadataRepository', () => { // Same `runtime-only` intent the real caller computes: the protocol's // publish handler derives intent from `isArtifactBacked` and nothing // ships an artifact under this name (promoteDraft's own default is - // `override-artifact`, which #6483's `app` rollback now 403s). + // `override-artifact`, which commit ee58392e1's `app` rollback now 403s). await repo.promoteDraft(ref, { actor: 'admin', intent: 'runtime-only' }); const activeRow = Array.from(engine.rows.values()).find( (r) => (r as any).type === 'app' diff --git a/packages/objectql/src/system-write-organization.test.ts b/packages/objectql/src/system-write-organization.test.ts index 14250432d4e..1679cb84eb2 100644 --- a/packages/objectql/src/system-write-organization.test.ts +++ b/packages/objectql/src/system-write-organization.test.ts @@ -114,7 +114,7 @@ const DISPATCH_ORDER = { * * ⚠️ Its exclusion below is `unclassified`, not `global`. Until the 2026-08-31 * ruling this file read it as "platform namespace ⇒ deliberately org-less - * (#8672)"; that wholesale reading was withdrawn, and what these cases now pin + * (…)"; that wholesale reading was withdrawn, and what these cases now pin * is that an UNADJUDICATED object's behaviour did not move — which is what * bounds the reclassification's blast radius to the admitted list. The admitted * and `global` sides are pinned in `tenancy-by-object-classification.test.ts`. @@ -344,7 +344,7 @@ describe('#8844 the exclusions — populations the refusal must not touch', () = 'a platform-namespace object stays org-less on the %s posture', async (posture) => { // ⚠️ [#13491] Reads as an UNCLASSIFIED verdict now, not a namespace one. - // #8672 measured this primitive on `sys_permission_set` and filed it as an + // The card commit ff08691e6 cites measured this primitive on `sys_permission_set` and filed it as an // observation because an org-less row is defensible there. The #8844 // ruling confirms that reasoning holds for platform objects and does NOT // generalize to application objects — which is exactly the boundary here. diff --git a/packages/objectql/src/tenancy-by-object-classification.test.ts b/packages/objectql/src/tenancy-by-object-classification.test.ts index 6a53cbbb41d..9049f30940b 100644 --- a/packages/objectql/src/tenancy-by-object-classification.test.ts +++ b/packages/objectql/src/tenancy-by-object-classification.test.ts @@ -8,7 +8,7 @@ // measurement fired: // // - isSystem x a TENANT-SCOPED object = IN scope; -// - isSystem x a genuinely GLOBAL object = OUT of scope, #8672's reasoning +// - isSystem x a genuinely GLOBAL object = OUT of scope, commit ff08691e6's recorded reasoning // inheriting PER OBJECT rather than by namespace. // // ## What each test here discriminates @@ -23,7 +23,7 @@ // each admitted-object case carries its excluded-object control, run // through the same engine on the same posture. // 2. The engine's `bypassTenantAudit` isSystem mute. This is the gate the -// #13178 census measured as silencing 135 of 175 write call sites (77%) — +// census cited in commit e49d98896's message measured as silencing 135 of 175 write call sites (77%) — // the control's LARGEST gate, sitting ahead of the condition the control // is about. Pinned as the OPTION the engine hands the driver, because that // is the whole of what the engine decides; `@objectstack/objectql` cannot @@ -91,7 +91,7 @@ const PACKAGE_ID = '#13491'; /** ADMITTED by the inventory — #12745 fixed its writer, a backfill was ordered. */ const SYS_FILE = { name: 'sys_file', fields: { key: { type: 'text' } } } as any; -/** GLOBAL by the inventory — #8672's own example, named verbatim in the ruling. */ +/** GLOBAL by the inventory — commit ff08691e6's own example, named verbatim in the ruling. */ const SYS_PERMISSION_SET = { name: 'sys_permission_set', fields: { label: { type: 'text' } } } as any; /** UNCLASSIFIED — a platform object the inventory did not adjudicate. */ const SYS_UNADJUDICATED = { name: 'sys_audit_entry', fields: { subject: { type: 'text' } } } as any; diff --git a/packages/objectql/src/tenancy/platform-object-tenancy.ts b/packages/objectql/src/tenancy/platform-object-tenancy.ts index 7df78dfa4ba..622c7619fe8 100644 --- a/packages/objectql/src/tenancy/platform-object-tenancy.ts +++ b/packages/objectql/src/tenancy/platform-object-tenancy.ts @@ -14,7 +14,7 @@ * exists for; it has occurred five times (#12745, #12928, #10673, #8617, * cloud#1239 — one a credentials table) and every instance was found by a * person reading call sites, never by the control. - * - `isSystem` x a GENUINELY GLOBAL object = OUT of scope. #8672's reasoning + * - `isSystem` x a GENUINELY GLOBAL object = OUT of scope. Commit ff08691e6's recorded reasoning * ("an org-less row is defensible for `sys_permission_set`") inherits **per * object**; the wholesale `sys_ / cloud_ / ai_` namespace exemption is * withdrawn. @@ -31,7 +31,7 @@ * ⛔ The census that measures this is NOT restated here. It is derived by * `scripts/platform-object-tenancy-census.mjs`, committed as * `scripts/platform-object-tenancy-census.json`, and held to the tree by - * `scripts/check-platform-object-tenancy-census.mjs` (#14957). Its PREDICATE is + * `scripts/check-platform-object-tenancy-census.mjs` (commit 26144c204). Its PREDICATE is * the half this paragraph used to leave out: an object is inside the machinery * when `resolveTenantFieldName` answers non-null on the registered schema — * after `applySystemFields`, because the injected column is what the engine @@ -50,7 +50,7 @@ * * The ARGUMENT survives that measurement, and no digit was load-bearing for it: * the great majority of platform-namespace objects carry the tenant column — - * `sys_permission_set`, #8672's own example of a legitimately org-less object, + * `sys_permission_set`, commit ff08691e6's own example of a legitimately org-less object, * among them — so a schema read admits nearly all of them in one stroke, i.e. * it replaces a wholesale exemption with a wholesale inclusion. The ruling's classification source is * "有列**且有写手填**" — the column AND a writer that fills it — and the second @@ -100,7 +100,7 @@ import { isPlatformNamespaceObject } from './system-write-organization'; export type PlatformObjectTenancy = /** Column present AND a citable writer fills it. In scope. */ | 'tenant-scoped' - /** #8672's reasoning inherits: rows are deliberately org-less. Out of scope. */ + /** Commit ff08691e6's reasoning inherits: rows are deliberately org-less. Out of scope. */ | 'global' /** Not determinable from the tree. Out of scope, PENDING ADJUDICATION. */ | 'unclassified'; @@ -141,7 +141,7 @@ export const PLATFORM_OBJECT_TENANCY: Readonly { // ⭐ THIS ASSERTION IS THE INVERSION. Its two earlier lives, in order: - // * before #14399 the boot loop minted ['lead_views', + // * before commit 3c1bbd2a8 the boot loop minted ['lead_views', // 'lead_views.default', 'lead_views.hot'] — the container and its // whole expansion filed under the row identity, so // `getViewsByObject('crm_lead')` had nothing for this document; - // * #14399 moved `name` to LAST in the derivation, so it minted + // * commit 3c1bbd2a8 moved `name` to LAST in the derivation, so it minted // AGREED_KEYS instead — the right key, but with the author's // `name` silently overwritten on the way past. - // The #14666 ruling (direction 2, 2026-09-03) ends the second: a + // The ruling commit d0ee598e6 records (direction 2, 2026-09-03) ends the second: a // container whose `name` disagrees with its derived binding is // REFUSED, exactly as the artifact/HMR door has always refused it. // - // #14399's derivation answer is NOT lost by inverting this — it moves + // Commit 3c1bbd2a8's derivation answer is NOT lost by inverting this — it moves // to where the artifact door's answer was already read in this file: // the refusal names the key it derived. Both SOURCE registrars are now // read the same way, which is the convergence the card asked for. @@ -244,7 +244,7 @@ describe('#14399 — the row\'s own `name` is the LAST term of the container der expect(error.message).toContain("'crm_lead'"); // The derivation itself, still pinned: `crm_lead` is what it derived, // NOT the row's own `lead_views`. A refusal naming `lead_views` as the - // derived key would mean #14399 had regressed. + // derived key would mean commit 3c1bbd2a8 had regressed. expect(error.message).toContain("binds to, 'crm_lead'"); // Nothing filed: a refusal that has already registered half the // document would leave the registry in the state the card calls the @@ -272,7 +272,7 @@ describe('#14399 — the row\'s own `name` is the LAST term of the container der const err = await loadThroughArtifactDoor(divergentContainer).catch((e) => e as any); expect(err.code).toBe('VALIDATION_ERROR'); expect(err.status).toBe(400); - // ⭐ [#14666] THE SECOND INVERSION, and the card's actual subject. This + // ⭐ [commit d0ee598e6] THE SECOND INVERSION, and the card's actual subject. This // used to read // // expect((engine.registry.getItem('view', 'crm_lead') as any).name) @@ -293,7 +293,7 @@ describe('#14399 — the row\'s own `name` is the LAST term of the container der }); it('so the boot loop\'s expanded items are addressable under the object', () => { - // [#14666] Driven on the ANONYMOUS container now. The expansion + // [commit d0ee598e6] Driven on the ANONYMOUS container now. The expansion // property this pins — expanded items bind to the derived object, not // to the container's row identity — is unchanged, but the divergent // shape no longer reaches expansion at all: it is refused before @@ -363,7 +363,7 @@ describe('#14399 — the row\'s own `name` is the LAST term of the container der }); // ------------------------------------------------------------------ - // [#14666] Scope controls. The ruling names keeping the refusal's scope + // [commit d0ee598e6] Scope controls. The ruling names keeping the refusal's scope // tight as the implementation's MAIN RISK, and `registerMetadataCollections` // is the GENERIC loop every metadata kind runs — so the three narrowings in // the gate get a control each, plus the measurement that decided which of diff --git a/packages/objectql/vitest.config.ts b/packages/objectql/vitest.config.ts index a379feae8c6..5f83f66abf7 100644 --- a/packages/objectql/vitest.config.ts +++ b/packages/objectql/vitest.config.ts @@ -58,7 +58,7 @@ import { // repo. `extends: true` keeps the root options (aliases included) on both. const REPO_TESTS: string[] = JSON.parse(readFileSync(path.join(__dirname, 'vitest.repo-tests.json'), 'utf8')); -// #17853 / #17978 — say so when a path named on the command line will run no +// Commit 08f5f0e5a / #17978 — say so when a path named on the command line will run no // tests. Invoked HERE, at config load, and ⛔ deliberately NOT as a // `test.reporters` entry: naming that option replaces vitest's own reporter // defaulting instead of extending it, which measurably changes a healthy run's From 8d64654574482f80a5627d6428cb38ed7ecb3032 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 1 Oct 2026 23:13:52 +0000 Subject: [PATCH 2/2] chore(changeset): objectql's reworded provenance comments reach the published dist The rewritten docblocks sit on exported members and land in index.d.ts, core.d.ts and the shared type chunk, and esbuild keeps some of the comments in the JavaScript output: a patch, comment text only. Claude-Session: https://claude.ai/code/session_017xfMoEjKUuSh2xYB8sCozp Co-authored-by: Claude --- .changeset/20595-objectql-provenance-anchors.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .changeset/20595-objectql-provenance-anchors.md diff --git a/.changeset/20595-objectql-provenance-anchors.md b/.changeset/20595-objectql-provenance-anchors.md new file mode 100644 index 00000000000..28d27fce775 --- /dev/null +++ b/.changeset/20595-objectql-provenance-anchors.md @@ -0,0 +1,16 @@ +--- +'@objectstack/objectql': patch +--- + +Provenance comments in `@objectstack/objectql` cite the commits and ADRs that decided them, not tracker numbers that no longer resolve + +Clause-②: no + +Docblocks and comments across the package cited issue-tracker numbers that now answer 404 on GitHub. +Each one now cites the commit in this repository's history that made the decision it describes, or the +ADR that records it (ADR-0029 D9.2a, ADR-0104's 2026-09-05 addendum, ADR-0126 §7.2, ADR-0130 D3). +Some of these docblocks sit on exported members, so the reworded text appears in the published +`index.d.ts` / `index.d.mts`, `core.d.ts` / `core.d.mts` and the shared type chunk, and comments that +esbuild keeps appear in the JavaScript output. + +Comment only: no export, type, error code, status, message text or runtime behaviour changes.