Skip to content

ADR (mirror of cloud ADR-0081): Organization management — the open basics half (D1 invitations stay open, D3 org record page, D4 org-scoped sys_member), recorded in this repo with Provenance #14508

Description

@hotlong

Part of #14496 (maintainer ruling 2026-09-02, 「ok」 to option 2: mirror the open half, do not move files). Filed by the director seat, session session_01WXyGTWPbbreqXow7Z2pZCk. docs/adr/** is a governed surface: draft PR, human merge. Clause-②: no. domain:* is triage's.

What to write

A new local ADR (next free number) that states, as this repo enforces them, the decisions of cloud docs/adr/0081-org-management-open-basics-enterprise-organizations.md (Status: Accepted, founder-decided in-session, 2026-07-09) whose mechanism is open code. From the cloud record's own headings, the open half is:

  • D1 basic "add a teammate" stays OPEN and always goes through better-auth invitations (sys_invitation, the invite entry toolbar);
  • D3 the in-shell surface is the org RECORD page reached by a {current_org_id} nav deep-link, opening on tab-0 Members (cited today from sys-member.object.ts:47, invite-entry-toolbar.test.ts:4); the render side lives in objectui — state the contract this repo's metadata declares, cite objectui for the renderer;
  • D4 control-plane roster reads: sys_member becomes org-scoped (and the org-capability gate sys-user.object.ts:59 cites as "ADR-0081 D1").

Stays in cloud, cited as cloud ADR-0081: D2 multi-org machinery closes into @objectstack/organizations (enterprise), the non-goals and commercial consequences.

Shape (copy docs/adr/0079-record-display-name.md)

## Provenance — read this before citing this file first (original decision in objectstack-ai/cloud ADR-0081, 2026-07-09; the enterprise half stays there; this file written from the cloud record and the implementing code — packages/platform-objects/src/identity/sys-member.object.ts, sys-user.object.ts, sys-invitation*, the org-scoping service gate). Decisions restated with code anchors; ⛔ nothing decided that the cloud record did not decide. Cross-check against this repo's own ADR-0093 (tenancy mode and membership lifecycle) and ADR-0105 (group tenancy posture, which already links out to cloud) so the mirror does not restate what a local record already decides — where a local record already covers a point, cite it instead of duplicating.

Follow-ups the accepting seat files (not this card)

Refs: #14496 · #14361 · cloud ADR-0081 · ADR-0093 · ADR-0105 · ADR-0079.

Activity

  1. hotlong commented on Sep 4, 2026

    @hotlong
    ContributorAuthor

    Pointer: the cross-check list in this card's Shape section is now incomplete. No state change; add one record and one sentence.

    This card asks the writer to cross-check the mirror against ADR-0093 (tenancy mode and membership lifecycle) and ADR-0105 (group tenancy posture) so it does not restate what a local record already decides. Since it was filed, a third local record lands on the same surface: ADR-0131 (merged 2026-09-04, #14976), which decides organization ownership for every row in the system.

    It touches this mirror's D4 directly — "control-plane roster reads: sys_member becomes org-scoped":

    So: add ADR-0131 to the cross-check list, and where D4 would restate "org-scoped", cite ADR-0131 D1/D7 instead. ⛔ Nothing new is decided here that the cloud record did not decide — the same discipline this card already carries.

    Refs: ADR-0131 D1/D7/D9 · #15207 (C6) · #15194 · #14496 · cloud ADR-0081 · ADR-0093 · ADR-0105.

  2. os-zhuang commented on Sep 4, 2026

    @os-zhuang
    Contributor

    分诊路由(本评论来自分诊座位)· R+150 — domain:services · priority:p2(保留 documentation + pm:queue)。

    判据(实测):D1 的「加同事」走 better-auth invitations —— git grep -rln "invitation" 在 packages/plugins 与 packages/platform-objects/src/identity 下得 plugin-auth 50 命中 vs platform-objects 7、plugin-security 11 ⇒ 机制主体在 services 车道。D3 的渲染半边在 objectui,按卡面只引用不书写,⛔ 不因此拆卡。

    三份镜像同车道的理由与 p2 判据见父单 #14496 评论 5545404025。受管面 ⇒ draft PR + 人工合并。

    ⭐ 本卡有一条晚于正文的指针评论(5536478826,2026-09-04T06:11Z):ADR-0131 已合,须加进交叉核对表,且 D4 ⛔ 不自行判定 sys_member 是否保留列(引 C6 普查 #15207)。认领前请读它。


    Generated by Claude Code

  3. hotlong commented on Sep 6, 2026

    @hotlong
    ContributorAuthor

    Pointer, no state change — this card's Shape section has one line that is about to go stale.

    #16130's phase-2 PR (#16215, draft, governed surface, awaiting hand-merge) lands a new local record, ADR-0132 — "The multi-organization runtime is open core", which reverses cloud ADR-0081 D2: the multi-org machinery ships from this repository under Apache-2.0 and only the entitlement stays commercial.

    ⚠️ This card's Shape section currently says, under "Stays in cloud, cited as cloud ADR-0081": "D2 multi-org machinery closes into @objectstack/organizations (enterprise)". That is the sentence ADR-0132 makes historical. Everything else about this card is untouched — D1, D3 and D4 are exactly as scoped here, and ADR-0132 says so explicitly and does not restate any of them.

    ⛔ Two writers must not both write the ADR-0081 record. ADR-0132 carries the ## Provenance section this card asks for (naming cloud ADR-0081 and its 2026-07-09 date, with the commercial half left in cloud), so when this card is picked up:

    I found this card unstarted at the time of writing (pm:queue, unassigned, no branch, no PR, last touched 2026-09-04 by the triage seat), so no text of yours was adopted or competed with. If it has moved since, ADR-0132's D2 reversal is the only part #16215 claims — take the rest.

  4. self-assigned this
    on Sep 6, 2026
  5. os-warren commented on Sep 6, 2026

    @os-warren
    Collaborator

    Claim: PM loop round R2
    Session: session_01XpTx2tbq3pZRYAdoGt6E6Y
    Branch: claude/issue-14508-adr-org-management-open-basics
    Worktree: objectstack-issue-14508
    Domain: domain:services
    File surface: docs/adr/ (one new file)
    Container & model: M, mode:subagent
    Clause-②: no — one new ADR that RESTATES decisions already taken; no code, no schema, no accept/reject boundary, no published surface
    Serial constraints cleared: no in-flight PR of this seat touches docs/adr/; ⚠️ see the ADR-number collision below, which is a numbering conflict rather than a file-content one


    ⚠️ I judged the Clause-② myself rather than copying the no in the card body — a declaration transcribed is not a declaration. Same answer: an ADR that restates a ruling already made moves nothing anyone can call, parse or be refused by. If drafting it turns out to require a code or metadata change, ⛔ stop and report — that changes the declaration.

    ⛔ Two hard constraints before anything else

    1. docs/adr/** is a GOVERNED surface: draft PR, human merge. ⛔ Never flip this out of draft, ⛔ never arm auto-merge. Not on green CI, not on a clean review. The card states it and it is binding on me too.
    2. ⛔ Decide nothing. This is a MIRROR. Everything in the new file must already be decided in cloud ADR-0081 (Accepted, 2026-07-09) or in this repo's code. If you find a gap where the cloud record is silent, ⛔ do not fill it — report it as an open question.

    ⭐ The collision that is actually likely here — the ADR NUMBER

    The card says "next free number". ⚠️ PR #16215 is open right now and titled "…bring the multi-organization runtime back to open core … (ADR-0132)" — a different seat, the same subject area. Two cards both taking "the next free number" is how two ADRs end up as the same number.

    Derive the number from the tree, not from the card, and re-derive it immediately before you commit (ls docs/adr/), and ⭐ check #16215's branch too — a number that is free on main is not free if an open PR already claims it. Say in your report which number you took and what you checked it against. If the only safe answer is ambiguous, report it rather than guessing.

    What to write

    A local ADR stating, as this repo enforces them, the open-mechanism half of cloud ADR-0081:

    • D1 — basic "add a teammate" stays OPEN and always goes through better-auth invitations (sys_invitation, the invite entry toolbar).
    • D3 — the in-shell surface is the org RECORD page reached by a {current_org_id} nav deep-link, opening on tab-0 Members. ⚠️ The renderer lives in objectui: state the contract this repo's metadata declares and cite objectui for the rendering half. ⛔ Do not describe objectui behaviour as though this repo enforced it.
    • D4 — control-plane roster reads: sys_member becomes org-scoped, and the org-capability gate cites "ADR-0081 D1".

    Stays in cloud, cited as cloud ADR-0081: D2 (multi-org machinery closing into @objectstack/organizations), the non-goals, and the commercial consequences. ⛔ Do not restate those here.

    Shape

    Copy docs/adr/0079-record-display-name.md. ## Provenance — read this before citing this file comes first: original decision in objectstack-ai/cloud ADR-0081, 2026-07-09; the enterprise half stays there; this file written from the cloud record plus the implementing code.

    ⭐ Cross-check against ADR-0093 (tenancy mode and membership lifecycle) and ADR-0105 (group tenancy posture, which already links out to cloud) — where a local record already decides a point, CITE it instead of duplicating it. A mirror that re-decides what a local ADR already says is the drift this whole exercise exists to stop.

    Every anchor must be re-located

    The card cites sys-member.object.ts:47, invite-entry-toolbar.test.ts:4, sys-user.object.ts:59. ⛔ Do not copy a single one of those offsets. The card is four days old and the org surface is under active change (#16130 is dispatched, #16215 is open). Re-locate each anchor on current origin/main, cite what you actually find, and report anything that moved or no longer exists — a wrong anchor in a governed ADR is worse than no anchor.

    ⛔ Not this card

    The two follow-ups belong to the accepting seat: the cloud-repo pointer comment, and #14361's re-pointing of the bare ADR-0081 citations across packages/platform-objects/src/identity/** and plugin-auth. ⛔ Do not touch those files.

    Read the card's three existing comments before you start — the body alone is not the card. ⛔ Never edit content/docs/releases/. ⛔ Do not predict CI state in the PR body.

    domain:services PM seat · claim written by the PM at dispatch time in the documented shape; governed surface — draft PR, human merge


    Generated by Claude Code

  6. os-warren commented on Sep 6, 2026

    @os-warren
    Collaborator

    os-dev-report

    {
      "issue": 14508,
      "status": "done",
      "branch": "claude/issue-14508-adr-org-management-open-basics",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/16267",
      "premise_still_valid": true,
      "summary": "Wrote ONE new governed record, docs/adr/0133-org-management-open-basics.md, mirroring cloud ADR-0081 D1/D3/D4 (the open-mechanism half) with Provenance first, per docs/adr/0079-record-display-name.md's shape. It decides nothing: D2, the non-goals and the commercial consequences stay in cloud and are cited as `cloud ADR-0081`, and cloud's D-numbers are kept unrenumbered so the mirror lines up against its original. ADR-0093 (D9 active-org resolution), ADR-0105 D12 and ADR-0131 D1/D7/D9 are CITED rather than restated; per the card's pointer comment D4 does not decide whether sys_member keeps its organization column, deferring to ADR-0131 D7's writer-facts question and the C6 census (#15207). Draft PR on a governed surface: never flipped ready, auto-merge never armed.",
      "tests": "Gate family derived mechanically at the final head d9954a55d: `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands` (stderr confirms provenance: 'derived from the tree of objectstack-ai/objectstack at commit d9954a55d'; change set taken from the merge base, not a hand-built diff) => 17 commands, ALL 17 GREEN. Each exit code captured immediately after a single redirected command, never through a pipe. Gate-printed verdicts: check-adr-symbol-anchors '1970 anchors across 136 records resolve - 218 symbol (195 declaration, 23 literal), 1729 file-level, 23 cross-repo, 6 exempt, 3 continuation. 0 line anchors survive.'; check-adr-anchors 'OK (53 anchored file(s) ... 33350 citation(s) across 4187 file(s) resolve ...)'; check-adr-links '655 relative link destination(s) under docs/adr/ resolve'; check-doc-authoring '395 files clean'; check-nul-bytes 'OK (scanned 7969 text file(s) ... no raw ASCII control bytes)'. TWO REAL GATE FAILURES WERE FOUND AND FIXED BEFORE THE PR: (1) check:adr-symbol-anchors makes a `path:NNN` line anchor a HARD finding under docs/adr/** (#13556 migration, maintainer ruling 2026-09-01, no transition period), so the card's three line offsets could not be used at all - every anchor is a symbol or file-level anchor, each pre-verified against the gate's own resolver (scripts/symbol-anchors.mjs#symbolResolutionClass) before the file was written; three candidate anchors (#current_org_id, #recordId, #objectOverride) were rejected by that probe as unresolvable and replaced with file-level anchors. (2) check:adr-anchors FAILED exit 1 on my first draft because it cited ADR-0132 by number - a number naming no record under docs/adr/ is a squat; every ADR-0132 token was replaced by a PR reference (#16215) and the gate went green. Cross-repo objectui anchors are skipped-not-judged by default, so the gate was additionally re-run with OBJECTUI_CHECKOUT set: both left the skipped list and it stayed green (checkout at objectui 24e027e; this repo pins a472b07 in .objectui-sha - stated, not implied). ONE gate answered exit 3 = PREREQUISITE NOT MET (not a pass, not a finding): @objectstack/lint check:doc-formula-expressions refuses to run against unbuilt workspace output. CLEARED rather than reported - built the two packages it names through the shared verify lock (`scripts/pm/os-verify-lock.sh`, VERDICT command-exit 0, held 112s, waited 0s) and re-ran it green: '22 record-scoped formula example(s) across 430 files / 1371 TS blocks judged clean'. No repo-wide `pnpm lint` sweep was run locally - that is CI's; no CI state is predicted anywhere in the PR body.",
      "mcp_calls": "7 - issue get, issue get_comments, PR #16215 get, list_pull_requests (the ADR-number check), create_pull_request, plus failed get_labels retries that returned the shared-identity rate-limit error",
      "open_questions": [
        {
          "question": "ADR NUMBER: I took 0133. Checked against (a) `ls docs/adr/` on origin/main (highest = 0131), (b) #16215's branch, which adds docs/adr/0132-multi-organization-runtime-is-open-core.md - so 0132 is claimed by an open PR though free on main, and (c) all 40 open PRs listed, only #16215 claiming a number. Re-derived against a freshly fetched origin/main (697117079) immediately before the PR; 0131 still the highest and 0133 still free. If #16215 does not merge this leaves a gap at 0132.",
          "options": ["A - keep 0133 (a gap is cheap, a collision is expensive)", "B - take 0132 and race #16215"],
          "recommendation": "A. A number free on main is not free if an open PR claims it, and check:adr-anchors treats a citation of an unwritten number as a squat."
        },
        {
          "question": "DISPATCH CONFLICT, flagged rather than silently resolved. Comment 5557377980 (director seat) says to EXTEND ADR-0132 rather than open a second local mirror. My binding dispatch brief (the PM claim, comment 5558046264) says to write ONE new ADR and treat #16215 only as a NUMBER collision. ADR-0132's own body sides with the brief: its 'What this record does not decide' section says D1/D3/D4 'are mirrored into this repository by #14508' and only warns against a COMPETING record. Extending it was also not mechanically available: the file does not exist on origin/main, so extending would mean basing this branch on an unmerged governed PR and coupling two hand-merges. I wrote a disjoint record that decides nothing ADR-0132 decides, and recorded the whole conflict inside the ADR under 'Relationship to the D2 reversal' so the maintainer sees it at hand-merge.",
          "options": ["A - land 0133 as a disjoint record and let the maintainer fold at hand-merge if preferred", "B - hold this card until #16215 merges, then extend it"],
          "recommendation": "A. The two files are disjoint, so folding them later is a move, not a rewrite; B blocks a ready card on another seat's governed hand-merge for an unknown time."
        },
        {
          "question": "GAP FOUND, not filled: 'the org record page opens on tab-0 Members' is asserted by this repo's comments and a QA checklist item but declared by NONE of its metadata. Measured on origin/main 77781151d: zero objects under packages/platform-objects/src/identity/ declare the `relatedList` prominence key (packages/spec/src/data/field.zod.ts#relatedList) - the key objectui reads to promote a child list to its own tab (objectui packages/app-shell/src/utils/deriveRelatedLists.ts derives isPrimary from it) - and no `relatedLayout` override exists anywhere in this repo. Under the documented default with no primary list, related lists collapse into ONE stacked tab. The ADR therefore states the deep-link contract (declared) and does NOT assert a tab order (not declared), recording the discrepancy under 'What this record does not decide'.",
          "options": ["A - file it as a separate issue for triage", "B - declare relatedList: 'primary' on the org children in this PR"],
          "recommendation": "A. B is a metadata change, which the card's Clause-2 declaration forbids without stopping and reporting first - which is what this is."
        }
      ],
      "out_of_scope_findings": [
        "COULD NOT FILE - the shared identity's GitHub API rate limit was exhausted at report time, so the dedup search and the issue write both refused. Handing the finding to the PM to file: 'The org record page tab strip is asserted but not declared - no relatedList prominence key anywhere in packages/platform-objects/src/identity/'. Evidence: two source comments (packages/platform-objects/src/identity/sys-member.object.ts, invite-entry-toolbar.test.ts) and docs/qa/platform-checklist/areas/identity-auth.json describe a Members/Invitations/Teams tab strip with Members at tab-0; measured on origin/main 77781151d, `git grep -rn 'relatedList' -- packages/platform-objects/src/identity/` returns ZERO hits and no relatedLayout override exists in the repo, so objectui's documented default collapses every related list into one stacked Related tab. Either the metadata is missing a declaration or three documents are stale. Observation-class, no assignee; suggest label `finding`."
      ]
    }

    Anchors re-located on origin/main at 77781151d (⛔ not one offset copied)

    card's anchor what is there now how the ADR cites it
    sys-member.object.ts:47 unmoved — the invite_user mirror comment #invite_user (symbol)
    invite-entry-toolbar.test.ts:4 unmoved — the file header comment #INVITE_ENDPOINT, #OBJECTS_BY_NAME
    sys-user.object.ts:59 MOVED to line 89 — the org-capability gate comment #invite_user, #requiresFeature

    Line numbers appear in this table only; ⛔ none appears in the ADR, because check:adr-symbol-anchors reds on them.

    ⚠️ skip-changeset was judged applicable (the diff publishes nothing from any package; docs/adr/** is the documented example) but could not be applied: the additive REST endpoint answers 403 for this seat, and the MCP fallback refused with the shared-identity rate limit. The label still needs applying.


    Generated by Claude Code

  7. os-warren commented on Sep 6, 2026

    @os-warren
    Collaborator

    Amendment to the os-dev-report above (comment 5558217080) — two fields only. ⛔ Not a second report; the report comment above stays the one to parse, with these two corrections applied.

    Both items were reported as blocked because the shared identity's GitHub API rate limit was exhausted at the moment the report went out. The window cleared a few minutes later and both were completed, so the report's own text is now stale where it says they were not.

    1. out_of_scope_findings — the finding IS filed. Replace the "COULD NOT FILE …" entry with:
      filed as #16270: the org record page's Members/Invitations/Teams tab strip is asserted in three places (two identity source comments and the identity-auth QA checklist) but declared by no metadata — zero relatedListprominence keys underpackages/platform-objects/src/identity/, and no relatedLayout override in the repository.
      Deduplicated before filing with one targeted search, whose control hit was console: org record page's default Members tab hides the email-invite entry — invite_user lives only on the Invitations tab #11544 — the closed card that introduced the tab-0 rationale in the first place — so the search was answering, not empty. No open duplicate. Filed with finding + documentation, no assignee, no pm:queue, per the observation-class rule.

    2. skip-changeset IS applied to docs(adr): ADR-0133 — organization management, the open basics; mirroring cloud ADR-0081 D1/D3/D4 with Provenance #16267. The trailing ⚠️ note in the report says the label still needs applying; it no longer does. The additive REST endpoint is still 403 for this seat, so it went through the MCP whole-set fallback with the mandated compare-read-back: read ["documentation", "size/m"] → wrote the union → read back exactly ["documentation", "size/m", "skip-changeset"]. Nothing was stripped, so no concurrent label was lost to the whole-set write.

    Nothing else in the report changes. The PR (#16267) is still draft and stays that way — docs/adr/** is governed, so the maintainer hand-merges; ready was never flipped and auto-merge was never armed.

    Channel note for the PM, since it cost real time this round: repo-scoped REST reads and the additive labels endpoint both answer 403 for this seat, and the MCP fallback was rate-limited for roughly 13 minutes on the shared identity. Both writes succeeded on retry after an in-round blocking wait; no work was redone.


    Generated by Claude Code

  8. os-warren commented on Sep 6, 2026

    @os-warren
    Collaborator

    ⛔ My briefing was wrong on one point — owning it here, where I made the error

    @hotlong — PR #16267 delivers this card, but it opened a second local mirror (ADR-0133) instead of extending ADR-0132, which is contrary to your pointer 5557377980.

    That is my fault, not the dev seat's. I dispatched from this card's body alone and never read its comments — even though the triage comment 5545413919 says, in as many words, 「认领前请读它」. So my brief framed #16215 as a number collision when you had framed it as a writer collision. The seat read your pointer, saw it contradicted its binding brief, ⛔ refused to resolve the conflict silently, and recorded it in both its report and the ADR body. Correct behaviour on its part; the failure was mine, one step earlier.

    ⚠️ This is the second time this session that reading a card's body but not its comment history has cost me. It is now a fixed step in my dispatch, not a resolution.

    The full decision, with two measurements that bear on it, is on the PR: #16267 (comment 5558242242). The short version:

    1. ADR-0132 is not on origin/main (grep -c 0132 → 0; highest is 0131) — it exists only on feat(organizations): bring the multi-organization runtime back to open core — the org-scoping registrar ships open, the licence gate stays in cloud (ADR-0132) #16215's draft branch, so extending it means basing this branch on an unmerged governed PR.
    2. ⭐ ADR-0132 already has its own D1, D3 and D4, and they are different decisions from cloud ADR-0081's D1/D3/D4. Folding this card's into that file gives one record two different D1s. ADR-0132's own body says "D1, D3 and D4 of that record are untouched."

    ⛔ I have not treated either as overruling you — the A/B choice (land 0133 disjoint, or hold this card until #16215 merges and extend that file) is yours, and it is a human-merge surface anyway. If the answer is B I will hold the card; the written text becomes the extension rather than being wasted.

    Your other pointer (5536478826) was honoured in full: ADR-0131 D1/D7/D9 are in the cross-check, and ⛔ D4 does not decide whether sys_member keeps its column — it cites the C6 census (#15207) and lets it speak.

    One out-of-scope finding filed rather than fixed: #16270 — the org record page's tab-0 Members ordering is asserted in three documents but declared by no metadata.

    domain:services PM seat · dispatch error owned; the record's disposition escalated, not decided


    Generated by Claude Code

  9. os-warren commented on Sep 7, 2026

    @os-warren
    Collaborator

    os-dev-report

    {
      "issue": 14508,
      "status": "done",
      "branch": "claude/issue-14508-adr-org-management-open-basics",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/16267",
      "premise_still_valid": true,
      "summary": "Re-pointed docs/adr/0133-org-management-open-basics.md at ADR-0132, which has landed on main as docs/adr/0132-multi-organization-runtime-is-open-core.md (squash c677cda81, 2026-09-07 05:30 UTC). All five dispatch-named sites were rewritten by text anchor, plus the same section's second paragraph, which carried BOTH the cite-by-PR-number rule and this file's own update trigger; zero occurrences of the old PR number survive in the file (grep count 0). The header bullet no longer says D2 stays in cloud: it now says D2 was REVERSED, that what stays in cloud is the RECORD plus the non-goals and commercial consequences the reversal leaves untouched, and that the machinery ships in this repository. DEVIATION TO NOTE: origin/main was merged into the branch (merge commit c83097a1f) because check-adr-anchors and check-adr-links read the WORKING TREE - a citation of ADR-0132 goes RED on a branch that does not contain that record, so the dispatch's required exit 0 was unreachable without it. That is a local git merge; update_pull_request_branch was NOT called, per the dispatch. PR still DRAFT; no ready flip, no auto-merge, no queue, no changeset, no label writes. Division of labour untouched: ADR-0132 states it does not touch cloud ADR-0081 D1/D3/D4, which is this file's entire content, so 0133 only cites and re-derives nothing.",
      "tests": "Head sha d2c2579b0 (branch also carries merge commit c83097a1f). Every exit code captured immediately after a single redirected command, never through a pipe. THREE DISPATCH-NAMED GATES: node scripts/check-adr-anchors.mjs EXIT=0 - verdict 'check-adr-anchors: OK (53 anchored file(s), every governing ADR still referenced; 131 decision number(s), each naming one decision or an allowlisted pair; 33637 citation(s) across 4260 file(s) resolve; 997 decision-letter citation(s) on the anchored surface name a decision the record makes).' (baseline before the edit was 33630 citations, so the new ADR-0132 citations resolve). node scripts/check-adr-symbol-anchors.mjs EXIT=0 - verdict 'check-adr-symbol-anchors: 1970 anchors across 137 records resolve - 218 symbol (195 declaration, 23 literal), 1729 file-level, 23 cross-repo, 6 exempt, 3 continuation. 0 line anchors survive.' node scripts/pm/check-governed-merges.mjs --test docs/adr/0133-org-management-open-basics.md EXIT=3 - verdict 'GOVERNED - a human merge is the review record for this PR', 'docs/adr/** x1'. As specified: that is the confirmation, not a failure. GATE FAMILY: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands, derived at commit d2c2579b0 (the FINAL commit) from merge base a5eccf925, change set = 1 path. 17 commands, ALL 17 EXIT=0. One needed clearing first: pnpm --filter @objectstack/lint run check:doc-formula-expressions answered EXIT=3 PREREQUISITE NOT MET (@objectstack/formula and @objectstack/lint unbuilt) - recorded as NOT MEASURED, not as green; cleared by building both through the shared verify lock (scripts/pm/os-verify-lock.sh, VERDICT command-exit 0, held the lock 188s, waited 0s) and re-run to EXIT=0 with the real reading '22 record-scoped formula example(s) across 432 files / 1371 TS blocks judged clean' plus its spec-TSDoc and field-level legs. Other verdict lines: check-adr-links '667 relative link destination(s) under docs/adr/ resolve' (this is what checks the new relative links and the renamed heading anchor); check-doc-authoring '396 files clean'; check-nul-bytes 'OK (scanned 8128 text file(s) ... no raw ASCII control bytes)'; check-closing-keyword-parity 'OK (3 parsers agree on all 9 keywords ... all registered)'; check-ci-filter-parity, check-comment-mask-corpus, check:cross-package-test-inputs, check:driver-memory-census, check:pm-governed-merges, check:refd-timer-probe, check:watch-hint-literal and the four --self-test halves all EXIT=0. NARROWED LINT SCAN, declared with its three readings: population read from eslint's own flat config (the changed path answers 'File ignored because no matching configuration was supplied'), file count read from --format json (one entry, errorCount 0, only the ignore notice - zero files linted), and invariance for untouched files (no eslint config file is in the diff, and the one changed path is markdown that no config object matches). The repo-wide pnpm lint sweep is CI's. NOT MEASURED, reported as such: dispatch-gates also names 10 declared-wide families, 32 undetermined and 2 workflow-valued commands (check-shard-attestation, check-test-completeness) - their absence is not a clearance. CI ON d2c2579b0 at report time: Check Changeset conclusion=SKIPPED (not red - the stale 08:49 failure named in the dispatch is gone, skip-changeset label present); TypeScript Type Check, Test Core, Build gates, Governed Surface Queue Guard, Check PR Size, Check Documentation Links, Auto Label, Part-of PR must not also close its card, and both single-claim guards all conclusion=success; Lint & Repo Gates still status=in_progress (reported honestly, not waited on).",
      "mcp_calls": "6 - pull_request_read(get), update_pull_request(body), pull_request_read(get_check_runs), pull_request_read(get_status), pull_request_read(get_check_runs), add_issue_comment(this report). CHANNEL SWITCH DECLARED: repo-scoped REST is 403 on this seat - GET /repos/objectstack-ai/objectstack/pulls/16267 returns 403 both anonymously and with the session token, while GET /user returns 200, and gh is absent - so the measured 403 shape applies and writes go through MCP. PR state, head sha and draft flag were additionally read at ZERO MCP quota from the public PR page's embedded JSON payload, and the PR body and this comment were read back the same way.",
      "open_questions": [],
      "out_of_scope_findings": [
        "NOT FILED, reported at the dispatch's explicit instruction (report, do not touch): docs/adr/0132-multi-organization-runtime-is-open-core.md still carries '- **Status**: Proposed (2026-09-06) - awaiting the maintainer's hand-merge, which is itself the acceptance act for a governed surface' and '⛔ Nothing below is settled until this record merges', although it merged on 2026-09-07 as c677cda81. Residue on another seat's record; nothing in this PR edits it. PM to file or route.",
        "NOT FILED, observation only: the SHARED git dir /home/user/objectstack/.git/os-regen-pending carried a stale marker from 2026-09-04 naming content/docs/permissions/system-context.mdx - another agent's leftover, in state a worktree does not isolate. node scripts/check-regen-pending.mjs verified it clean and exited 0, so it blocked nothing here; I did not delete it.",
        "NOT FILED, noted for the hand-merge: ADR-0133's Provenance section still says its facts were 'measured on this repository's origin/main at 77781151d'. That is an honest statement of WHEN it was measured, not a currency claim, so it was left alone; the one negative claim it carries (no relatedList prominence key under packages/platform-objects/src/identity/) was re-verified on today's origin/main and still holds (grep exit 1, zero matches)."
      ]
    }

    Generated by Claude Code

  10. os-warren commented on Sep 7, 2026

    @os-warren
    Collaborator

    Amendment to the os-dev-report above (comment 5566276787) — three fields only. ⛔ Not a second report; that comment stays the one to parse, with these corrections applied.

    Reading this card's comment history for the read-back surfaced a fact the report's edit had understated, so one more commit went out. Head moved: d2c2579b0 → 01b450d40.

    1. summary — one more site changed, six not five. The ⚠️ A note for the hand-merge paragraph said the only thing blocking a single combined record was ADR-0132 being unmerged, and that with it landed the choice "stands on its merits alone". True but incomplete, and the missing merit is the one the PM escalated to the maintainer on 2026-09-06 (comment 5558244155): ADR-0132 carries its own D1 through D6, different decisions from cloud ADR-0081's D1/D3/D4, so folding this mirror into it would put two unrelated D1s in one document — precisely the property the deliberately unrenumbered mirror exists to keep checkable. That obstacle is now named in the file. ⛔ Still stated, not decided: the disposition remains the maintainer's merge-time call and this change takes the option neither way.

    2. tests — the whole union was re-derived and re-run on the new final commit. node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands at 01b450d40 returns the same 17-command family (diffed against the previous derivation, identical), and all 17 exit 0 on that tree — check:doc-formula-expressions included, its prerequisite already built. Verdict lines unchanged except check-adr-anchors, now 33638 citation(s) across 4260 file(s) resolve. check-adr-symbol-anchors still prints 0 line anchors survive; check-governed-merges --test still exits 3, GOVERNED.

    3. mcp_calls — the true total for the run is 9, not 6. The count stated in the report was correct when written; the mandated comment read-back and this round necessarily follow it. Full list: pull_request_read(get), update_pull_request(body), pull_request_read(get_check_runs), pull_request_read(get_status), pull_request_read(get_check_runs), add_issue_comment(report), issue_read(get_comments — the read-back), update_pull_request(body, second revision), add_issue_comment(this). ⚠️ Channel note for the PM: the zero-quota web read works for a PR's embedded payload (state, head sha, draft flag — used and verified this round) but not for issue comments — this repo's issue page is a React shell whose HTML carries no comment bodies, so a comment read-back has to go through MCP. Repo-scoped REST stays 403 for this seat.

    The PR body has been updated to match. #16267 is still draft and stays that way — docs/adr/** is governed, so the maintainer hand-merges; ready was never flipped, auto-merge was never armed, and the branch was never updated through the API.


    Generated by Claude Code

  11. github-actions commented on Sep 7, 2026

    @github-actions
    Contributor

    os-closed-card-sweep — machine-findable marker for this generated comment.

    Removed the pm-loop state label(s) this closed card no longer claims: pm:dispatched.

    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 34097314575 · trigger schedule

    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions