Repository navigation
Amend ADR-0131 D13 to drop the two platform-admin reporter symbols (maintainer ruling B on #18336) — and close the single-row NULL-ownership question the drop leaves open #18413
Description
Activity
Claim: PM loop round 1
Session:session_01Gqi43smmqjJ5sUrhfoPeKu
Branch:claude/issue-18413-adr-0131-d13-drop-reporter-symbols
Worktree:objectstack-issue-18413
Domain:domain:skills
Seat:domain:skills#1
File surface:docs/adr/0131-total-organization-ownership-no-null-organization-id.mdonly (D13's retirement list losesreportLegacyPlatformAdminGrant+resetLegacyPlatformAdminGrantReportwith the ruling recorded; thesingle-row NULL-ownership question CLOSED in text, ⛔ not deferred; the two standing constraints — Choice 4A 5587754690 and the zero-config constraint — honoured verbatim); ⛔ no code, ⛔ no other ADR; governeddocs/adr/**⇒ draft, four-piece, the maintainer's approval lands it (stop on breach; explain in the report)
Container & model:M(ADR 修订,规则层;含一个必须在文本里关掉的开口),mode:subagent,model: claude-opus-5—node scripts/pm/dispatch-gates.mjs --tier --repo objectstack-ai/objectstack <surface>at 2026-09-17T11:43Z on the fast-forwarded tree: 「Model tier — no path-derived mandate … floor sonnet · default opus · ceiling fable」; default tier taken; the seat's contract-tier review at delivery
Clause-②: no
Thread-read: 5713104256
Serial constraints cleared:pm:blocking— #18336 (services) ispm:blockedon this card and lands after it; the ADR file is FREE; 12 open PRs' file lists read at 2026-09-17T11:43Z — none touches this surface;os-verify-lock.sh --statusat 2026-09-17T11:43Z: free, queue empty; shared checkout fast-forwarded toorigin/main32be735e5before this dispatch. Batch of 3 this round: #18413 (pm:blocking, first in the total order) · #18343 · #18379 (p2 Bugs by card age); #18422, #18636, #18372, #18426 queue behind (SKILL.md and check-half-states.mjs serial where they share a file).
Ruling-ref: 5713104256
Generated by Claude Code
os-dev-report
{ "issue": 18413, "status": "done", "branch": "claude/issue-18413-adr-0131-d13-drop-reporter-symbols", "pr": "https://github.com/objectstack-ai/objectstack/pull/18646", "head_sha": "ef300b6864eb049ae1879aca388c9cb046cffe1c", "files": [ "docs/adr/0131-total-organization-ownership-no-null-organization-id.md (+129 / -4)" ], "session": "session_01Gqi43smmqjJ5sUrhfoPeKu", "premise_still_valid": true, "premise_note": "SURVIVES in substance, with one reading correction the card got wrong. The card says D13's retirement list names both symbols. Measured on origin/main 32be735e5: D13's own list (:641-659) names NEITHER. `reportLegacyPlatformAdminGrant` occurs exactly ONCE in docs/adr/ - ADR-0131 :362, inside D5, in the sentence that ASSIGNS its retirement to D13. `resetLegacyPlatformAdminGrantReport` occurs ZERO times in docs/ at all. Counts by `grep -ro`: docs/adr/ 1 and 0; docs/ 3 and 0; positive control packages/ 15 and 17; negative control (a nonexistent symbol over docs/adr/) 0. The ASSIGNMENT is what the ruling reaches, so the amendment edits D5, D14 and section 7 and leaves D13's list unchanged. Before: the retirement was D13's and therefore v18's. After: it is #11663's and 17.x's. No PR premise died.", "summary": "Amended ADR-0131 to carry the maintainer's option-B ruling on #18336 (session session_01LmoCFLwGkcAGefVf7jryEV, 2026-09-16T09:54Z): D5's assignment of `reportLegacyPlatformAdminGrant` and `resetLegacyPlatformAdminGrantReport` to D13 is withdrawn; those symbols retire on the 17.x line under #11663's design, WALLED POSTURE ONLY. Five text sites: the Status line gains an `**Amended** (2026-09-17, #18413 ...)` clause; D5's sentence is rewritten; D14 gains one named, exhausted exception; section 7's post-17.2 audit line gains the same exception; a full `## Amendment (2026-09-17, #18413)` record is added at the end of the file carrying the authority, both standing constraints verbatim and untranslated, the closed question and the D14 reconciliation. The corpus's own revision convention was followed (status-line note + in-place correction + a named end-of-file Amendment section, as ADR-0045 / ADR-0049 / ADR-0055 do; ADR-0090's #17189 block read for the inline form). The NULL-ownership question is CLOSED in the text, not deferred: the STOP condition did not trigger. NO code, NO other ADR, NO packages/** path.", "decision_sentence_that_closes_the_open_question": "Decision (2026-09-17, #18413). The `single`-posture first-user grant row STILL BECOMES OWNED BY THE DEFAULT ORGANIZATION. That is D5's own answer, accepted by the maintainer on 2026-09-04 (ADR-0131 section 6, one of the four open questions answered 'jie shou ni de jian yi' - the verbatim text in the ADR is unchanged and untranslated), and the option-B ruling does not touch it. It still lands ON THE V18 LINE, UNDER C3 (section 8), exactly where it was before this amendment. UNTIL C3 LANDS, THE ROW KEEPS THE NULL ORGANIZATION IT CARRIES TODAY - the state D10's migration exists to clear - and D1's NOT NULL constraint still reaches that table only when D10 reports zero for it.", "why_no_stop": "The STOP condition asked for a fork if the two standing constraints conflict with the D13 change in a way the ruled texts do not settle. They do not conflict. (1) Choice 4A ('retiring the walled write must not retire the `single` one') - the D13 change REDUCES what retires, and a reduction cannot retire the `single` write. (2) The zero-config constraint - the zero-config channel is the unscoped-grant read at resolve-authz-context.ts:839 / :928, which is NOT the reporter and is untouched. The closure needs no new maintainer decision: it is D5 (ruled 2026-09-04) plus the option-B ruling's own explicit statement of what it did NOT decide. MEASURED, not argued, that the drop moves no row: reportLegacyPlatformAdminGrant (platform-admin.ts:351) is a once-per-process warn naming one holder and pointing at OS_PLATFORM_OWNER_EMAIL; resetLegacyPlatformAdminGrantReport (:371) drops that latch for tests. Neither writes the grant row, neither reads its `organization`, neither participates in the PLATFORM_ADMIN derivation. So the 17.x retirement adds no NULL row, removes none, re-owns none => D1 and D10 are unaffected. Also mechanically decisive: the deprecation pointer is ALREADY posture-keyed (postureEnforcesWall(resolveTenancyPosture()) at the 6b-config arm), so under `single` there is no pointer behaviour to retire at all - the all-postures reading was never available for this leg.", "d13_text_before_after": { "site": "D5, ADR-0131 :358-363 on origin/main 32be735e5 (D13's own list is NOT edited - see premise_note)", "before": "`PLATFORM_ADMIN` derives from `OS_PLATFORM_OWNER_EMAIL` (#13514 L4) - configuration, not a row. The `single`-posture first-user promotion (Choice 4A), which today writes an `admin_full_access` grant row with a NULL organization, writes it **owned by the Default Organization** instead; under a walled posture no grant row is written (unchanged). `reportLegacyPlatformAdminGrant` and the legacy unscoped anchor retire with D13. No NULL grant row is ever produced.", "after": "... under a walled posture no grant row is written (unchanged). That ownership change is C3's, on the v18 line, and it is **unchanged by the 2026-09-16 ruling** - so **no NULL grant row is ever produced once C3 has landed**; until then the `single` row carries the NULL organization it carries today, and D10's migration is what clears it. The legacy unscoped anchor retires with D13 **for the `single` posture only**: its **walled** half, together with the two symbols that carry the migration window - `reportLegacyPlatformAdminGrant` and `resetLegacyPlatformAdminGrantReport` - **left D13 on 2026-09-16** and retire on the **17.x** line under #11663's design instead (#18336; see the Amendment at the end). The `single` anchor's own disposition is #11979's (Choice 4B), which this record does not pre-empt." }, "standing_constraints_honoured": [ "Choice 4A (maintainer 2026-09-08, #16682 comment 5587754690), quoted verbatim in the ADR: 'The rest of Choice 4A (#11974, 2026-08-25) stands: retiring the walled write must not retire the `single` one'. Honoured: every site that names the retirement says WALLED - D5, D14's exception, the section 7 line. The `single` write, its row and its zero-config promotion are stated as surviving until #11979 (Choice 4B). Nothing in the diff removes or narrows the `single` half.", "The zero-config constraint (maintainer 2026-09-16, same session as the ruling), quoted verbatim and untranslated in the ADR (the original Chinese sentence about a development environment started for a moment not being configurable). Honoured: the amendment states `single` keeps its zero-config first-user promotion and touches no part of the derivation that delivers it; it also records that the pointer is already posture-keyed, so `single` has no pointer behaviour to retire." ], "d14_and_15193": "D14 gains ONE named exception, written into D14 itself, with two independent sufficient reasons: (1) the leg is not 'a half of this record' - the ruling put it under #11663's design, so this record no longer governs it; (2) it narrows no ARM - the arms D14 fences are the drivers' orWhereNull arms inside applyTenantScope (this record's own vocabulary: D13 :641, D14 :674, section 7 :836 'the arms are inside applyTenantScope ... there are two'; the reads in resolve-authz-context.ts are called 'NULL readings', never arms). The exception is written as EXHAUSTED by that leg and those two symbols; every other D13 retirement keeps D14's fence and stays gated on D10's zero-NULL report. #15193: CONFIRMED it no longer gates #18336 under this ruling - #15193 binds 'every ADR-0131 execution card' and option B took this leg out of that set; the ruling comment states it directly. NO label or body of #15193 was touched - that re-pointing is #18336's, out of scope here.", "tests": "No tests owed and none written: the diff is one markdown file under docs/adr/, no packages/** path, no code. GATES (derived, not hand-listed): `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` from the worktree, change set taken three-dot vs merge base 32be735e5 -> 18 commands. All 18 run, exit captured BEFORE any pipe (redirect-then-$?), all exit 0: check-adr-links (+--self-test), check-adr-symbol-anchors (+--self-test), check-ci-filter-parity, check-closing-keyword-parity (+--self-test), check-comment-mask-corpus, @objectstack/lint check:doc-formula-expressions, check:adr-anchors, check:cross-package-test-inputs, check:doc-authoring, check:driver-memory-census, check:nul-bytes, check:pm-governed-merges, check:pm-prior-rulings, check:refd-timer-probe, check:watch-hint-literal. RECONCILED: `dispatch-gates --ran` -> '18 derived, 18 run, 0 NOT-MEASURED, 0 UNRUN' and 'a DERIVED zero - all 18 recorded an exit code and none of them is 3'. ONE non-measurement, declared: check:doc-formula-expressions exited 3 on the first attempt = PREREQUISITE NOT MET, its own text 'Nothing was measured: this gate exited before running a single check'; its prescribed remedy was run (turbo run build --filter=@objectstack/formula --filter=@objectstack/lint under scripts/pm/os-verify-lock.sh, OS_VERIFY_LOCK_SLOT=issue-18413, VERDICT command-exit 0, held 134s, waited 0s) and the gate re-run to a real exit 0. The 3 is recorded as a non-measurement, NOT as a failed gate. GOVERNED CHECK: `node scripts/pm/check-governed-merges.mjs --test docs/adr/0131-...md` -> GOVERNED, 1 of 1 path hit the register, exit 3 (the GOVERNED verdict code, as the dispatch expected). ESLINT - a PROVEN narrowing, three pieces: (1) population read from eslint's own config - every `files:` entry in eslint.config.mjs names only {ts,tsx,mts,cts,js,jsx,mjs,cjs}, including COMMENT_SWALLOW_FILES, and `grep -c '\\.md' eslint.config.mjs` returns 0; (2) `pnpm exec eslint --no-inline-config --format json` over the one changed path -> 1 result, errorCount 0, single message 'File ignored because no matching configuration was supplied.'; (3) invariance - the diff is one .md file and touches no eslint config and no TS/JS source, so no untouched file's verdict can move, and type-aware linting does not enter into it because the file is not in the population at all. Measured against final head ef300b686. NO ABLATION and no reverse verification: there is no executable assertion in this diff to ablate - it is a governance record, and the corresponding claim is proved instead by the mechanical reading of the two symbols' definitions (platform-admin.ts:351/:371) quoted in the PR body. CI CONVERGENCE: not waited on, per the report-on-local-completion rule.", "mcp_calls": "0 - no MCP GitHub tool was called, read or write, at any point.", "api_writes": "3 REST proxy writes: POST /repos/objectstack-ai/objectstack/pulls (draft PR #18646, HTTP 201); POST /repos/objectstack-ai/objectstack/issues/18646/labels (skip-changeset, via scripts/pm/label-write.mjs, HTTP 200, four-step with read-back: target {size/m, skip-changeset} == read-back {size/m, skip-changeset}; size/m was the size-labeler's and was not touched); POST /repos/objectstack-ai/objectstack/issues/18413/comments (this report). Plus 2 git pushes (the mandated empty-branch routing probe, then the commit). PR body read back after create: byte-identical to what was sent apart from the trailing newline GitHub strips (md5 compared; footer present exactly once, session-URL form, under the rule line).", "open_questions": [], "out_of_scope_findings": [ "noted, not filed: docs/qa/platform-checklist/areas/access-security.json :2462 / :2492 describe the legacy-anchor deprecation pointer as live behaviour and name reportLegacyPlatformAdminGrant. Those two clauses go stale for walled rigs the moment #18336 lands. Not one of the three filing classes (not a reproducible defect, not a declared-contract violation, not a metadata-authoring trap), and it has a named taker: #18336 itself, whose diff removes the symbol those clauses name. Out of this PR's declared file surface (one ADR).", "noted, not filed: the card's claim that D13's LIST names the two symbols is a reading error, not a defect in the tree - it is reported as premise_note above and corrected in the ADR's own Amendment section so the next reader does not repeat it. Taker: this PR." ] }
Generated by Claude Code
ACCEPT — in-seat contract-tier review of PR #18646 (head
ef300b686, report 5714035120) by the skills seat, 2026-09-17T12:21Z. Verified against GitHub and a scratch worktree at the head, ⛔ not against the report:- Scope = the claim (5713780209): one file, +129 / −4 —
docs/adr/0131-total-organization-ownership-no-null-organization-id.md; ⛔ no code, ⛔ no other ADR, ⛔ nopackages/**. Five text sites: the Status line gains an**Amended** (2026-09-17, #18413 …)clause; D5 :362's assignment sentence is rewritten; D14 gains one named, exhausted exception; §7's post-17.2 audit line gains the same exception; a## Amendment (2026-09-17, #18413)section closes the file. The corpus's own revision convention (status-line note + in-place correction + named end-of-file Amendment). - Reading correction, measured here:
git grep -oonorigin/main32be735e5—reportLegacyPlatformAdminGrantindocs/adr/1 (ADR-0131 :362, inside D5),docs/3,packages/15;resetLegacyPlatformAdminGrantReportindocs/adr/0,docs/0,packages/17. D13's own list (:641–659) names neither. The card's premise 「D13 lists both symbols」 was a reading error; what the ruling reaches is D5's assignment to D13, and that is what the diff edits. Substance unchanged: before, the retirement was D13's and therefore v18's; after, it is [Design] Re-anchor platform-admin:admin_full_accessbecomes a kernel metadata declaration; WHO holds it comes from env-configured verified emails — retiring the org-less row anchor #11663's and 17.x's. - Authority and constraints, verbatim-checked: the option-B text matches the ruling record on platform-admin re-anchor L5 EXIT (re-file of the unreadable #13515): retire the legacy row-id grant dual read and its deprecation log — the 17.4.0 boundary is measured MET #18336 (5695555178, 2026-09-16T09:54Z) byte for byte; the Choice 4A sentence matches plugin-security: the first-user promotion picks the oldest authenticable user from an UNORDERED 50-row
sys_userwindow, so on the default driver a seeded job seeker became platform admin and owned every seeded row #16682 comment 5587754690 (os-zhuang, 2026-09-08); the zero-config sentence 「比如临时启动的开发环境,我不可能去配置啊」 is the one the ruling record carries. Every site that names the retirement says walled; thesinglewrite, its row and its zero-config promotion are stated as surviving until platform-admin re-anchor follow-up (Choice 4B): config-anchor thesingleposture — first-user promotion becomes development-only fallback #11979 (Choice 4B). - The open question is CLOSED in the text, not deferred — no new ruling needed: the decision sentence says the
singlerow still becomes Default-Organization-owned under C3, on the v18 line (D5's own answer, accepted 2026-09-04), and until C3 lands it keeps the NULL it carries today, which D10's migration clears. That is a restatement of what §8 C3 already schedules, not a new decision; the option-B ruling explicitly left it alone. The seat's independent check of 「the drop moves no row」:platform-admin.ts:351(reportLegacyPlatformAdminGrant, once-per-process warn) and:371(resetLegacyPlatformAdminGrantReport, test latch reset) neither write the grant row nor read itsorganization; the pointer is already posture-keyed (postureEnforcesWall(resolveTenancyPosture()),resolve-authz-context.ts:1024). ⇒ STOP condition not triggered; the seat agrees. - D14 / [gate] the v18 development line is not open — ADR-0131 execution cards are blocked on this card #15193: D14's exception is written into D14 itself, exhausted by this leg and these two symbols, with two independent reasons (not a half of this record after the ruling; narrows no
applyTenantScopearm). [gate] the v18 development line is not open — ADR-0131 execution cards are blocked on this card #15193 no longer gates platform-admin re-anchor L5 EXIT (re-file of the unreadable #13515): retire the legacy row-id grant dual read and its deprecation log — the 17.4.0 boundary is measured MET #18336, as the ruling record states; [gate] the v18 development line is not open — ADR-0131 execution cards are blocked on this card #15193's own label/body untouched — that re-pointing is platform-admin re-anchor L5 EXIT (re-file of the unreadable #13515): retire the legacy row-id grant dual read and its deprecation log — the 17.4.0 boundary is measured MET #18336's. - Gates: re-run here on the head —
check-adr-links0,check-adr-symbol-anchors0,check-closing-keyword-parity0 (+--self-test0, from the dependency-bearing worktree; a fresh worktree answers 3 = PREREQUISITE, non-measurement),--pair 18646→ 0 (Clause-②: no, both carriers agree, no widening tell),check-governed-merges --testexit 3 = GOVERNED (docs/adr/**×1). The report's 18 derived families all exit 0 (one declared non-measurement remedied and re-run to 0). CI onef300b686: 24 success / 11 skipped onef300b686(check-expected-skips --pr 18646exit 0, every skip rostered), 0 failures. - Deviations: none. Dev's open questions: none. Out-of-scope notes (two
access-security.jsonchecklist clauses that name the symbol go stale when platform-admin re-anchor L5 EXIT (re-file of the unreadable #13515): retire the legacy row-id grant dual read and its deprecation log — the 17.4.0 boundary is measured MET #18336 lands — platform-admin re-anchor L5 EXIT (re-file of the unreadable #13515): retire the legacy row-id grant dual read and its deprecation log — the 17.4.0 boundary is measured MET #18336's own diff is the taker; the card's reading error, corrected in the Amendment's reading note) recorded, nothing to file.
Rules layer ⇒ the four-piece is hung on PR #18646 in the same act: 维护者速读(终稿) on the PR,
needs-user-decision, review requested fromos-zhuangandhotlong. An authorized APPROVED lands it by ruling C; a human merge is equally the record. #18336 (services) stayspm:blockedon this card until the merge.
Generated by Claude Code
- Scope = the claim (5713780209): one file, +129 / −4 —
LANDED — PR #18646 (#18413
pm:blocking: ADR-0131 amended under ruling B on #18336 — D5's assignment of the two platform-admin reporter symbols to D13 withdrawn, walled-only, 17.x under #11663; thesingle-row NULL-ownership question closed in text by D5's own answer under C3 / v18) merged through the queue at 2026-09-18T01:44:29Z (merged_at), squash0b271e2e16b338ee70bee65623ee6a775da7990d(single parentc7dc0895fa3c312bff1199df81d2e396f78fd501, an ancestor oforigin/main;docs/adr/0131-total-organization-ownership-no-null-organization-id.md+129 / −4, the Amendment 2026-09-17 onmain). Governed surface (docs/adr/**): the seat's four-piece was ACCEPT 5714248975 here,## 维护者速读(终稿)5714246119 on the PR,needs-user-decision+ reviewers os-zhuang / hotlong at 2026-09-17T12:21Z; os-zhuang APPROVED at 2026-09-18T01:11:16Z (review 5243100378 on the ACCEPT headef300b6864), marked ready and enqueued by hand at 2026-09-18T01:11:21Z; the seat strippedneeds-user-decisionat 2026-09-18T01:12:46Z per ruling C (--pair 186460,check-governed-merges --pr 18646GOVERNED, harness CURRENT at88aa326deb). The card auto-closedcompletedat 2026-09-18T01:44:30Z on the PR'sFixes;pm:dispatchedand the assignee are stripped in the same act. Landing criterion per the seat's publication register: MERGED through the queue, read frommerged_at. ⇒ #18336 (domain:services,pm:blockedon this PR) is unblocked by this landing — that lane's card, reported here only.
Generated by Claude Code
github-actions commented
on Sep 18, 2026 on Sep 18, 2026 – with GitHub ActionsContributorMore actionsos-closed-card-sweep — machine-findable marker for this generated comment.
Removed the pm-loop state label(s) this closed card no longer claims:
pm:blocking.- Closing pull request: docs(adr-0131): amend D13's reach — the legacy-anchor retirement leaves it for the walled posture, on the 17.x line #18646, merged.
- Closing commit
0b271e2e16, merged intomain. - Left untouched:
priority:p2,domain:skills— ownership, priority and outcome are not state claims. - The label set was read back after the write and matched.
A state label claims work is in flight. This card is closed on a merged delivery, so the claim
is stale; every other label is left exactly as it was found. Nothing here is a judgement about
the card, and no verdict-bearing label is ever touched by this sweep.posted by half-state-patrol run 35297049699 · trigger
scheduleGenerated by Claude Code
- added 2 commits that reference this issue
on Sep 28, 2026
ADR-0131 D13 lists
reportLegacyPlatformAdminGrantandresetLegacyPlatformAdminGrantReportamong the retirements it assigns to the v18 line. A maintainer ruling in sessionsession_01LmoCFLwGkcAGefVf7jryEV(2026-09-16T09:54Z) decided option B on #18336: #11663's design governs this leg, the work stays on the 17.x line, and ADR-0131 D13 is to be amended to drop those two symbols.⇒ This card is that amendment. It is a governed-surface change (
docs/adr/**) ⇒ single PR, maintainer-merged, ⛔ never a rider on a code PR.Why it must land BEFORE the code
ADR-0131 is Accepted and on
maintoday. Landing #18336's removal while D13 still names these symbols puts the code in direct contradiction with an accepted ADR. ⇒ ordering is fixed: this card → then #18336. #18336 ispm:blockedon this one.What the amendment must say
sys_userwindow, so on the default driver a seeded job seeker became platform admin and owned every seeded row #16682 comment5587754690), verbatim: 「The rest of Choice 4A (platform-admin re-anchor L4 (plugin-security): bootstrap stops granting under walled postures; explain reports config-derived standing; deprecation log for legacy grants #11974, 2026-08-25) stands: retiring the walled write must not retire thesingleone」;⇒ the retirement is walled-posture only;
singlekeeps its zero-config first-user promotion and its row until platform-admin re-anchor follow-up (Choice 4B): config-anchor thesingleposture — first-user promotion becomes development-only fallback #11979 disposes of it.🔴 The open question this amendment MUST close, ⛔ not defer
ADR-0131's core rule is 「no NULL
organization_id」. Ifsinglekeeps writing its grant row, and that row'sorganizationis NULL today, then dropping two symbols from D13 does not address the NULL ownership at all.ADR-0131 already states an answer for this,
:360–363verbatim:⇒ The amendment must say explicitly whether the
singlerow still becomes Default-Organization-owned (ADR-0131's own answer, untouched by the ruling) or stays NULL for now. The two have materially different consequences for D1 (the constraint) and D10 (the zero-NULL migration that D13's other retirements are gated on).Also reconcile
Dedup words:
ADR-0131 D13 amendment·reportLegacyPlatformAdminGrant retire 17.x·#18336 option B ruling·D14 v18 line half record·single posture NULL organization grant rowGenerated by Claude Code