docs(qa): re-ground the activation-ledger checklist items on the tenantless sys_metadata_activation - #15251

Merged
hotlong merged 1 commit into
mainfrom
claude/issue-15154-platform-checklist-activation-ledger
Sep 4, 2026
Merged

docs(qa): re-ground the activation-ledger checklist items on the tenantless sys_metadata_activation#15251
hotlong merged 1 commit into
mainfrom
claude/issue-15154-platform-checklist-activation-ledger

Conversation

@hotlong

Copy link
Copy Markdown
Contributor

Fixes#15154

sys_metadata_activation dropped its reserved organization_id column before it ever
shipped (#15024, PR #15155). Verified against origin/main rather than inferred from the
card: sys-metadata-activation.object.ts declares systemFields: { tenant: false }, the
declared index is { fields: ['metadata_type', 'name'], unique: 'global' }, and
ObjectStoreMetadataActivationStore.list() is scoped by metadata_type and nothing else —
no NULL-organization filter, no org-row skip. The premise holds.

platform-core.activation-ledger-row-contract (revision 1 → 2)

legwasnow
step 2five declared columns incl. organization_id, "NULL on every row"four ledger columns beside id and the audit family; organization_idabsent from the row key set
step 6refusal attributed to the COALESCE'd index (ADR-0120 D3 NULL-collapse)the plain unique: 'global' over two required key parts; D3's collapse kept as history that is no longer reachable
step 7INSERT a row withorganization_id — impossible, no such columnreplaced by a no-tenant-column probe

Step 2 is a real strengthening, not a wording fix. The old spelling cannot be carried
forward at all: once the column is gone, a value check of the shape row.organization_id ?? null answers null either way, so it passes while measuring nothing — green for exactly
the reason it should be red. The key-set assertion is the same inversion #15024 already
applied to the dogfood pin (expect(Object.keys(row)).not.toContain('organization_id'),
with an arrayContaining anti-vacuity control beside it).

Step 7 is replaced, not retired — the judgement call the card flagged, ruled by the PM
on dispatch. ADR-0131 D7 names sys_metadata_activation as reverted before 17.3 and not
returning, which makes "this ledger has no organization column" a load-bearing platform
property; dropping the leg would lose coverage rather than retire an obsolete assertion.
The replacement stays inside the item's established idiom — the same direct-sqlite fixture
class steps 6 and 7 already required, no new checklist mechanism:

  • PRAGMA table_info(sys_metadata_activation) — the column list carries metadata_type /
    name / package_id / active beside the driver's id and the injected audit family,
    and nothing tenant-shaped;
  • an INSERT naming organization_id is refused by sqlite (has no column named organization_id);
  • an anti-vacuity CONTROL: the same statement with that column dropped succeeds, so the
    refusal names the missing column rather than a malformed statement. The
    (metadata_type, name) pair is fresh on purpose, so step 6's unique index cannot be what
    answered.

The negative entries follow the same correction. A resurrected tenant column is now worse
than the shape it replaced: the store no longer filters or skips on read (there is no column
to filter on), so an org-carrying row would be merged straight into the deployment-wide
answer. And a duplicate accepted by the index is no longer diagnosable as the #5030
NULL-distinct hole — that hole needed a nullable tenant column inside the key.

source gains anchors for #systemFields (the opt-out that removes the column rather
than leaving it unwritten — resolveInjectedSystemColumns would provision it by injection
with no field declared) and #list, plus the ADR-0131 D7 citation. ADR-0126 §5's "the org
column is reserved" bullet is marked withdrawn, and §5's operator-gate half is explicitly
recorded as standing.

access-security.activation-write-operator-gate (revision 1 → 2)

Read-back detail only, as the card scoped it. Two sites (step 7 and the inert-gate clause's
verify) asked the runner to see organization_id NULL; they now read the key set, with the
same vacuity warning. The gate itself is untouched and its unit pins are unmodified — the
source citation now says so explicitly, so the next reader does not infer the gate moved with
the withdrawn column bullet.

Both items bump revision and append a history entry, per the README's change lifecycle.

Gates

pnpm check:platform-checklist (deliberately not in lint.yml — maintainer decision;
run by hand). Baseline captured at 1bc3c092abefore any edit, re-run at 96fc81042
after: the output is byte-identical, diff empty. The 4 pre-existing UNCLASSIFIED
coverage problems (batch_endpoints, crud_endpoints, metadata_endpoints,
route_generation) are unchanged — this change adds none and removes none.

Anti-vacuity for that green. Because a checklist edit's gate can go green by not being
read at all, one of the two anchors this change adds was re-pointed at a symbol that does
not exist, proven on disk by grep counts before and after, then measured: the gate went
4 problems → 5, naming sys-metadata-activation.object.ts#thisSymbolDoesNotExist as an
ABSENT SYMBOL. Restored with git checkout HEAD -- (absolute path) and proven byte-identical
(git hash-object equals the HEAD blob 3cb88d94; git diff HEAD and git status --porcelain
both empty; zero residual mutation markers).

Symbol-anchor floor (scripts/checklist-symbol-anchor-baseline.json, shrink-never):
areas/platform-core.json 58 → 60 (two anchors added, the safe direction),
areas/access-security.json 44 → 44. No floor lowered; the baseline file is untouched.

Derived family.node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
let the script derive its own change set (2 committed paths vs merge base 1bc3c092a,
three-dot). It reconciles to 10 runnable families, harvested with --commands. All 10
green at 96fc81042, exit codes captured before any pipe (cmd > file 2>&1; EXIT=$?):

check-ci-filter-parity · check-closing-keyword-parity (+ --self-test) ·
check-comment-mask-corpus · check:doc-formula-expressions · check:cross-package-test-inputs ·
check:doc-authoring · check:nul-bytes · check:refd-timer-probe · check:watch-hint-literal

One NOT MEASURED, then measured.check:doc-formula-expressions first exited 3
PREREQUISITE NOT MET, its own words: "Nothing was measured … It is NOT a finding." It needed
@objectstack/formula and then @objectstack/lint built. Both built, gate re-run, exit 0.
Recorded here rather than reported as a red, since exit 3 says nothing about the tree.

Verify-lock declaration. The two builds went through
bash scripts/pm/os-verify-lock.sh -c ..., which reported UNLOCKED (declared) · no usable flock on this host, so the shared verify lock was NEVER taken and NOTHING was serialized.
Declaring it as the entry point instructs: the wall-clock numbers above are shared-box
readings, not quiet-machine promises.

Not run, deliberately: the repo-wide pnpm lint sweep and the full test suite. This diff
is two JSON data files under docs/qa/; no package source, no test, no gate script changed —
dispatch-gates derived no test family for it, and CI runs the farm exactly once regardless.

Changeset

None, and none is owed: the diff publishes nothing from any released package. The
skip-changeset label is applied on this PR (⛔ not an empty-frontmatter changeset — the gate
rejects those).


Generated by Claude Code

…ntless table
`sys_metadata_activation` dropped its reserved `organization_id` column before it
ever shipped (#15024): the object declares `systemFields: { tenant: false }`, the
declared index is `unique: 'global'` over `(metadata_type, name)`, and
`ObjectStoreMetadataActivationStore` no longer filters reads to NULL-organization
rows or skips org-carrying ones. Three legs of
`platform-core.activation-ledger-row-contract` were written around that column.
- Step 2 asserted five declared columns with `organization_id` NULL on every row.
It now asserts the column is ABSENT from the row's key set. The value spelling
passes vacuously once the column is gone (`row.organization_id ?? null` is
`null` either way), which is why the dogfood pin was inverted into a key-set
assertion rather than carried forward.
- Step 6 (uniqueness) still works and still refuses; only its stated mechanism was
wrong. It now names the plain `unique: 'global'` over two required key parts,
with ADR-0120 D3's COALESCE collapse recorded as history that is no longer
reachable here.
- Step 7 INSERTed a row carrying `organization_id`, so the leg could not be run at
all. It is REPLACED by a no-tenant-column probe — `PRAGMA table_info` plus an
INSERT naming the column, refused, bracketed by a control INSERT that lands
without it — not retired, because ADR-0131 D7 makes "this ledger has no
organization column" a load-bearing platform property.
`access-security.activation-write-operator-gate` changes only its two ledger
read-backs; the operator gate and its unit pins are untouched. ADR-0126 §5's
operator-gate half stands, and the source citation now says so, so the next reader
does not infer the gate moved with the withdrawn column bullet.
Both items bump `revision` and append a `history` entry, per the checklist's
change lifecycle.
Fixes#15154
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@hotlonghotlong added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 4, 2026
@hotlong
hotlong added this pull request to the merge queueSep 4, 2026
Merged via the queue into main with commit 5ab3507Sep 4, 2026
35 checks passed
@hotlong
hotlong deleted the claude/issue-15154-platform-checklist-activation-ledger branch September 4, 2026 08:33
os-zhuang pushed a commit that referenced this pull request Sep 4, 2026
…sertions
`sys_metadata_activation` dropped its reserved `organization_id` column before it
ever shipped (#15024): the object declares `systemFields: { tenant: false }`, the
opt-out that REMOVES the column rather than leaving it unwritten. PR #15251
re-grounded the two items #15154 named. Four siblings still read that column back
and asserted it NULL — a VACUOUS leg, not merely a wrong value: once the column
is gone, `row.organization_id ?? null` answers `null` either way, so the read
passes rather than failing and a runner sees green for exactly the reason it
should be red. Each is inverted into a KEY-SET assertion, the shape #15024 used
on the dogfood pin and PR #15251 carried into step 2.
- platform-core.activation-ledger-registration-home — step 2's row capture and
the no-automation clause's "ONE install-level row (organization_id NULL)". The
row is re-said as DEPLOYMENT-level: with no tenant column there is no second
scope for install-level to be distinguished from. The schema-side probe stays
with the sibling item that owns it.
- api-backend.packaged-action-disabled-dispatch — the disable step's row
confirmation, plus `automated.ref`, which described the dogfood pin as
asserting "ONE install-level row with organization_id NULL". That pin has been
a key-set reading named "writes ONE deployment-level row, and the TABLE has no
tenant column at all" since #15024; the ref now quotes its live name.
- api-backend.action-activation-door-contract — the happy-path step, its
acceptance clause and `automated.ref`. The clause also glossed the column as
"the per-org dimension is reserved and unwritten": ADR-0131 D7 WITHDREW that
ADR-0126 §5 D3 bullet ("a reserved nullable tenant column is the shape D1
forbids") and names this table as reverted before 17.3 and not returning, so
the gloss told a runner the tenant dimension was coming back. The source list
now cites ADR-0131 D7 and marks which half of §5 survives.
- automation.packaged-flow-disable-durable — the ledger read step, the row
clause and its "§5 reserves the column" gloss, the verify line's
NULL-collapsed 'organization' index (it is a plain `unique: 'global'` over two
required key parts; with no tenant column `normalizeDeclaredIndex` has no part
to prepend), and the `source` line still citing "org-carrying rows skipped on
read" and "organization_id never written". The store citation splits so
`#list` carries the read-path correction where the read path lives.
Each item bumps `revision` and appends a `history` entry, per the checklist's
change lifecycle. No item outside this defect class is touched, and no clause of
the four contracts themselves moved — only what a runner records about the row.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs(qa): platform-checklist activation-ledger-row-contract is written around the removed sys_metadata_activation tenant column

1 participant

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

docs(qa): re-ground the activation-ledger checklist items on the tenantless sys_metadata_activation - #15251

Merged
hotlong merged 1 commit into
mainfrom
claude/issue-15154-platform-checklist-activation-ledger
Sep 4, 2026
Merged

docs(qa): re-ground the activation-ledger checklist items on the tenantless sys_metadata_activation#15251
hotlong merged 1 commit into
mainfrom
claude/issue-15154-platform-checklist-activation-ledger

Conversation

@hotlong

Copy link
Copy Markdown
Contributor

Fixes#15154

sys_metadata_activation dropped its reserved organization_id column before it ever
shipped (#15024, PR #15155). Verified against origin/main rather than inferred from the
card: sys-metadata-activation.object.ts declares systemFields: { tenant: false }, the
declared index is { fields: ['metadata_type', 'name'], unique: 'global' }, and
ObjectStoreMetadataActivationStore.list() is scoped by metadata_type and nothing else —
no NULL-organization filter, no org-row skip. The premise holds.

platform-core.activation-ledger-row-contract (revision 1 → 2)

legwasnow
step 2five declared columns incl. organization_id, "NULL on every row"four ledger columns beside id and the audit family; organization_idabsent from the row key set
step 6refusal attributed to the COALESCE'd index (ADR-0120 D3 NULL-collapse)the plain unique: 'global' over two required key parts; D3's collapse kept as history that is no longer reachable
step 7INSERT a row withorganization_id — impossible, no such columnreplaced by a no-tenant-column probe

Step 2 is a real strengthening, not a wording fix. The old spelling cannot be carried
forward at all: once the column is gone, a value check of the shape row.organization_id ?? null answers null either way, so it passes while measuring nothing — green for exactly
the reason it should be red. The key-set assertion is the same inversion #15024 already
applied to the dogfood pin (expect(Object.keys(row)).not.toContain('organization_id'),
with an arrayContaining anti-vacuity control beside it).

Step 7 is replaced, not retired — the judgement call the card flagged, ruled by the PM
on dispatch. ADR-0131 D7 names sys_metadata_activation as reverted before 17.3 and not
returning, which makes "this ledger has no organization column" a load-bearing platform
property; dropping the leg would lose coverage rather than retire an obsolete assertion.
The replacement stays inside the item's established idiom — the same direct-sqlite fixture
class steps 6 and 7 already required, no new checklist mechanism:

  • PRAGMA table_info(sys_metadata_activation) — the column list carries metadata_type /
    name / package_id / active beside the driver's id and the injected audit family,
    and nothing tenant-shaped;
  • an INSERT naming organization_id is refused by sqlite (has no column named organization_id);
  • an anti-vacuity CONTROL: the same statement with that column dropped succeeds, so the
    refusal names the missing column rather than a malformed statement. The
    (metadata_type, name) pair is fresh on purpose, so step 6's unique index cannot be what
    answered.

The negative entries follow the same correction. A resurrected tenant column is now worse
than the shape it replaced: the store no longer filters or skips on read (there is no column
to filter on), so an org-carrying row would be merged straight into the deployment-wide
answer. And a duplicate accepted by the index is no longer diagnosable as the #5030
NULL-distinct hole — that hole needed a nullable tenant column inside the key.

source gains anchors for #systemFields (the opt-out that removes the column rather
than leaving it unwritten — resolveInjectedSystemColumns would provision it by injection
with no field declared) and #list, plus the ADR-0131 D7 citation. ADR-0126 §5's "the org
column is reserved" bullet is marked withdrawn, and §5's operator-gate half is explicitly
recorded as standing.

access-security.activation-write-operator-gate (revision 1 → 2)

Read-back detail only, as the card scoped it. Two sites (step 7 and the inert-gate clause's
verify) asked the runner to see organization_id NULL; they now read the key set, with the
same vacuity warning. The gate itself is untouched and its unit pins are unmodified — the
source citation now says so explicitly, so the next reader does not infer the gate moved with
the withdrawn column bullet.

Both items bump revision and append a history entry, per the README's change lifecycle.

Gates

pnpm check:platform-checklist (deliberately not in lint.yml — maintainer decision;
run by hand). Baseline captured at 1bc3c092abefore any edit, re-run at 96fc81042
after: the output is byte-identical, diff empty. The 4 pre-existing UNCLASSIFIED
coverage problems (batch_endpoints, crud_endpoints, metadata_endpoints,
route_generation) are unchanged — this change adds none and removes none.

Anti-vacuity for that green. Because a checklist edit's gate can go green by not being
read at all, one of the two anchors this change adds was re-pointed at a symbol that does
not exist, proven on disk by grep counts before and after, then measured: the gate went
4 problems → 5, naming sys-metadata-activation.object.ts#thisSymbolDoesNotExist as an
ABSENT SYMBOL. Restored with git checkout HEAD -- (absolute path) and proven byte-identical
(git hash-object equals the HEAD blob 3cb88d94; git diff HEAD and git status --porcelain
both empty; zero residual mutation markers).

Symbol-anchor floor (scripts/checklist-symbol-anchor-baseline.json, shrink-never):
areas/platform-core.json 58 → 60 (two anchors added, the safe direction),
areas/access-security.json 44 → 44. No floor lowered; the baseline file is untouched.

Derived family.node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
let the script derive its own change set (2 committed paths vs merge base 1bc3c092a,
three-dot). It reconciles to 10 runnable families, harvested with --commands. All 10
green at 96fc81042, exit codes captured before any pipe (cmd > file 2>&1; EXIT=$?):

check-ci-filter-parity · check-closing-keyword-parity (+ --self-test) ·
check-comment-mask-corpus · check:doc-formula-expressions · check:cross-package-test-inputs ·
check:doc-authoring · check:nul-bytes · check:refd-timer-probe · check:watch-hint-literal

One NOT MEASURED, then measured.check:doc-formula-expressions first exited 3
PREREQUISITE NOT MET, its own words: "Nothing was measured … It is NOT a finding." It needed
@objectstack/formula and then @objectstack/lint built. Both built, gate re-run, exit 0.
Recorded here rather than reported as a red, since exit 3 says nothing about the tree.

Verify-lock declaration. The two builds went through
bash scripts/pm/os-verify-lock.sh -c ..., which reported UNLOCKED (declared) · no usable flock on this host, so the shared verify lock was NEVER taken and NOTHING was serialized.
Declaring it as the entry point instructs: the wall-clock numbers above are shared-box
readings, not quiet-machine promises.

Not run, deliberately: the repo-wide pnpm lint sweep and the full test suite. This diff
is two JSON data files under docs/qa/; no package source, no test, no gate script changed —
dispatch-gates derived no test family for it, and CI runs the farm exactly once regardless.

Changeset

None, and none is owed: the diff publishes nothing from any released package. The
skip-changeset label is applied on this PR (⛔ not an empty-frontmatter changeset — the gate
rejects those).


Generated by Claude Code

…ntless table
`sys_metadata_activation` dropped its reserved `organization_id` column before it
ever shipped (#15024): the object declares `systemFields: { tenant: false }`, the
declared index is `unique: 'global'` over `(metadata_type, name)`, and
`ObjectStoreMetadataActivationStore` no longer filters reads to NULL-organization
rows or skips org-carrying ones. Three legs of
`platform-core.activation-ledger-row-contract` were written around that column.
- Step 2 asserted five declared columns with `organization_id` NULL on every row.
It now asserts the column is ABSENT from the row's key set. The value spelling
passes vacuously once the column is gone (`row.organization_id ?? null` is
`null` either way), which is why the dogfood pin was inverted into a key-set
assertion rather than carried forward.
- Step 6 (uniqueness) still works and still refuses; only its stated mechanism was
wrong. It now names the plain `unique: 'global'` over two required key parts,
with ADR-0120 D3's COALESCE collapse recorded as history that is no longer
reachable here.
- Step 7 INSERTed a row carrying `organization_id`, so the leg could not be run at
all. It is REPLACED by a no-tenant-column probe — `PRAGMA table_info` plus an
INSERT naming the column, refused, bracketed by a control INSERT that lands
without it — not retired, because ADR-0131 D7 makes "this ledger has no
organization column" a load-bearing platform property.
`access-security.activation-write-operator-gate` changes only its two ledger
read-backs; the operator gate and its unit pins are untouched. ADR-0126 §5's
operator-gate half stands, and the source citation now says so, so the next reader
does not infer the gate moved with the withdrawn column bullet.
Both items bump `revision` and append a `history` entry, per the checklist's
change lifecycle.
Fixes#15154
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@hotlonghotlong added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 4, 2026
@hotlong
hotlong added this pull request to the merge queueSep 4, 2026
Merged via the queue into main with commit 5ab3507Sep 4, 2026
35 checks passed
@hotlong
hotlong deleted the claude/issue-15154-platform-checklist-activation-ledger branch September 4, 2026 08:33
os-zhuang pushed a commit that referenced this pull request Sep 4, 2026
…sertions
`sys_metadata_activation` dropped its reserved `organization_id` column before it
ever shipped (#15024): the object declares `systemFields: { tenant: false }`, the
opt-out that REMOVES the column rather than leaving it unwritten. PR #15251
re-grounded the two items #15154 named. Four siblings still read that column back
and asserted it NULL — a VACUOUS leg, not merely a wrong value: once the column
is gone, `row.organization_id ?? null` answers `null` either way, so the read
passes rather than failing and a runner sees green for exactly the reason it
should be red. Each is inverted into a KEY-SET assertion, the shape #15024 used
on the dogfood pin and PR #15251 carried into step 2.
- platform-core.activation-ledger-registration-home — step 2's row capture and
the no-automation clause's "ONE install-level row (organization_id NULL)". The
row is re-said as DEPLOYMENT-level: with no tenant column there is no second
scope for install-level to be distinguished from. The schema-side probe stays
with the sibling item that owns it.
- api-backend.packaged-action-disabled-dispatch — the disable step's row
confirmation, plus `automated.ref`, which described the dogfood pin as
asserting "ONE install-level row with organization_id NULL". That pin has been
a key-set reading named "writes ONE deployment-level row, and the TABLE has no
tenant column at all" since #15024; the ref now quotes its live name.
- api-backend.action-activation-door-contract — the happy-path step, its
acceptance clause and `automated.ref`. The clause also glossed the column as
"the per-org dimension is reserved and unwritten": ADR-0131 D7 WITHDREW that
ADR-0126 §5 D3 bullet ("a reserved nullable tenant column is the shape D1
forbids") and names this table as reverted before 17.3 and not returning, so
the gloss told a runner the tenant dimension was coming back. The source list
now cites ADR-0131 D7 and marks which half of §5 survives.
- automation.packaged-flow-disable-durable — the ledger read step, the row
clause and its "§5 reserves the column" gloss, the verify line's
NULL-collapsed 'organization' index (it is a plain `unique: 'global'` over two
required key parts; with no tenant column `normalizeDeclaredIndex` has no part
to prepend), and the `source` line still citing "org-carrying rows skipped on
read" and "organization_id never written". The store citation splits so
`#list` carries the read-path correction where the read path lives.
Each item bumps `revision` and appends a `history` entry, per the checklist's
change lifecycle. No item outside this defect class is touched, and no clause of
the four contracts themselves moved — only what a runner records about the row.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs(qa): platform-checklist activation-ledger-row-contract is written around the removed sys_metadata_activation tenant column

1 participant

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

docs(qa): re-ground the activation-ledger checklist items on the tenantless sys_metadata_activation - #15251

Merged
hotlong merged 1 commit into
mainfrom
claude/issue-15154-platform-checklist-activation-ledger
Sep 4, 2026
Merged

docs(qa): re-ground the activation-ledger checklist items on the tenantless sys_metadata_activation#15251
hotlong merged 1 commit into
mainfrom
claude/issue-15154-platform-checklist-activation-ledger

Conversation

@hotlong

Copy link
Copy Markdown
Contributor

Fixes#15154

sys_metadata_activation dropped its reserved organization_id column before it ever
shipped (#15024, PR #15155). Verified against origin/main rather than inferred from the
card: sys-metadata-activation.object.ts declares systemFields: { tenant: false }, the
declared index is { fields: ['metadata_type', 'name'], unique: 'global' }, and
ObjectStoreMetadataActivationStore.list() is scoped by metadata_type and nothing else —
no NULL-organization filter, no org-row skip. The premise holds.

platform-core.activation-ledger-row-contract (revision 1 → 2)

legwasnow
step 2five declared columns incl. organization_id, "NULL on every row"four ledger columns beside id and the audit family; organization_idabsent from the row key set
step 6refusal attributed to the COALESCE'd index (ADR-0120 D3 NULL-collapse)the plain unique: 'global' over two required key parts; D3's collapse kept as history that is no longer reachable
step 7INSERT a row withorganization_id — impossible, no such columnreplaced by a no-tenant-column probe

Step 2 is a real strengthening, not a wording fix. The old spelling cannot be carried
forward at all: once the column is gone, a value check of the shape row.organization_id ?? null answers null either way, so it passes while measuring nothing — green for exactly
the reason it should be red. The key-set assertion is the same inversion #15024 already
applied to the dogfood pin (expect(Object.keys(row)).not.toContain('organization_id'),
with an arrayContaining anti-vacuity control beside it).

Step 7 is replaced, not retired — the judgement call the card flagged, ruled by the PM
on dispatch. ADR-0131 D7 names sys_metadata_activation as reverted before 17.3 and not
returning, which makes "this ledger has no organization column" a load-bearing platform
property; dropping the leg would lose coverage rather than retire an obsolete assertion.
The replacement stays inside the item's established idiom — the same direct-sqlite fixture
class steps 6 and 7 already required, no new checklist mechanism:

  • PRAGMA table_info(sys_metadata_activation) — the column list carries metadata_type /
    name / package_id / active beside the driver's id and the injected audit family,
    and nothing tenant-shaped;
  • an INSERT naming organization_id is refused by sqlite (has no column named organization_id);
  • an anti-vacuity CONTROL: the same statement with that column dropped succeeds, so the
    refusal names the missing column rather than a malformed statement. The
    (metadata_type, name) pair is fresh on purpose, so step 6's unique index cannot be what
    answered.

The negative entries follow the same correction. A resurrected tenant column is now worse
than the shape it replaced: the store no longer filters or skips on read (there is no column
to filter on), so an org-carrying row would be merged straight into the deployment-wide
answer. And a duplicate accepted by the index is no longer diagnosable as the #5030
NULL-distinct hole — that hole needed a nullable tenant column inside the key.

source gains anchors for #systemFields (the opt-out that removes the column rather
than leaving it unwritten — resolveInjectedSystemColumns would provision it by injection
with no field declared) and #list, plus the ADR-0131 D7 citation. ADR-0126 §5's "the org
column is reserved" bullet is marked withdrawn, and §5's operator-gate half is explicitly
recorded as standing.

access-security.activation-write-operator-gate (revision 1 → 2)

Read-back detail only, as the card scoped it. Two sites (step 7 and the inert-gate clause's
verify) asked the runner to see organization_id NULL; they now read the key set, with the
same vacuity warning. The gate itself is untouched and its unit pins are unmodified — the
source citation now says so explicitly, so the next reader does not infer the gate moved with
the withdrawn column bullet.

Both items bump revision and append a history entry, per the README's change lifecycle.

Gates

pnpm check:platform-checklist (deliberately not in lint.yml — maintainer decision;
run by hand). Baseline captured at 1bc3c092abefore any edit, re-run at 96fc81042
after: the output is byte-identical, diff empty. The 4 pre-existing UNCLASSIFIED
coverage problems (batch_endpoints, crud_endpoints, metadata_endpoints,
route_generation) are unchanged — this change adds none and removes none.

Anti-vacuity for that green. Because a checklist edit's gate can go green by not being
read at all, one of the two anchors this change adds was re-pointed at a symbol that does
not exist, proven on disk by grep counts before and after, then measured: the gate went
4 problems → 5, naming sys-metadata-activation.object.ts#thisSymbolDoesNotExist as an
ABSENT SYMBOL. Restored with git checkout HEAD -- (absolute path) and proven byte-identical
(git hash-object equals the HEAD blob 3cb88d94; git diff HEAD and git status --porcelain
both empty; zero residual mutation markers).

Symbol-anchor floor (scripts/checklist-symbol-anchor-baseline.json, shrink-never):
areas/platform-core.json 58 → 60 (two anchors added, the safe direction),
areas/access-security.json 44 → 44. No floor lowered; the baseline file is untouched.

Derived family.node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
let the script derive its own change set (2 committed paths vs merge base 1bc3c092a,
three-dot). It reconciles to 10 runnable families, harvested with --commands. All 10
green at 96fc81042, exit codes captured before any pipe (cmd > file 2>&1; EXIT=$?):

check-ci-filter-parity · check-closing-keyword-parity (+ --self-test) ·
check-comment-mask-corpus · check:doc-formula-expressions · check:cross-package-test-inputs ·
check:doc-authoring · check:nul-bytes · check:refd-timer-probe · check:watch-hint-literal

One NOT MEASURED, then measured.check:doc-formula-expressions first exited 3
PREREQUISITE NOT MET, its own words: "Nothing was measured … It is NOT a finding." It needed
@objectstack/formula and then @objectstack/lint built. Both built, gate re-run, exit 0.
Recorded here rather than reported as a red, since exit 3 says nothing about the tree.

Verify-lock declaration. The two builds went through
bash scripts/pm/os-verify-lock.sh -c ..., which reported UNLOCKED (declared) · no usable flock on this host, so the shared verify lock was NEVER taken and NOTHING was serialized.
Declaring it as the entry point instructs: the wall-clock numbers above are shared-box
readings, not quiet-machine promises.

Not run, deliberately: the repo-wide pnpm lint sweep and the full test suite. This diff
is two JSON data files under docs/qa/; no package source, no test, no gate script changed —
dispatch-gates derived no test family for it, and CI runs the farm exactly once regardless.

Changeset

None, and none is owed: the diff publishes nothing from any released package. The
skip-changeset label is applied on this PR (⛔ not an empty-frontmatter changeset — the gate
rejects those).


Generated by Claude Code

…ntless table
`sys_metadata_activation` dropped its reserved `organization_id` column before it
ever shipped (#15024): the object declares `systemFields: { tenant: false }`, the
declared index is `unique: 'global'` over `(metadata_type, name)`, and
`ObjectStoreMetadataActivationStore` no longer filters reads to NULL-organization
rows or skips org-carrying ones. Three legs of
`platform-core.activation-ledger-row-contract` were written around that column.
- Step 2 asserted five declared columns with `organization_id` NULL on every row.
It now asserts the column is ABSENT from the row's key set. The value spelling
passes vacuously once the column is gone (`row.organization_id ?? null` is
`null` either way), which is why the dogfood pin was inverted into a key-set
assertion rather than carried forward.
- Step 6 (uniqueness) still works and still refuses; only its stated mechanism was
wrong. It now names the plain `unique: 'global'` over two required key parts,
with ADR-0120 D3's COALESCE collapse recorded as history that is no longer
reachable here.
- Step 7 INSERTed a row carrying `organization_id`, so the leg could not be run at
all. It is REPLACED by a no-tenant-column probe — `PRAGMA table_info` plus an
INSERT naming the column, refused, bracketed by a control INSERT that lands
without it — not retired, because ADR-0131 D7 makes "this ledger has no
organization column" a load-bearing platform property.
`access-security.activation-write-operator-gate` changes only its two ledger
read-backs; the operator gate and its unit pins are untouched. ADR-0126 §5's
operator-gate half stands, and the source citation now says so, so the next reader
does not infer the gate moved with the withdrawn column bullet.
Both items bump `revision` and append a `history` entry, per the checklist's
change lifecycle.
Fixes#15154
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@hotlonghotlong added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 4, 2026
@hotlong
hotlong added this pull request to the merge queueSep 4, 2026
Merged via the queue into main with commit 5ab3507Sep 4, 2026
35 checks passed
@hotlong
hotlong deleted the claude/issue-15154-platform-checklist-activation-ledger branch September 4, 2026 08:33
os-zhuang pushed a commit that referenced this pull request Sep 4, 2026
…sertions
`sys_metadata_activation` dropped its reserved `organization_id` column before it
ever shipped (#15024): the object declares `systemFields: { tenant: false }`, the
opt-out that REMOVES the column rather than leaving it unwritten. PR #15251
re-grounded the two items #15154 named. Four siblings still read that column back
and asserted it NULL — a VACUOUS leg, not merely a wrong value: once the column
is gone, `row.organization_id ?? null` answers `null` either way, so the read
passes rather than failing and a runner sees green for exactly the reason it
should be red. Each is inverted into a KEY-SET assertion, the shape #15024 used
on the dogfood pin and PR #15251 carried into step 2.
- platform-core.activation-ledger-registration-home — step 2's row capture and
the no-automation clause's "ONE install-level row (organization_id NULL)". The
row is re-said as DEPLOYMENT-level: with no tenant column there is no second
scope for install-level to be distinguished from. The schema-side probe stays
with the sibling item that owns it.
- api-backend.packaged-action-disabled-dispatch — the disable step's row
confirmation, plus `automated.ref`, which described the dogfood pin as
asserting "ONE install-level row with organization_id NULL". That pin has been
a key-set reading named "writes ONE deployment-level row, and the TABLE has no
tenant column at all" since #15024; the ref now quotes its live name.
- api-backend.action-activation-door-contract — the happy-path step, its
acceptance clause and `automated.ref`. The clause also glossed the column as
"the per-org dimension is reserved and unwritten": ADR-0131 D7 WITHDREW that
ADR-0126 §5 D3 bullet ("a reserved nullable tenant column is the shape D1
forbids") and names this table as reverted before 17.3 and not returning, so
the gloss told a runner the tenant dimension was coming back. The source list
now cites ADR-0131 D7 and marks which half of §5 survives.
- automation.packaged-flow-disable-durable — the ledger read step, the row
clause and its "§5 reserves the column" gloss, the verify line's
NULL-collapsed 'organization' index (it is a plain `unique: 'global'` over two
required key parts; with no tenant column `normalizeDeclaredIndex` has no part
to prepend), and the `source` line still citing "org-carrying rows skipped on
read" and "organization_id never written". The store citation splits so
`#list` carries the read-path correction where the read path lives.
Each item bumps `revision` and appends a `history` entry, per the checklist's
change lifecycle. No item outside this defect class is touched, and no clause of
the four contracts themselves moved — only what a runner records about the row.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs(qa): platform-checklist activation-ledger-row-contract is written around the removed sys_metadata_activation tenant column

1 participant

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

docs(qa): re-ground the activation-ledger checklist items on the tenantless sys_metadata_activation - #15251

Merged
hotlong merged 1 commit into
mainfrom
claude/issue-15154-platform-checklist-activation-ledger
Sep 4, 2026
Merged

docs(qa): re-ground the activation-ledger checklist items on the tenantless sys_metadata_activation#15251
hotlong merged 1 commit into
mainfrom
claude/issue-15154-platform-checklist-activation-ledger

Conversation

@hotlong

Copy link
Copy Markdown
Contributor

Fixes#15154

sys_metadata_activation dropped its reserved organization_id column before it ever
shipped (#15024, PR #15155). Verified against origin/main rather than inferred from the
card: sys-metadata-activation.object.ts declares systemFields: { tenant: false }, the
declared index is { fields: ['metadata_type', 'name'], unique: 'global' }, and
ObjectStoreMetadataActivationStore.list() is scoped by metadata_type and nothing else —
no NULL-organization filter, no org-row skip. The premise holds.

platform-core.activation-ledger-row-contract (revision 1 → 2)

legwasnow
step 2five declared columns incl. organization_id, "NULL on every row"four ledger columns beside id and the audit family; organization_idabsent from the row key set
step 6refusal attributed to the COALESCE'd index (ADR-0120 D3 NULL-collapse)the plain unique: 'global' over two required key parts; D3's collapse kept as history that is no longer reachable
step 7INSERT a row withorganization_id — impossible, no such columnreplaced by a no-tenant-column probe

Step 2 is a real strengthening, not a wording fix. The old spelling cannot be carried
forward at all: once the column is gone, a value check of the shape row.organization_id ?? null answers null either way, so it passes while measuring nothing — green for exactly
the reason it should be red. The key-set assertion is the same inversion #15024 already
applied to the dogfood pin (expect(Object.keys(row)).not.toContain('organization_id'),
with an arrayContaining anti-vacuity control beside it).

Step 7 is replaced, not retired — the judgement call the card flagged, ruled by the PM
on dispatch. ADR-0131 D7 names sys_metadata_activation as reverted before 17.3 and not
returning, which makes "this ledger has no organization column" a load-bearing platform
property; dropping the leg would lose coverage rather than retire an obsolete assertion.
The replacement stays inside the item's established idiom — the same direct-sqlite fixture
class steps 6 and 7 already required, no new checklist mechanism:

  • PRAGMA table_info(sys_metadata_activation) — the column list carries metadata_type /
    name / package_id / active beside the driver's id and the injected audit family,
    and nothing tenant-shaped;
  • an INSERT naming organization_id is refused by sqlite (has no column named organization_id);
  • an anti-vacuity CONTROL: the same statement with that column dropped succeeds, so the
    refusal names the missing column rather than a malformed statement. The
    (metadata_type, name) pair is fresh on purpose, so step 6's unique index cannot be what
    answered.

The negative entries follow the same correction. A resurrected tenant column is now worse
than the shape it replaced: the store no longer filters or skips on read (there is no column
to filter on), so an org-carrying row would be merged straight into the deployment-wide
answer. And a duplicate accepted by the index is no longer diagnosable as the #5030
NULL-distinct hole — that hole needed a nullable tenant column inside the key.

source gains anchors for #systemFields (the opt-out that removes the column rather
than leaving it unwritten — resolveInjectedSystemColumns would provision it by injection
with no field declared) and #list, plus the ADR-0131 D7 citation. ADR-0126 §5's "the org
column is reserved" bullet is marked withdrawn, and §5's operator-gate half is explicitly
recorded as standing.

access-security.activation-write-operator-gate (revision 1 → 2)

Read-back detail only, as the card scoped it. Two sites (step 7 and the inert-gate clause's
verify) asked the runner to see organization_id NULL; they now read the key set, with the
same vacuity warning. The gate itself is untouched and its unit pins are unmodified — the
source citation now says so explicitly, so the next reader does not infer the gate moved with
the withdrawn column bullet.

Both items bump revision and append a history entry, per the README's change lifecycle.

Gates

pnpm check:platform-checklist (deliberately not in lint.yml — maintainer decision;
run by hand). Baseline captured at 1bc3c092abefore any edit, re-run at 96fc81042
after: the output is byte-identical, diff empty. The 4 pre-existing UNCLASSIFIED
coverage problems (batch_endpoints, crud_endpoints, metadata_endpoints,
route_generation) are unchanged — this change adds none and removes none.

Anti-vacuity for that green. Because a checklist edit's gate can go green by not being
read at all, one of the two anchors this change adds was re-pointed at a symbol that does
not exist, proven on disk by grep counts before and after, then measured: the gate went
4 problems → 5, naming sys-metadata-activation.object.ts#thisSymbolDoesNotExist as an
ABSENT SYMBOL. Restored with git checkout HEAD -- (absolute path) and proven byte-identical
(git hash-object equals the HEAD blob 3cb88d94; git diff HEAD and git status --porcelain
both empty; zero residual mutation markers).

Symbol-anchor floor (scripts/checklist-symbol-anchor-baseline.json, shrink-never):
areas/platform-core.json 58 → 60 (two anchors added, the safe direction),
areas/access-security.json 44 → 44. No floor lowered; the baseline file is untouched.

Derived family.node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
let the script derive its own change set (2 committed paths vs merge base 1bc3c092a,
three-dot). It reconciles to 10 runnable families, harvested with --commands. All 10
green at 96fc81042, exit codes captured before any pipe (cmd > file 2>&1; EXIT=$?):

check-ci-filter-parity · check-closing-keyword-parity (+ --self-test) ·
check-comment-mask-corpus · check:doc-formula-expressions · check:cross-package-test-inputs ·
check:doc-authoring · check:nul-bytes · check:refd-timer-probe · check:watch-hint-literal

One NOT MEASURED, then measured.check:doc-formula-expressions first exited 3
PREREQUISITE NOT MET, its own words: "Nothing was measured … It is NOT a finding." It needed
@objectstack/formula and then @objectstack/lint built. Both built, gate re-run, exit 0.
Recorded here rather than reported as a red, since exit 3 says nothing about the tree.

Verify-lock declaration. The two builds went through
bash scripts/pm/os-verify-lock.sh -c ..., which reported UNLOCKED (declared) · no usable flock on this host, so the shared verify lock was NEVER taken and NOTHING was serialized.
Declaring it as the entry point instructs: the wall-clock numbers above are shared-box
readings, not quiet-machine promises.

Not run, deliberately: the repo-wide pnpm lint sweep and the full test suite. This diff
is two JSON data files under docs/qa/; no package source, no test, no gate script changed —
dispatch-gates derived no test family for it, and CI runs the farm exactly once regardless.

Changeset

None, and none is owed: the diff publishes nothing from any released package. The
skip-changeset label is applied on this PR (⛔ not an empty-frontmatter changeset — the gate
rejects those).


Generated by Claude Code

…ntless table
`sys_metadata_activation` dropped its reserved `organization_id` column before it
ever shipped (#15024): the object declares `systemFields: { tenant: false }`, the
declared index is `unique: 'global'` over `(metadata_type, name)`, and
`ObjectStoreMetadataActivationStore` no longer filters reads to NULL-organization
rows or skips org-carrying ones. Three legs of
`platform-core.activation-ledger-row-contract` were written around that column.
- Step 2 asserted five declared columns with `organization_id` NULL on every row.
It now asserts the column is ABSENT from the row's key set. The value spelling
passes vacuously once the column is gone (`row.organization_id ?? null` is
`null` either way), which is why the dogfood pin was inverted into a key-set
assertion rather than carried forward.
- Step 6 (uniqueness) still works and still refuses; only its stated mechanism was
wrong. It now names the plain `unique: 'global'` over two required key parts,
with ADR-0120 D3's COALESCE collapse recorded as history that is no longer
reachable here.
- Step 7 INSERTed a row carrying `organization_id`, so the leg could not be run at
all. It is REPLACED by a no-tenant-column probe — `PRAGMA table_info` plus an
INSERT naming the column, refused, bracketed by a control INSERT that lands
without it — not retired, because ADR-0131 D7 makes "this ledger has no
organization column" a load-bearing platform property.
`access-security.activation-write-operator-gate` changes only its two ledger
read-backs; the operator gate and its unit pins are untouched. ADR-0126 §5's
operator-gate half stands, and the source citation now says so, so the next reader
does not infer the gate moved with the withdrawn column bullet.
Both items bump `revision` and append a `history` entry, per the checklist's
change lifecycle.
Fixes#15154
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@hotlonghotlong added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 4, 2026
@hotlong
hotlong added this pull request to the merge queueSep 4, 2026
Merged via the queue into main with commit 5ab3507Sep 4, 2026
35 checks passed
@hotlong
hotlong deleted the claude/issue-15154-platform-checklist-activation-ledger branch September 4, 2026 08:33
os-zhuang pushed a commit that referenced this pull request Sep 4, 2026
…sertions
`sys_metadata_activation` dropped its reserved `organization_id` column before it
ever shipped (#15024): the object declares `systemFields: { tenant: false }`, the
opt-out that REMOVES the column rather than leaving it unwritten. PR #15251
re-grounded the two items #15154 named. Four siblings still read that column back
and asserted it NULL — a VACUOUS leg, not merely a wrong value: once the column
is gone, `row.organization_id ?? null` answers `null` either way, so the read
passes rather than failing and a runner sees green for exactly the reason it
should be red. Each is inverted into a KEY-SET assertion, the shape #15024 used
on the dogfood pin and PR #15251 carried into step 2.
- platform-core.activation-ledger-registration-home — step 2's row capture and
the no-automation clause's "ONE install-level row (organization_id NULL)". The
row is re-said as DEPLOYMENT-level: with no tenant column there is no second
scope for install-level to be distinguished from. The schema-side probe stays
with the sibling item that owns it.
- api-backend.packaged-action-disabled-dispatch — the disable step's row
confirmation, plus `automated.ref`, which described the dogfood pin as
asserting "ONE install-level row with organization_id NULL". That pin has been
a key-set reading named "writes ONE deployment-level row, and the TABLE has no
tenant column at all" since #15024; the ref now quotes its live name.
- api-backend.action-activation-door-contract — the happy-path step, its
acceptance clause and `automated.ref`. The clause also glossed the column as
"the per-org dimension is reserved and unwritten": ADR-0131 D7 WITHDREW that
ADR-0126 §5 D3 bullet ("a reserved nullable tenant column is the shape D1
forbids") and names this table as reverted before 17.3 and not returning, so
the gloss told a runner the tenant dimension was coming back. The source list
now cites ADR-0131 D7 and marks which half of §5 survives.
- automation.packaged-flow-disable-durable — the ledger read step, the row
clause and its "§5 reserves the column" gloss, the verify line's
NULL-collapsed 'organization' index (it is a plain `unique: 'global'` over two
required key parts; with no tenant column `normalizeDeclaredIndex` has no part
to prepend), and the `source` line still citing "org-carrying rows skipped on
read" and "organization_id never written". The store citation splits so
`#list` carries the read-path correction where the read path lives.
Each item bumps `revision` and appends a `history` entry, per the checklist's
change lifecycle. No item outside this defect class is touched, and no clause of
the four contracts themselves moved — only what a runner records about the row.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs(qa): platform-checklist activation-ledger-row-contract is written around the removed sys_metadata_activation tenant column

1 participant

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

docs(qa): re-ground the activation-ledger checklist items on the tenantless sys_metadata_activation - #15251

Merged
hotlong merged 1 commit into
mainfrom
claude/issue-15154-platform-checklist-activation-ledger
Sep 4, 2026
Merged

docs(qa): re-ground the activation-ledger checklist items on the tenantless sys_metadata_activation#15251
hotlong merged 1 commit into
mainfrom
claude/issue-15154-platform-checklist-activation-ledger

Conversation

@hotlong

Copy link
Copy Markdown
Contributor

Fixes#15154

sys_metadata_activation dropped its reserved organization_id column before it ever
shipped (#15024, PR #15155). Verified against origin/main rather than inferred from the
card: sys-metadata-activation.object.ts declares systemFields: { tenant: false }, the
declared index is { fields: ['metadata_type', 'name'], unique: 'global' }, and
ObjectStoreMetadataActivationStore.list() is scoped by metadata_type and nothing else —
no NULL-organization filter, no org-row skip. The premise holds.

platform-core.activation-ledger-row-contract (revision 1 → 2)

legwasnow
step 2five declared columns incl. organization_id, "NULL on every row"four ledger columns beside id and the audit family; organization_idabsent from the row key set
step 6refusal attributed to the COALESCE'd index (ADR-0120 D3 NULL-collapse)the plain unique: 'global' over two required key parts; D3's collapse kept as history that is no longer reachable
step 7INSERT a row withorganization_id — impossible, no such columnreplaced by a no-tenant-column probe

Step 2 is a real strengthening, not a wording fix. The old spelling cannot be carried
forward at all: once the column is gone, a value check of the shape row.organization_id ?? null answers null either way, so it passes while measuring nothing — green for exactly
the reason it should be red. The key-set assertion is the same inversion #15024 already
applied to the dogfood pin (expect(Object.keys(row)).not.toContain('organization_id'),
with an arrayContaining anti-vacuity control beside it).

Step 7 is replaced, not retired — the judgement call the card flagged, ruled by the PM
on dispatch. ADR-0131 D7 names sys_metadata_activation as reverted before 17.3 and not
returning, which makes "this ledger has no organization column" a load-bearing platform
property; dropping the leg would lose coverage rather than retire an obsolete assertion.
The replacement stays inside the item's established idiom — the same direct-sqlite fixture
class steps 6 and 7 already required, no new checklist mechanism:

  • PRAGMA table_info(sys_metadata_activation) — the column list carries metadata_type /
    name / package_id / active beside the driver's id and the injected audit family,
    and nothing tenant-shaped;
  • an INSERT naming organization_id is refused by sqlite (has no column named organization_id);
  • an anti-vacuity CONTROL: the same statement with that column dropped succeeds, so the
    refusal names the missing column rather than a malformed statement. The
    (metadata_type, name) pair is fresh on purpose, so step 6's unique index cannot be what
    answered.

The negative entries follow the same correction. A resurrected tenant column is now worse
than the shape it replaced: the store no longer filters or skips on read (there is no column
to filter on), so an org-carrying row would be merged straight into the deployment-wide
answer. And a duplicate accepted by the index is no longer diagnosable as the #5030
NULL-distinct hole — that hole needed a nullable tenant column inside the key.

source gains anchors for #systemFields (the opt-out that removes the column rather
than leaving it unwritten — resolveInjectedSystemColumns would provision it by injection
with no field declared) and #list, plus the ADR-0131 D7 citation. ADR-0126 §5's "the org
column is reserved" bullet is marked withdrawn, and §5's operator-gate half is explicitly
recorded as standing.

access-security.activation-write-operator-gate (revision 1 → 2)

Read-back detail only, as the card scoped it. Two sites (step 7 and the inert-gate clause's
verify) asked the runner to see organization_id NULL; they now read the key set, with the
same vacuity warning. The gate itself is untouched and its unit pins are unmodified — the
source citation now says so explicitly, so the next reader does not infer the gate moved with
the withdrawn column bullet.

Both items bump revision and append a history entry, per the README's change lifecycle.

Gates

pnpm check:platform-checklist (deliberately not in lint.yml — maintainer decision;
run by hand). Baseline captured at 1bc3c092abefore any edit, re-run at 96fc81042
after: the output is byte-identical, diff empty. The 4 pre-existing UNCLASSIFIED
coverage problems (batch_endpoints, crud_endpoints, metadata_endpoints,
route_generation) are unchanged — this change adds none and removes none.

Anti-vacuity for that green. Because a checklist edit's gate can go green by not being
read at all, one of the two anchors this change adds was re-pointed at a symbol that does
not exist, proven on disk by grep counts before and after, then measured: the gate went
4 problems → 5, naming sys-metadata-activation.object.ts#thisSymbolDoesNotExist as an
ABSENT SYMBOL. Restored with git checkout HEAD -- (absolute path) and proven byte-identical
(git hash-object equals the HEAD blob 3cb88d94; git diff HEAD and git status --porcelain
both empty; zero residual mutation markers).

Symbol-anchor floor (scripts/checklist-symbol-anchor-baseline.json, shrink-never):
areas/platform-core.json 58 → 60 (two anchors added, the safe direction),
areas/access-security.json 44 → 44. No floor lowered; the baseline file is untouched.

Derived family.node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
let the script derive its own change set (2 committed paths vs merge base 1bc3c092a,
three-dot). It reconciles to 10 runnable families, harvested with --commands. All 10
green at 96fc81042, exit codes captured before any pipe (cmd > file 2>&1; EXIT=$?):

check-ci-filter-parity · check-closing-keyword-parity (+ --self-test) ·
check-comment-mask-corpus · check:doc-formula-expressions · check:cross-package-test-inputs ·
check:doc-authoring · check:nul-bytes · check:refd-timer-probe · check:watch-hint-literal

One NOT MEASURED, then measured.check:doc-formula-expressions first exited 3
PREREQUISITE NOT MET, its own words: "Nothing was measured … It is NOT a finding." It needed
@objectstack/formula and then @objectstack/lint built. Both built, gate re-run, exit 0.
Recorded here rather than reported as a red, since exit 3 says nothing about the tree.

Verify-lock declaration. The two builds went through
bash scripts/pm/os-verify-lock.sh -c ..., which reported UNLOCKED (declared) · no usable flock on this host, so the shared verify lock was NEVER taken and NOTHING was serialized.
Declaring it as the entry point instructs: the wall-clock numbers above are shared-box
readings, not quiet-machine promises.

Not run, deliberately: the repo-wide pnpm lint sweep and the full test suite. This diff
is two JSON data files under docs/qa/; no package source, no test, no gate script changed —
dispatch-gates derived no test family for it, and CI runs the farm exactly once regardless.

Changeset

None, and none is owed: the diff publishes nothing from any released package. The
skip-changeset label is applied on this PR (⛔ not an empty-frontmatter changeset — the gate
rejects those).


Generated by Claude Code

…ntless table
`sys_metadata_activation` dropped its reserved `organization_id` column before it
ever shipped (#15024): the object declares `systemFields: { tenant: false }`, the
declared index is `unique: 'global'` over `(metadata_type, name)`, and
`ObjectStoreMetadataActivationStore` no longer filters reads to NULL-organization
rows or skips org-carrying ones. Three legs of
`platform-core.activation-ledger-row-contract` were written around that column.
- Step 2 asserted five declared columns with `organization_id` NULL on every row.
It now asserts the column is ABSENT from the row's key set. The value spelling
passes vacuously once the column is gone (`row.organization_id ?? null` is
`null` either way), which is why the dogfood pin was inverted into a key-set
assertion rather than carried forward.
- Step 6 (uniqueness) still works and still refuses; only its stated mechanism was
wrong. It now names the plain `unique: 'global'` over two required key parts,
with ADR-0120 D3's COALESCE collapse recorded as history that is no longer
reachable here.
- Step 7 INSERTed a row carrying `organization_id`, so the leg could not be run at
all. It is REPLACED by a no-tenant-column probe — `PRAGMA table_info` plus an
INSERT naming the column, refused, bracketed by a control INSERT that lands
without it — not retired, because ADR-0131 D7 makes "this ledger has no
organization column" a load-bearing platform property.
`access-security.activation-write-operator-gate` changes only its two ledger
read-backs; the operator gate and its unit pins are untouched. ADR-0126 §5's
operator-gate half stands, and the source citation now says so, so the next reader
does not infer the gate moved with the withdrawn column bullet.
Both items bump `revision` and append a `history` entry, per the checklist's
change lifecycle.
Fixes#15154
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@hotlonghotlong added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 4, 2026
@hotlong
hotlong added this pull request to the merge queueSep 4, 2026
Merged via the queue into main with commit 5ab3507Sep 4, 2026
35 checks passed
@hotlong
hotlong deleted the claude/issue-15154-platform-checklist-activation-ledger branch September 4, 2026 08:33
os-zhuang pushed a commit that referenced this pull request Sep 4, 2026
…sertions
`sys_metadata_activation` dropped its reserved `organization_id` column before it
ever shipped (#15024): the object declares `systemFields: { tenant: false }`, the
opt-out that REMOVES the column rather than leaving it unwritten. PR #15251
re-grounded the two items #15154 named. Four siblings still read that column back
and asserted it NULL — a VACUOUS leg, not merely a wrong value: once the column
is gone, `row.organization_id ?? null` answers `null` either way, so the read
passes rather than failing and a runner sees green for exactly the reason it
should be red. Each is inverted into a KEY-SET assertion, the shape #15024 used
on the dogfood pin and PR #15251 carried into step 2.
- platform-core.activation-ledger-registration-home — step 2's row capture and
the no-automation clause's "ONE install-level row (organization_id NULL)". The
row is re-said as DEPLOYMENT-level: with no tenant column there is no second
scope for install-level to be distinguished from. The schema-side probe stays
with the sibling item that owns it.
- api-backend.packaged-action-disabled-dispatch — the disable step's row
confirmation, plus `automated.ref`, which described the dogfood pin as
asserting "ONE install-level row with organization_id NULL". That pin has been
a key-set reading named "writes ONE deployment-level row, and the TABLE has no
tenant column at all" since #15024; the ref now quotes its live name.
- api-backend.action-activation-door-contract — the happy-path step, its
acceptance clause and `automated.ref`. The clause also glossed the column as
"the per-org dimension is reserved and unwritten": ADR-0131 D7 WITHDREW that
ADR-0126 §5 D3 bullet ("a reserved nullable tenant column is the shape D1
forbids") and names this table as reverted before 17.3 and not returning, so
the gloss told a runner the tenant dimension was coming back. The source list
now cites ADR-0131 D7 and marks which half of §5 survives.
- automation.packaged-flow-disable-durable — the ledger read step, the row
clause and its "§5 reserves the column" gloss, the verify line's
NULL-collapsed 'organization' index (it is a plain `unique: 'global'` over two
required key parts; with no tenant column `normalizeDeclaredIndex` has no part
to prepend), and the `source` line still citing "org-carrying rows skipped on
read" and "organization_id never written". The store citation splits so
`#list` carries the read-path correction where the read path lives.
Each item bumps `revision` and appends a `history` entry, per the checklist's
change lifecycle. No item outside this defect class is touched, and no clause of
the four contracts themselves moved — only what a runner records about the row.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs(qa): platform-checklist activation-ledger-row-contract is written around the removed sys_metadata_activation tenant column

1 participant

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

docs(qa): re-ground the activation-ledger checklist items on the tenantless sys_metadata_activation - #15251

Merged
hotlong merged 1 commit into
mainfrom
claude/issue-15154-platform-checklist-activation-ledger
Sep 4, 2026
Merged

docs(qa): re-ground the activation-ledger checklist items on the tenantless sys_metadata_activation#15251
hotlong merged 1 commit into
mainfrom
claude/issue-15154-platform-checklist-activation-ledger

Conversation

@hotlong

Copy link
Copy Markdown
Contributor

Fixes#15154

sys_metadata_activation dropped its reserved organization_id column before it ever
shipped (#15024, PR #15155). Verified against origin/main rather than inferred from the
card: sys-metadata-activation.object.ts declares systemFields: { tenant: false }, the
declared index is { fields: ['metadata_type', 'name'], unique: 'global' }, and
ObjectStoreMetadataActivationStore.list() is scoped by metadata_type and nothing else —
no NULL-organization filter, no org-row skip. The premise holds.

platform-core.activation-ledger-row-contract (revision 1 → 2)

legwasnow
step 2five declared columns incl. organization_id, "NULL on every row"four ledger columns beside id and the audit family; organization_idabsent from the row key set
step 6refusal attributed to the COALESCE'd index (ADR-0120 D3 NULL-collapse)the plain unique: 'global' over two required key parts; D3's collapse kept as history that is no longer reachable
step 7INSERT a row withorganization_id — impossible, no such columnreplaced by a no-tenant-column probe

Step 2 is a real strengthening, not a wording fix. The old spelling cannot be carried
forward at all: once the column is gone, a value check of the shape row.organization_id ?? null answers null either way, so it passes while measuring nothing — green for exactly
the reason it should be red. The key-set assertion is the same inversion #15024 already
applied to the dogfood pin (expect(Object.keys(row)).not.toContain('organization_id'),
with an arrayContaining anti-vacuity control beside it).

Step 7 is replaced, not retired — the judgement call the card flagged, ruled by the PM
on dispatch. ADR-0131 D7 names sys_metadata_activation as reverted before 17.3 and not
returning, which makes "this ledger has no organization column" a load-bearing platform
property; dropping the leg would lose coverage rather than retire an obsolete assertion.
The replacement stays inside the item's established idiom — the same direct-sqlite fixture
class steps 6 and 7 already required, no new checklist mechanism:

  • PRAGMA table_info(sys_metadata_activation) — the column list carries metadata_type /
    name / package_id / active beside the driver's id and the injected audit family,
    and nothing tenant-shaped;
  • an INSERT naming organization_id is refused by sqlite (has no column named organization_id);
  • an anti-vacuity CONTROL: the same statement with that column dropped succeeds, so the
    refusal names the missing column rather than a malformed statement. The
    (metadata_type, name) pair is fresh on purpose, so step 6's unique index cannot be what
    answered.

The negative entries follow the same correction. A resurrected tenant column is now worse
than the shape it replaced: the store no longer filters or skips on read (there is no column
to filter on), so an org-carrying row would be merged straight into the deployment-wide
answer. And a duplicate accepted by the index is no longer diagnosable as the #5030
NULL-distinct hole — that hole needed a nullable tenant column inside the key.

source gains anchors for #systemFields (the opt-out that removes the column rather
than leaving it unwritten — resolveInjectedSystemColumns would provision it by injection
with no field declared) and #list, plus the ADR-0131 D7 citation. ADR-0126 §5's "the org
column is reserved" bullet is marked withdrawn, and §5's operator-gate half is explicitly
recorded as standing.

access-security.activation-write-operator-gate (revision 1 → 2)

Read-back detail only, as the card scoped it. Two sites (step 7 and the inert-gate clause's
verify) asked the runner to see organization_id NULL; they now read the key set, with the
same vacuity warning. The gate itself is untouched and its unit pins are unmodified — the
source citation now says so explicitly, so the next reader does not infer the gate moved with
the withdrawn column bullet.

Both items bump revision and append a history entry, per the README's change lifecycle.

Gates

pnpm check:platform-checklist (deliberately not in lint.yml — maintainer decision;
run by hand). Baseline captured at 1bc3c092abefore any edit, re-run at 96fc81042
after: the output is byte-identical, diff empty. The 4 pre-existing UNCLASSIFIED
coverage problems (batch_endpoints, crud_endpoints, metadata_endpoints,
route_generation) are unchanged — this change adds none and removes none.

Anti-vacuity for that green. Because a checklist edit's gate can go green by not being
read at all, one of the two anchors this change adds was re-pointed at a symbol that does
not exist, proven on disk by grep counts before and after, then measured: the gate went
4 problems → 5, naming sys-metadata-activation.object.ts#thisSymbolDoesNotExist as an
ABSENT SYMBOL. Restored with git checkout HEAD -- (absolute path) and proven byte-identical
(git hash-object equals the HEAD blob 3cb88d94; git diff HEAD and git status --porcelain
both empty; zero residual mutation markers).

Symbol-anchor floor (scripts/checklist-symbol-anchor-baseline.json, shrink-never):
areas/platform-core.json 58 → 60 (two anchors added, the safe direction),
areas/access-security.json 44 → 44. No floor lowered; the baseline file is untouched.

Derived family.node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
let the script derive its own change set (2 committed paths vs merge base 1bc3c092a,
three-dot). It reconciles to 10 runnable families, harvested with --commands. All 10
green at 96fc81042, exit codes captured before any pipe (cmd > file 2>&1; EXIT=$?):

check-ci-filter-parity · check-closing-keyword-parity (+ --self-test) ·
check-comment-mask-corpus · check:doc-formula-expressions · check:cross-package-test-inputs ·
check:doc-authoring · check:nul-bytes · check:refd-timer-probe · check:watch-hint-literal

One NOT MEASURED, then measured.check:doc-formula-expressions first exited 3
PREREQUISITE NOT MET, its own words: "Nothing was measured … It is NOT a finding." It needed
@objectstack/formula and then @objectstack/lint built. Both built, gate re-run, exit 0.
Recorded here rather than reported as a red, since exit 3 says nothing about the tree.

Verify-lock declaration. The two builds went through
bash scripts/pm/os-verify-lock.sh -c ..., which reported UNLOCKED (declared) · no usable flock on this host, so the shared verify lock was NEVER taken and NOTHING was serialized.
Declaring it as the entry point instructs: the wall-clock numbers above are shared-box
readings, not quiet-machine promises.

Not run, deliberately: the repo-wide pnpm lint sweep and the full test suite. This diff
is two JSON data files under docs/qa/; no package source, no test, no gate script changed —
dispatch-gates derived no test family for it, and CI runs the farm exactly once regardless.

Changeset

None, and none is owed: the diff publishes nothing from any released package. The
skip-changeset label is applied on this PR (⛔ not an empty-frontmatter changeset — the gate
rejects those).


Generated by Claude Code

…ntless table
`sys_metadata_activation` dropped its reserved `organization_id` column before it
ever shipped (#15024): the object declares `systemFields: { tenant: false }`, the
declared index is `unique: 'global'` over `(metadata_type, name)`, and
`ObjectStoreMetadataActivationStore` no longer filters reads to NULL-organization
rows or skips org-carrying ones. Three legs of
`platform-core.activation-ledger-row-contract` were written around that column.
- Step 2 asserted five declared columns with `organization_id` NULL on every row.
It now asserts the column is ABSENT from the row's key set. The value spelling
passes vacuously once the column is gone (`row.organization_id ?? null` is
`null` either way), which is why the dogfood pin was inverted into a key-set
assertion rather than carried forward.
- Step 6 (uniqueness) still works and still refuses; only its stated mechanism was
wrong. It now names the plain `unique: 'global'` over two required key parts,
with ADR-0120 D3's COALESCE collapse recorded as history that is no longer
reachable here.
- Step 7 INSERTed a row carrying `organization_id`, so the leg could not be run at
all. It is REPLACED by a no-tenant-column probe — `PRAGMA table_info` plus an
INSERT naming the column, refused, bracketed by a control INSERT that lands
without it — not retired, because ADR-0131 D7 makes "this ledger has no
organization column" a load-bearing platform property.
`access-security.activation-write-operator-gate` changes only its two ledger
read-backs; the operator gate and its unit pins are untouched. ADR-0126 §5's
operator-gate half stands, and the source citation now says so, so the next reader
does not infer the gate moved with the withdrawn column bullet.
Both items bump `revision` and append a `history` entry, per the checklist's
change lifecycle.
Fixes#15154
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@hotlonghotlong added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 4, 2026
@hotlong
hotlong added this pull request to the merge queueSep 4, 2026
Merged via the queue into main with commit 5ab3507Sep 4, 2026
35 checks passed
@hotlong
hotlong deleted the claude/issue-15154-platform-checklist-activation-ledger branch September 4, 2026 08:33
os-zhuang pushed a commit that referenced this pull request Sep 4, 2026
…sertions
`sys_metadata_activation` dropped its reserved `organization_id` column before it
ever shipped (#15024): the object declares `systemFields: { tenant: false }`, the
opt-out that REMOVES the column rather than leaving it unwritten. PR #15251
re-grounded the two items #15154 named. Four siblings still read that column back
and asserted it NULL — a VACUOUS leg, not merely a wrong value: once the column
is gone, `row.organization_id ?? null` answers `null` either way, so the read
passes rather than failing and a runner sees green for exactly the reason it
should be red. Each is inverted into a KEY-SET assertion, the shape #15024 used
on the dogfood pin and PR #15251 carried into step 2.
- platform-core.activation-ledger-registration-home — step 2's row capture and
the no-automation clause's "ONE install-level row (organization_id NULL)". The
row is re-said as DEPLOYMENT-level: with no tenant column there is no second
scope for install-level to be distinguished from. The schema-side probe stays
with the sibling item that owns it.
- api-backend.packaged-action-disabled-dispatch — the disable step's row
confirmation, plus `automated.ref`, which described the dogfood pin as
asserting "ONE install-level row with organization_id NULL". That pin has been
a key-set reading named "writes ONE deployment-level row, and the TABLE has no
tenant column at all" since #15024; the ref now quotes its live name.
- api-backend.action-activation-door-contract — the happy-path step, its
acceptance clause and `automated.ref`. The clause also glossed the column as
"the per-org dimension is reserved and unwritten": ADR-0131 D7 WITHDREW that
ADR-0126 §5 D3 bullet ("a reserved nullable tenant column is the shape D1
forbids") and names this table as reverted before 17.3 and not returning, so
the gloss told a runner the tenant dimension was coming back. The source list
now cites ADR-0131 D7 and marks which half of §5 survives.
- automation.packaged-flow-disable-durable — the ledger read step, the row
clause and its "§5 reserves the column" gloss, the verify line's
NULL-collapsed 'organization' index (it is a plain `unique: 'global'` over two
required key parts; with no tenant column `normalizeDeclaredIndex` has no part
to prepend), and the `source` line still citing "org-carrying rows skipped on
read" and "organization_id never written". The store citation splits so
`#list` carries the read-path correction where the read path lives.
Each item bumps `revision` and appends a `history` entry, per the checklist's
change lifecycle. No item outside this defect class is touched, and no clause of
the four contracts themselves moved — only what a runner records about the row.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs(qa): platform-checklist activation-ledger-row-contract is written around the removed sys_metadata_activation tenant column

1 participant

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

docs(qa): re-ground the activation-ledger checklist items on the tenantless sys_metadata_activation - #15251

Merged
hotlong merged 1 commit into
mainfrom
claude/issue-15154-platform-checklist-activation-ledger
Sep 4, 2026
Merged

docs(qa): re-ground the activation-ledger checklist items on the tenantless sys_metadata_activation#15251
hotlong merged 1 commit into
mainfrom
claude/issue-15154-platform-checklist-activation-ledger

Conversation

@hotlong

Copy link
Copy Markdown
Contributor

Fixes#15154

sys_metadata_activation dropped its reserved organization_id column before it ever
shipped (#15024, PR #15155). Verified against origin/main rather than inferred from the
card: sys-metadata-activation.object.ts declares systemFields: { tenant: false }, the
declared index is { fields: ['metadata_type', 'name'], unique: 'global' }, and
ObjectStoreMetadataActivationStore.list() is scoped by metadata_type and nothing else —
no NULL-organization filter, no org-row skip. The premise holds.

platform-core.activation-ledger-row-contract (revision 1 → 2)

legwasnow
step 2five declared columns incl. organization_id, "NULL on every row"four ledger columns beside id and the audit family; organization_idabsent from the row key set
step 6refusal attributed to the COALESCE'd index (ADR-0120 D3 NULL-collapse)the plain unique: 'global' over two required key parts; D3's collapse kept as history that is no longer reachable
step 7INSERT a row withorganization_id — impossible, no such columnreplaced by a no-tenant-column probe

Step 2 is a real strengthening, not a wording fix. The old spelling cannot be carried
forward at all: once the column is gone, a value check of the shape row.organization_id ?? null answers null either way, so it passes while measuring nothing — green for exactly
the reason it should be red. The key-set assertion is the same inversion #15024 already
applied to the dogfood pin (expect(Object.keys(row)).not.toContain('organization_id'),
with an arrayContaining anti-vacuity control beside it).

Step 7 is replaced, not retired — the judgement call the card flagged, ruled by the PM
on dispatch. ADR-0131 D7 names sys_metadata_activation as reverted before 17.3 and not
returning, which makes "this ledger has no organization column" a load-bearing platform
property; dropping the leg would lose coverage rather than retire an obsolete assertion.
The replacement stays inside the item's established idiom — the same direct-sqlite fixture
class steps 6 and 7 already required, no new checklist mechanism:

  • PRAGMA table_info(sys_metadata_activation) — the column list carries metadata_type /
    name / package_id / active beside the driver's id and the injected audit family,
    and nothing tenant-shaped;
  • an INSERT naming organization_id is refused by sqlite (has no column named organization_id);
  • an anti-vacuity CONTROL: the same statement with that column dropped succeeds, so the
    refusal names the missing column rather than a malformed statement. The
    (metadata_type, name) pair is fresh on purpose, so step 6's unique index cannot be what
    answered.

The negative entries follow the same correction. A resurrected tenant column is now worse
than the shape it replaced: the store no longer filters or skips on read (there is no column
to filter on), so an org-carrying row would be merged straight into the deployment-wide
answer. And a duplicate accepted by the index is no longer diagnosable as the #5030
NULL-distinct hole — that hole needed a nullable tenant column inside the key.

source gains anchors for #systemFields (the opt-out that removes the column rather
than leaving it unwritten — resolveInjectedSystemColumns would provision it by injection
with no field declared) and #list, plus the ADR-0131 D7 citation. ADR-0126 §5's "the org
column is reserved" bullet is marked withdrawn, and §5's operator-gate half is explicitly
recorded as standing.

access-security.activation-write-operator-gate (revision 1 → 2)

Read-back detail only, as the card scoped it. Two sites (step 7 and the inert-gate clause's
verify) asked the runner to see organization_id NULL; they now read the key set, with the
same vacuity warning. The gate itself is untouched and its unit pins are unmodified — the
source citation now says so explicitly, so the next reader does not infer the gate moved with
the withdrawn column bullet.

Both items bump revision and append a history entry, per the README's change lifecycle.

Gates

pnpm check:platform-checklist (deliberately not in lint.yml — maintainer decision;
run by hand). Baseline captured at 1bc3c092abefore any edit, re-run at 96fc81042
after: the output is byte-identical, diff empty. The 4 pre-existing UNCLASSIFIED
coverage problems (batch_endpoints, crud_endpoints, metadata_endpoints,
route_generation) are unchanged — this change adds none and removes none.

Anti-vacuity for that green. Because a checklist edit's gate can go green by not being
read at all, one of the two anchors this change adds was re-pointed at a symbol that does
not exist, proven on disk by grep counts before and after, then measured: the gate went
4 problems → 5, naming sys-metadata-activation.object.ts#thisSymbolDoesNotExist as an
ABSENT SYMBOL. Restored with git checkout HEAD -- (absolute path) and proven byte-identical
(git hash-object equals the HEAD blob 3cb88d94; git diff HEAD and git status --porcelain
both empty; zero residual mutation markers).

Symbol-anchor floor (scripts/checklist-symbol-anchor-baseline.json, shrink-never):
areas/platform-core.json 58 → 60 (two anchors added, the safe direction),
areas/access-security.json 44 → 44. No floor lowered; the baseline file is untouched.

Derived family.node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
let the script derive its own change set (2 committed paths vs merge base 1bc3c092a,
three-dot). It reconciles to 10 runnable families, harvested with --commands. All 10
green at 96fc81042, exit codes captured before any pipe (cmd > file 2>&1; EXIT=$?):

check-ci-filter-parity · check-closing-keyword-parity (+ --self-test) ·
check-comment-mask-corpus · check:doc-formula-expressions · check:cross-package-test-inputs ·
check:doc-authoring · check:nul-bytes · check:refd-timer-probe · check:watch-hint-literal

One NOT MEASURED, then measured.check:doc-formula-expressions first exited 3
PREREQUISITE NOT MET, its own words: "Nothing was measured … It is NOT a finding." It needed
@objectstack/formula and then @objectstack/lint built. Both built, gate re-run, exit 0.
Recorded here rather than reported as a red, since exit 3 says nothing about the tree.

Verify-lock declaration. The two builds went through
bash scripts/pm/os-verify-lock.sh -c ..., which reported UNLOCKED (declared) · no usable flock on this host, so the shared verify lock was NEVER taken and NOTHING was serialized.
Declaring it as the entry point instructs: the wall-clock numbers above are shared-box
readings, not quiet-machine promises.

Not run, deliberately: the repo-wide pnpm lint sweep and the full test suite. This diff
is two JSON data files under docs/qa/; no package source, no test, no gate script changed —
dispatch-gates derived no test family for it, and CI runs the farm exactly once regardless.

Changeset

None, and none is owed: the diff publishes nothing from any released package. The
skip-changeset label is applied on this PR (⛔ not an empty-frontmatter changeset — the gate
rejects those).


Generated by Claude Code

…ntless table
`sys_metadata_activation` dropped its reserved `organization_id` column before it
ever shipped (#15024): the object declares `systemFields: { tenant: false }`, the
declared index is `unique: 'global'` over `(metadata_type, name)`, and
`ObjectStoreMetadataActivationStore` no longer filters reads to NULL-organization
rows or skips org-carrying ones. Three legs of
`platform-core.activation-ledger-row-contract` were written around that column.
- Step 2 asserted five declared columns with `organization_id` NULL on every row.
It now asserts the column is ABSENT from the row's key set. The value spelling
passes vacuously once the column is gone (`row.organization_id ?? null` is
`null` either way), which is why the dogfood pin was inverted into a key-set
assertion rather than carried forward.
- Step 6 (uniqueness) still works and still refuses; only its stated mechanism was
wrong. It now names the plain `unique: 'global'` over two required key parts,
with ADR-0120 D3's COALESCE collapse recorded as history that is no longer
reachable here.
- Step 7 INSERTed a row carrying `organization_id`, so the leg could not be run at
all. It is REPLACED by a no-tenant-column probe — `PRAGMA table_info` plus an
INSERT naming the column, refused, bracketed by a control INSERT that lands
without it — not retired, because ADR-0131 D7 makes "this ledger has no
organization column" a load-bearing platform property.
`access-security.activation-write-operator-gate` changes only its two ledger
read-backs; the operator gate and its unit pins are untouched. ADR-0126 §5's
operator-gate half stands, and the source citation now says so, so the next reader
does not infer the gate moved with the withdrawn column bullet.
Both items bump `revision` and append a `history` entry, per the checklist's
change lifecycle.
Fixes#15154
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@hotlonghotlong added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 4, 2026
@hotlong
hotlong added this pull request to the merge queueSep 4, 2026
Merged via the queue into main with commit 5ab3507Sep 4, 2026
35 checks passed
@hotlong
hotlong deleted the claude/issue-15154-platform-checklist-activation-ledger branch September 4, 2026 08:33
os-zhuang pushed a commit that referenced this pull request Sep 4, 2026
…sertions
`sys_metadata_activation` dropped its reserved `organization_id` column before it
ever shipped (#15024): the object declares `systemFields: { tenant: false }`, the
opt-out that REMOVES the column rather than leaving it unwritten. PR #15251
re-grounded the two items #15154 named. Four siblings still read that column back
and asserted it NULL — a VACUOUS leg, not merely a wrong value: once the column
is gone, `row.organization_id ?? null` answers `null` either way, so the read
passes rather than failing and a runner sees green for exactly the reason it
should be red. Each is inverted into a KEY-SET assertion, the shape #15024 used
on the dogfood pin and PR #15251 carried into step 2.
- platform-core.activation-ledger-registration-home — step 2's row capture and
the no-automation clause's "ONE install-level row (organization_id NULL)". The
row is re-said as DEPLOYMENT-level: with no tenant column there is no second
scope for install-level to be distinguished from. The schema-side probe stays
with the sibling item that owns it.
- api-backend.packaged-action-disabled-dispatch — the disable step's row
confirmation, plus `automated.ref`, which described the dogfood pin as
asserting "ONE install-level row with organization_id NULL". That pin has been
a key-set reading named "writes ONE deployment-level row, and the TABLE has no
tenant column at all" since #15024; the ref now quotes its live name.
- api-backend.action-activation-door-contract — the happy-path step, its
acceptance clause and `automated.ref`. The clause also glossed the column as
"the per-org dimension is reserved and unwritten": ADR-0131 D7 WITHDREW that
ADR-0126 §5 D3 bullet ("a reserved nullable tenant column is the shape D1
forbids") and names this table as reverted before 17.3 and not returning, so
the gloss told a runner the tenant dimension was coming back. The source list
now cites ADR-0131 D7 and marks which half of §5 survives.
- automation.packaged-flow-disable-durable — the ledger read step, the row
clause and its "§5 reserves the column" gloss, the verify line's
NULL-collapsed 'organization' index (it is a plain `unique: 'global'` over two
required key parts; with no tenant column `normalizeDeclaredIndex` has no part
to prepend), and the `source` line still citing "org-carrying rows skipped on
read" and "organization_id never written". The store citation splits so
`#list` carries the read-path correction where the read path lives.
Each item bumps `revision` and appends a `history` entry, per the checklist's
change lifecycle. No item outside this defect class is touched, and no clause of
the four contracts themselves moved — only what a runner records about the row.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs(qa): platform-checklist activation-ledger-row-contract is written around the removed sys_metadata_activation tenant column

1 participant

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

docs(qa): re-ground the activation-ledger checklist items on the tenantless sys_metadata_activation - #15251

Merged
hotlong merged 1 commit into
mainfrom
claude/issue-15154-platform-checklist-activation-ledger
Sep 4, 2026
Merged

docs(qa): re-ground the activation-ledger checklist items on the tenantless sys_metadata_activation#15251
hotlong merged 1 commit into
mainfrom
claude/issue-15154-platform-checklist-activation-ledger

Conversation

@hotlong

Copy link
Copy Markdown
Contributor

Fixes#15154

sys_metadata_activation dropped its reserved organization_id column before it ever
shipped (#15024, PR #15155). Verified against origin/main rather than inferred from the
card: sys-metadata-activation.object.ts declares systemFields: { tenant: false }, the
declared index is { fields: ['metadata_type', 'name'], unique: 'global' }, and
ObjectStoreMetadataActivationStore.list() is scoped by metadata_type and nothing else —
no NULL-organization filter, no org-row skip. The premise holds.

platform-core.activation-ledger-row-contract (revision 1 → 2)

legwasnow
step 2five declared columns incl. organization_id, "NULL on every row"four ledger columns beside id and the audit family; organization_idabsent from the row key set
step 6refusal attributed to the COALESCE'd index (ADR-0120 D3 NULL-collapse)the plain unique: 'global' over two required key parts; D3's collapse kept as history that is no longer reachable
step 7INSERT a row withorganization_id — impossible, no such columnreplaced by a no-tenant-column probe

Step 2 is a real strengthening, not a wording fix. The old spelling cannot be carried
forward at all: once the column is gone, a value check of the shape row.organization_id ?? null answers null either way, so it passes while measuring nothing — green for exactly
the reason it should be red. The key-set assertion is the same inversion #15024 already
applied to the dogfood pin (expect(Object.keys(row)).not.toContain('organization_id'),
with an arrayContaining anti-vacuity control beside it).

Step 7 is replaced, not retired — the judgement call the card flagged, ruled by the PM
on dispatch. ADR-0131 D7 names sys_metadata_activation as reverted before 17.3 and not
returning, which makes "this ledger has no organization column" a load-bearing platform
property; dropping the leg would lose coverage rather than retire an obsolete assertion.
The replacement stays inside the item's established idiom — the same direct-sqlite fixture
class steps 6 and 7 already required, no new checklist mechanism:

  • PRAGMA table_info(sys_metadata_activation) — the column list carries metadata_type /
    name / package_id / active beside the driver's id and the injected audit family,
    and nothing tenant-shaped;
  • an INSERT naming organization_id is refused by sqlite (has no column named organization_id);
  • an anti-vacuity CONTROL: the same statement with that column dropped succeeds, so the
    refusal names the missing column rather than a malformed statement. The
    (metadata_type, name) pair is fresh on purpose, so step 6's unique index cannot be what
    answered.

The negative entries follow the same correction. A resurrected tenant column is now worse
than the shape it replaced: the store no longer filters or skips on read (there is no column
to filter on), so an org-carrying row would be merged straight into the deployment-wide
answer. And a duplicate accepted by the index is no longer diagnosable as the #5030
NULL-distinct hole — that hole needed a nullable tenant column inside the key.

source gains anchors for #systemFields (the opt-out that removes the column rather
than leaving it unwritten — resolveInjectedSystemColumns would provision it by injection
with no field declared) and #list, plus the ADR-0131 D7 citation. ADR-0126 §5's "the org
column is reserved" bullet is marked withdrawn, and §5's operator-gate half is explicitly
recorded as standing.

access-security.activation-write-operator-gate (revision 1 → 2)

Read-back detail only, as the card scoped it. Two sites (step 7 and the inert-gate clause's
verify) asked the runner to see organization_id NULL; they now read the key set, with the
same vacuity warning. The gate itself is untouched and its unit pins are unmodified — the
source citation now says so explicitly, so the next reader does not infer the gate moved with
the withdrawn column bullet.

Both items bump revision and append a history entry, per the README's change lifecycle.

Gates

pnpm check:platform-checklist (deliberately not in lint.yml — maintainer decision;
run by hand). Baseline captured at 1bc3c092abefore any edit, re-run at 96fc81042
after: the output is byte-identical, diff empty. The 4 pre-existing UNCLASSIFIED
coverage problems (batch_endpoints, crud_endpoints, metadata_endpoints,
route_generation) are unchanged — this change adds none and removes none.

Anti-vacuity for that green. Because a checklist edit's gate can go green by not being
read at all, one of the two anchors this change adds was re-pointed at a symbol that does
not exist, proven on disk by grep counts before and after, then measured: the gate went
4 problems → 5, naming sys-metadata-activation.object.ts#thisSymbolDoesNotExist as an
ABSENT SYMBOL. Restored with git checkout HEAD -- (absolute path) and proven byte-identical
(git hash-object equals the HEAD blob 3cb88d94; git diff HEAD and git status --porcelain
both empty; zero residual mutation markers).

Symbol-anchor floor (scripts/checklist-symbol-anchor-baseline.json, shrink-never):
areas/platform-core.json 58 → 60 (two anchors added, the safe direction),
areas/access-security.json 44 → 44. No floor lowered; the baseline file is untouched.

Derived family.node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
let the script derive its own change set (2 committed paths vs merge base 1bc3c092a,
three-dot). It reconciles to 10 runnable families, harvested with --commands. All 10
green at 96fc81042, exit codes captured before any pipe (cmd > file 2>&1; EXIT=$?):

check-ci-filter-parity · check-closing-keyword-parity (+ --self-test) ·
check-comment-mask-corpus · check:doc-formula-expressions · check:cross-package-test-inputs ·
check:doc-authoring · check:nul-bytes · check:refd-timer-probe · check:watch-hint-literal

One NOT MEASURED, then measured.check:doc-formula-expressions first exited 3
PREREQUISITE NOT MET, its own words: "Nothing was measured … It is NOT a finding." It needed
@objectstack/formula and then @objectstack/lint built. Both built, gate re-run, exit 0.
Recorded here rather than reported as a red, since exit 3 says nothing about the tree.

Verify-lock declaration. The two builds went through
bash scripts/pm/os-verify-lock.sh -c ..., which reported UNLOCKED (declared) · no usable flock on this host, so the shared verify lock was NEVER taken and NOTHING was serialized.
Declaring it as the entry point instructs: the wall-clock numbers above are shared-box
readings, not quiet-machine promises.

Not run, deliberately: the repo-wide pnpm lint sweep and the full test suite. This diff
is two JSON data files under docs/qa/; no package source, no test, no gate script changed —
dispatch-gates derived no test family for it, and CI runs the farm exactly once regardless.

Changeset

None, and none is owed: the diff publishes nothing from any released package. The
skip-changeset label is applied on this PR (⛔ not an empty-frontmatter changeset — the gate
rejects those).


Generated by Claude Code

…ntless table
`sys_metadata_activation` dropped its reserved `organization_id` column before it
ever shipped (#15024): the object declares `systemFields: { tenant: false }`, the
declared index is `unique: 'global'` over `(metadata_type, name)`, and
`ObjectStoreMetadataActivationStore` no longer filters reads to NULL-organization
rows or skips org-carrying ones. Three legs of
`platform-core.activation-ledger-row-contract` were written around that column.
- Step 2 asserted five declared columns with `organization_id` NULL on every row.
It now asserts the column is ABSENT from the row's key set. The value spelling
passes vacuously once the column is gone (`row.organization_id ?? null` is
`null` either way), which is why the dogfood pin was inverted into a key-set
assertion rather than carried forward.
- Step 6 (uniqueness) still works and still refuses; only its stated mechanism was
wrong. It now names the plain `unique: 'global'` over two required key parts,
with ADR-0120 D3's COALESCE collapse recorded as history that is no longer
reachable here.
- Step 7 INSERTed a row carrying `organization_id`, so the leg could not be run at
all. It is REPLACED by a no-tenant-column probe — `PRAGMA table_info` plus an
INSERT naming the column, refused, bracketed by a control INSERT that lands
without it — not retired, because ADR-0131 D7 makes "this ledger has no
organization column" a load-bearing platform property.
`access-security.activation-write-operator-gate` changes only its two ledger
read-backs; the operator gate and its unit pins are untouched. ADR-0126 §5's
operator-gate half stands, and the source citation now says so, so the next reader
does not infer the gate moved with the withdrawn column bullet.
Both items bump `revision` and append a `history` entry, per the checklist's
change lifecycle.
Fixes#15154
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@hotlonghotlong added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 4, 2026
@hotlong
hotlong added this pull request to the merge queueSep 4, 2026
Merged via the queue into main with commit 5ab3507Sep 4, 2026
35 checks passed
@hotlong
hotlong deleted the claude/issue-15154-platform-checklist-activation-ledger branch September 4, 2026 08:33
os-zhuang pushed a commit that referenced this pull request Sep 4, 2026
…sertions
`sys_metadata_activation` dropped its reserved `organization_id` column before it
ever shipped (#15024): the object declares `systemFields: { tenant: false }`, the
opt-out that REMOVES the column rather than leaving it unwritten. PR #15251
re-grounded the two items #15154 named. Four siblings still read that column back
and asserted it NULL — a VACUOUS leg, not merely a wrong value: once the column
is gone, `row.organization_id ?? null` answers `null` either way, so the read
passes rather than failing and a runner sees green for exactly the reason it
should be red. Each is inverted into a KEY-SET assertion, the shape #15024 used
on the dogfood pin and PR #15251 carried into step 2.
- platform-core.activation-ledger-registration-home — step 2's row capture and
the no-automation clause's "ONE install-level row (organization_id NULL)". The
row is re-said as DEPLOYMENT-level: with no tenant column there is no second
scope for install-level to be distinguished from. The schema-side probe stays
with the sibling item that owns it.
- api-backend.packaged-action-disabled-dispatch — the disable step's row
confirmation, plus `automated.ref`, which described the dogfood pin as
asserting "ONE install-level row with organization_id NULL". That pin has been
a key-set reading named "writes ONE deployment-level row, and the TABLE has no
tenant column at all" since #15024; the ref now quotes its live name.
- api-backend.action-activation-door-contract — the happy-path step, its
acceptance clause and `automated.ref`. The clause also glossed the column as
"the per-org dimension is reserved and unwritten": ADR-0131 D7 WITHDREW that
ADR-0126 §5 D3 bullet ("a reserved nullable tenant column is the shape D1
forbids") and names this table as reverted before 17.3 and not returning, so
the gloss told a runner the tenant dimension was coming back. The source list
now cites ADR-0131 D7 and marks which half of §5 survives.
- automation.packaged-flow-disable-durable — the ledger read step, the row
clause and its "§5 reserves the column" gloss, the verify line's
NULL-collapsed 'organization' index (it is a plain `unique: 'global'` over two
required key parts; with no tenant column `normalizeDeclaredIndex` has no part
to prepend), and the `source` line still citing "org-carrying rows skipped on
read" and "organization_id never written". The store citation splits so
`#list` carries the read-path correction where the read path lives.
Each item bumps `revision` and appends a `history` entry, per the checklist's
change lifecycle. No item outside this defect class is touched, and no clause of
the four contracts themselves moved — only what a runner records about the row.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs(qa): platform-checklist activation-ledger-row-contract is written around the removed sys_metadata_activation tenant column

1 participant

@hotlong