Skip to content

platform-admin re-anchor L4 (plugin-security): bootstrap stops granting under walled postures; explain reports config-derived standing; deprecation log for legacy grants #11974

Description

@os-support-ai

Leg L4 of the accepted #11663 platform-admin re-anchor design. Provenance: design document = #11663 comment 5394453215 (§6 row L4, migration step 4); maintainer acceptance = #11663 comment 5404675670 (2026-08-25, verbatim 「接受你的建议,继续」). Filed by PM session session_01KWRU3s15AJz7PGW7a7wdCh.

Blocked-by: #11970

Surface: packages/plugins/plugin-security.

Content:

  • bootstrapPlatformAdmin stops writing grant rows under walled postures (Choice 4A: single keeps first-user promotion and its grant row — that branch stays inside the one derivation site, never a second site).
  • Local isEmailVerified deleted in favour of core's promoted one (L2); replay narrowed accordingly.
  • The platformAdmin service registered; explain reports config-derived standing (pin Implement ObjectStack protocol specification with Zod schemas and TypeScript interfaces #3 auditability: the resolved admin list surfaced read-only — Setup / discovery / health — since no grant row is left to query).
  • This is the step where the deprecation log starts firing: a detected legacy row-id grant logs a pointer at the config path (pin [WIP] Fix error in step four of the action run #5 loud migration; ⛔ never a silent dual-track). File the legacy-path removal card (L5's removal half) at this leg's landing, not later.

Discipline: Clause-② expected yes; needs:contract-review at review. Also touches packages/verify/src/harness.ts fixtures (verified-email shape).

Acceptance criterion: on a walled rig with the variable set, bootstrap mints no org-less grant; explain/standing surface reports the config-derived admin list read-only; a seeded legacy grant produces exactly one deprecation log line naming OS_PLATFORM_OWNER_EMAIL.

Activity

  1. added
    pm:blockedBlocked by another issue/PR — body carries Blocked-by: #N
    on Aug 25, 2026
  2. added
    domain:servicesRetired 2026-10-22, alias of domain:server (services surface); in-flight cards keep it until landed
    pm:queueReady for the PM dispatch loop
    and removed
    pm:blockedBlocked by another issue/PR — body carries Blocked-by: #N
    on Aug 28, 2026
  3. huangyiirene commented on Aug 29, 2026

    @huangyiirene
    Collaborator

    解锁:pm:blocked → pm:queue(L4)

    证据:阻塞源 #11970 state: closed · state_reason: completed · closed_at: 2026-08-29T09:58:29Z,由 MERGED PR #13146 关闭。

    ⚠️ 三张卡同时解锁并争抢同一批文件 —— ⛔ 不要并行认领

    本卡重写 bootstrap-platform-admin.ts,而 #13147 要动的六个读者里就包含它,L3 #11973 紧邻另外两个。

    ⭐ 建议顺序:L3 → 本卡 L4 → #13147,或把 #13147 吸收进 L3/L4 两条腿。完整争用表见 #13147 (comment) 。

    ⚠️ 一条针对本卡的具体提醒:#13147 测出 bootstrap-platform-admin.ts:404 在 OS_PLATFORM_OWNER_EMAIL 为逗号列表时找不到任何账号,并永远打印 "will be promoted when that account registers"。⇒ 既然本卡本来就要重写这个文件,顺手用共享解析器(PR #13146 已引入 parsePlatformAdminEmails 等)解决它,很可能比让 #13147 之后再来改一遍便宜。⛔ 但这是取卡人的范围判断,我不代裁,也不擅自把 #13147 的范围并进本卡。

    ⛔ 我没有用 pm:blocked 压住本卡来强制顺序——那会是一个 body 里没有依据的隐形阻塞。


    Generated by Claude Code

  4. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Aug 30, 2026
  5. self-assigned this
    on Aug 30, 2026
  6. os-steve commented on Aug 30, 2026

    @os-steve
    Collaborator

    Claim: PM loop round 6
    Session: session_016ZC5rNQj3WEet5HAmmAkMs
    Branch: claude/issue-11974-l4-plugin-security-walled-bootstrap
    Worktree: objectstack-issue-11974
    Domain: domain:services
    File surface: packages/plugins/plugin-security/src/ (bootstrap-platform-admin.ts, security-plugin.ts, platform-owner-wall-bypass.ts + their tests), packages/verify/src/harness.ts fixtures, one changeset (stop on breach; explain in the report)
    Container & model: L, mode:subagent, model: claude-fable-5 — CONTRACT_REVIEW_TIER, read live at origin/main:scripts/pm/dispatch-gates.mjs:5733. ⛔ Not a judgement call: the card mandates it in its own Discipline block ("Clause-②: expected yes; needs:contract-review at review").
    Clause-②: yes
    Serial constraints cleared: ✅ plugin-security is now free — #11971 (explain-engine.ts) CLOSED 14:44:31Z via MERGED PR #13415, verified by merge-base --is-ancestor and by the card's closed_by_pull_requests, ⛔ not by the branch being gone. ⛔ plugin-auth remains held by claude/issue-12981-batch5-plugin-auth (live, last push 14:31Z) — this card's surface does not enter it. #11973 (L3) is the sibling leg in plugin-auth, not dispatched, so ⛔ do not edit it there either.

    ⛔ Seat boundary

    Clause ② by content (authorization-adjacent standing semantics). This seat measures claude-opus-5, below CONTRACT_REVIEW_TIER. It dispatches at tier but ⛔ will not clear needs:contract-review, flip ready, enqueue, or arm auto-merge. The PR parks as a draft — designed outcome, not a failure. Keep CI green.

    裁决 — 不可重裁 (维护者 2026-08-25, #11663 comment 5404675670, verbatim「接受你的建议,继续」, bundle 1A/2B/3A/4A/5A/6A/7A)

    • Choice 4A: single posture keeps first-user promotion and its grant row. That branch stays inside the one derivation site — ⛔ never a second derivation site.
    • bootstrapPlatformAdmin stops writing grant rows under walled postures.
    • The platformAdmin service is registered; explain reports config-derived standing (pin Implement ObjectStack protocol specification with Zod schemas and TypeScript interfaces #3 auditability — the resolved admin list surfaced read-only, since no grant row is left to query).
    • The deprecation log starts firing at this leg: a detected legacy row-id grant logs a pointer at the config path (pin [WIP] Fix error in step four of the action run #5 loud migration; ⛔ never a silent dual-track).
    • File the legacy-path removal card (L5's removal half) at this leg's landing, not later.

    ⚠️ STALE PREMISE — one of the card's four work items is already effectively done, and it points at a home that does not exist

    The card says: "Local isEmailVerified deleted in favour of core's promoted one (L2)." Measured on origin/main at dispatch, with reverse controls:

    ❌ core has NO promoted isEmailVerified.
       packages/core/src/security/platform-admin.ts:56
         import { isEmailVerifiedUserRow, … } from '@objectstack/types';   ← core IMPORTS it
       packages/core/src/security/platform-admin.ts:277   return isEmailVerifiedUserRow(row);
    
    ✅ the canonical implementation lives in TYPES, not core:
       packages/types/src/email-verified.ts:24   export function isEmailVerifiedUserRow(row: unknown): boolean
    
    ✅ plugin-security ALREADY consumes it from there:
       platform-owner-wall-bypass.ts:51   import { isEmailVerifiedUserRow } from '@objectstack/types';
       bootstrap-platform-admin.ts:167    const isEmailVerified = isEmailVerifiedUserRow;   ← a one-line ALIAS
    

    ⇒ The consolidation L4 was written to perform already happened, into @objectstack/types rather than into core. What is left of that work item is deleting a one-line local alias — a readability choice, ⛔ not a consolidation, and ⛔ not a reason to touch packages/types.

    ⚠️ Treat this as the shape, not just the fact: the card describes a five-day-old plan, and L2 shipped somewhere the plan did not predict. Re-derive every other work item against the tree before implementing it — ⛔ do not trust this card's remaining prose merely because this seat corrected one line of it.

    What this seat measured as STILL OUTSTANDING (real work remains — this is not a premise-false card)

    ✅ platformAdmin service NOT yet registered — zero "platformAdmin" in security-plugin.ts
    ✅ bootstrap still walled-aware but still row-writing:
         bootstrap-platform-admin.ts:333  "[#11532] Under a walled posture these rows are organization-less BY RULING"
         bootstrap-platform-admin.ts:15-17 carries the #11184 posture ruling already
    

    ⇒ The grant-row stop, the service registration, the config-derived explain surface and the deprecation log are all genuinely undone.

    PM mechanism assumptions — measure these; I would rather be falsified

    1. That L4 may land before L3 (platform-admin re-anchor L3 (plugin-auth): re-point ensure-default-organization; re-price last-admin-guard as its own reviewed step #11973). The design's §6 puts L4 at migration step 4 and L3 at steps 4–5 — overlapping, and I did not read §6 to establish whether an order is imposed. L3 is fenced behind a live plugin-auth branch and is not being dispatched, so if the design requires L3 first, stop and report — ⛔ do not reach into plugin-auth to unblock yourself.
    2. That packages/verify/src/harness.ts still needs a fixture change. Card says it does. Measured: the file exists (reverse control: 3 export matches) but email_verified occurs zero times in it. Either L2 already handled the shape or it is expressed differently. ⛔ Re-derive; do not add a fixture the harness does not want.
    3. That "stops granting under walled postures" is a deletion and not a re-pricing. :333 says those rows are organization-less by ruling. Removing their creation may orphan readers — ⚠️ auto-org-admin-grant resolves the organization_admin set id by name alone (limit 1, unscoped, process-cached), so walled org-admin grants can point at the organization-less row #11670 is an open card about auto-org-admin-grant resolving the organization_admin set id by name alone and pointing at exactly the organization-less row. Enumerate the readers before deleting the writes, and report what you find; if a reader breaks, that is a fork, not a fix-in-passing.

    Non-negotiable, carried from the card

    • ⛔ Do not delete or add guard refusals as a side effect. L3's last-admin-guard re-pricing is its own reviewed step and is not in this dispatch. If a refusal looks obsolete, report it — ⛔ do not act on it here.
    • Every deleted or added guard refusal must be enumerated in the PR body with its re-pricing rationale. (Applies to any that prove unavoidable within L4's own scope.)
    • Acceptance: on a walled rig with the variable set, bootstrap mints no org-less grant; the standing surface reports the config-derived admin list read-only; a seeded legacy grant produces exactly one deprecation log line naming OS_PLATFORM_OWNER_EMAIL.
    • File the L5-removal-half card at landing — that is part of this dispatch's definition of done, ⛔ not a follow-up someone else will remember.

    Gates

    Re-derive from your worktree at origin/main and from your actual diff: node scripts/pm/dispatch-gates.mjs <changed paths>. ⚠️ The shared checkout the PM ran from was behind origin/main; derive from a fresh tree, ⛔ not from a remembered gate list.

    Report

    Land the terminal report as a comment on this issue first, then as the return message. Machine-checkable fields only (gates / line_budget / deviations / files_changed / premise_still_valid / pr / status / open_questions / out_of_scope_findings); ⛔ do not restate the PR body's narrative. premise_still_valid: false with no PR is a legitimate delivery — assumption 1 is a real ordering fork.


    Generated by Claude Code

  7. os-steve commented on Aug 30, 2026

    @os-steve
    Collaborator

    Claim (dev): implementing L4 on branch claude/issue-11974-l4-plugin-security-walled-bootstrap, worktree objectstack-issue-11974, base 3800e42932cd4b78a403df8b8107661ac494db97.

    Session: session_016ZC5rNQj3WEet5HAmmAkMs (os-dev subagent dispatched by the PM claim above, mode:subagent; same session id as the PM seat by construction — this comment is the dev-side claim, distinct from the PM's dispatch comment 5469415591).

    Read before writing code: issue body (complete, not truncated), both comments, design 11663#issuecomment-5394453215 in full (§2 flow, §5 steps 4-6, §6 row L4), acceptance 11663#issuecomment-5404675670 (bundle 1A/2B/3A/4A/5A/6A/7A).

    Scope fence honored: packages/plugins/plugin-auth/** and packages/types/** untouched.


    Generated by Claude Code

  8. os-steve commented on Aug 30, 2026

    @os-steve
    Collaborator

    os-dev-report

    {
      "issue": 11974,
      "status": "done",
      "branch": "claude/issue-11974-l4-plugin-security-walled-bootstrap",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/13514",
      "premise_still_valid": true,
      "summary": "L4 landed as draft PR 13514 at d5eeda5, parked with needs:contract-review (label verified by read-back beside size/xl; nothing stripped). Walled postures stop minting the grant row; single unchanged (4A). Read-only platformAdmin service registered (configuredEmails + standing, frozen, no writable member); walled boot logs the same standing answer. Legacy-grant deprecation pointer wired boot-side through core's shared once-per-process latch; pinned exactly-one line naming OS_PLATFORM_OWNER_EMAIL. Explain pin added: declared+verified admin with zero grant rows explains PLATFORM_ADMIN. shouldReplayBootstrapFor narrowed to single+insert/create. L5-removal-half card filed as 13515 (sub-issue of 11663, unassigned). Two card work items were dead against the tree: the isEmailVerified consolidation (already in @objectstack/types; only a one-line alias deleted) and the harness fixture change (dev-admin seed already stamps email_verified true; harness untouched).",
      "gates": "15 families re-derived from actual diff via dispatch-gates.mjs at 3800e42 (objectstack tree named on stderr) and re-run green at final commit d5eeda5 in one union with the package suite: 14 derived families + check:nul-bytes, plugin-security 90 test files / 1664 tests, package typecheck (UNION-RC=0, whole-batch accumulator). Two mid-run reds fixed, both mine: check:doc-authoring (issue id in a runtime log string; stripped) and check:objectql-double-limit (new test double was limit-blind; bound applied by presence). check:dual-build-cjs-loads was first PREREQUISITE-NOT-MET (8 unrelated packages had no local dist) - read as NOT MEASURED, converted by building them, then green. CI convergence is the PM's read per standing contract.",
      "tests": "Union at d5eeda5 (cited from the run after the final commit): plugin-security 1664/1664 + typecheck via 'pnpm --filter @objectstack/plugin-security test/typecheck' under os-verify-lock (VERDICT lines read, exits captured unpiped). Downstream at same tree: verify harness posture suites 4 files 18/18; walled dogfood fixtures (rls-multitenant, attachments-permission-matrix, showcase-external-autoconnect) 18 passed / 3 env-skipped. New pins: walled no-write family incl. group posture and the verify-update re-run sequence now asserting no write; legacy pointer exactly-once across two bootstraps via swapped core sink + latch reset; service standing/configuredEmails family incl. frozen no-writable-member; explain config-derived PLATFORM_ADMIN with zero grant rows; middleware seam re-derived (insert re-runs, verifying update no longer does).",
      "line_budget": "+875/-498 across 10 files (no numeric budget was set in the dispatch); skills/** untouched",
      "deviations": [
        "Walled all-good outcome reason renamed to walled_config_derived; walled_owner_not_registered/not_verified retired as return reasons (their distinction lives in the standing report; fail-closed verified-only enforcement pinned in core). walled_owner_email_undeclared kept verbatim.",
        "claimSeedOwnership no longer runs under walled postures (it was keyed on the promoted admin, which no longer exists there); declared in the PR body for the contract reviewer.",
        "Local verification narrowed to derived gate families + full package suite + targeted downstream walled fixtures; the repo-wide farm is CI's run (standing contract narrowing, declared).",
        "plugin-auth prose staleness reported on 11973 (comment 5469741477) instead of edited - fenced package."
      ],
      "files_changed": [
        ".changeset/walled-bootstrap-stops-granting.md",
        "packages/plugins/plugin-security/src/bootstrap-platform-admin.ts",
        "packages/plugins/plugin-security/src/bootstrap-platform-admin-walled-owner.test.ts",
        "packages/plugins/plugin-security/src/platform-admin-service.ts (new)",
        "packages/plugins/plugin-security/src/platform-admin-service.test.ts (new)",
        "packages/plugins/plugin-security/src/security-plugin.ts",
        "packages/plugins/plugin-security/src/security-plugin.test.ts",
        "packages/plugins/plugin-security/src/explain-engine.test.ts",
        "packages/plugins/plugin-security/src/platform-owner-wall-bypass.ts",
        "packages/plugins/plugin-security/src/index.ts"
      ],
      "mcp_calls": "12 - issue/comment reads (3), claim + report + 11973-note comments (3), PR create (1), label write (1, additive-equivalent + read-back via zero-quota web channel), failed get_labels probe on the PR (1), 11663 sub-issue list (1), dedupe search (1), 13515 create (1); bulk reads of 11663 design + 11975 + PR body read-back went through the zero-quota web channel",
      "open_questions": [
        {
          "question": "PM assumption 1 measured: design section 6 imposes NO L3-before-L4 order (L3 and L4 each depend on L2 only) - so this landed. But migration step 4 spans both legs, and the enterprise organizations package (out of repo) reuses ensureDefaultOrganization, which still finds the admin via grant rows and triggers on grant inserts: a FRESH walled rig on that package will not auto-create its default org between L4 landing and L3. In-repo paths are unaffected (plugin-auth's bootstrap is gated !postureEnforcesWall - measured).",
          "options": ["A: merge L4 when contract review clears; the window is L3's (11973) and is flagged in the PR body and on 11973", "B: hold PR 13514 until L3 lands"],
          "recommendation": "A - the design's dependency table allows it, existing rigs keep their rows (nothing revoked), and the window is now recorded on the card that owns closing it."
        }
      ],
      "out_of_scope_findings": [
        "filed as #13515: L5 removal-half card (in-card deliverable, filed at landing as sub-issue of 11663, unassigned/unlabeled for triage)",
        "reported on #11973 (comment 5469741477): walled-owner-verification-path.ts and walled-owner-operator-stamp.ts prose references retired bootstrap outcomes - fenced, L3's file family"
      ]
    }

    Generated by Claude Code

  9. os-steve commented on Aug 30, 2026

    @os-steve
    Collaborator

    ✅ ACCEPT — PR #13514, parked at the contract-review gate by design

    domain:services PM seat, session session_016ZC5rNQj3WEet5HAmmAkMs, R6. Reviewer of record. Every line below was checked against GitHub and the tree, ⛔ not against the report's self-description.

    Checklist

    item verdict
    PR shape ✅ draft, base main, Fixes #11974 on line 1, Part of #11663 — verified on the PR object, ⛔ not from the report
    Scope / fences ✅ 10 files, all packages/plugins/plugin-security/src/ + one changeset. Enumerated the file list and tested it against the fence set: zero hits in plugin-auth/**, packages/types/**, packages/core/**, content/docs/releases/**. The plugin-auth fence held while claude/issue-12981-batch5-plugin-auth was live beside it
    Changeset ✅ .changeset/walled-bootstrap-stops-granting.md (+46); Check Changeset green
    Clause ② ✅ needs:contract-review hung on the PR, and correctly — index.ts (+13) widens plugin-security's published surface with the new service
    CI ✅ converging with zero reds. Green already: Check Changeset · Governed Surface Queue Guard · Type Check · source gates · Check Documentation Links · Flag docs affected by code changes · Part-of PR must not also close its card · No other open PR may claim the same issue · No other open PR may claim the same single-writer path — the last two are CI independently confirming the serial fences this seat asserted at claim time. Remainder in_progress; at draft time that is an honest reading, ⛔ not a pass
    In-card deliverable ✅ #13515 filed at landing, as the card demanded — sub-issue of #11663, unassigned and unlabelled for triage, Blocked-by: #11975, and it carries the minor-boundary timing constraint rather than dropping it
    Guard refusals ✅ none deleted, none added; L3's last-admin-guard re-pricing untouched. walled_owner_email_undeclared kept with its exact reason string
    Out-of-scope handling ✅ Prose staleness found in plugin-auth's L3 file family was reported on #11973 (issuecomment-5469741477), ⛔ not edited across the fence. That is the fence working, not a miss

    ⭐ Two of the card's four work items were dead against the tree — and the dev reported both instead of manufacturing a diff

    The isEmailVerified consolidation was the stale premise this seat measured and carried into the brief; the dev confirmed it and deleted only the one-line alias. It then independently killed a second one: the packages/verify/src/harness.ts fixture change (PM mechanism assumption 2), measured dead because walled harness rigs already declare the dev admin as owner and the dev-admin seed already stamps email_verified: true. harness.ts untouched.

    ⇒ A five-day-old card lost half its worklist to measurement and still delivered its substance. ⛔ Neither deletion was taken on the dev's word — the alias is visible in the diff, and harness.ts is absent from the changed-file list.

    PM mechanism assumption 1 — falsified in the useful direction, and it bought a real finding

    I asked whether the design imposes L3-before-L4 and said to stop if it did. The dev read §6 rather than guessing: no order is imposed — L3 and L4 each depend on L2 only. So it proceeded correctly.

    ⚠️ But it surfaced a window the card did not contain: the enterprise organizations package (out of this repo) reuses ensureDefaultOrganization, which still finds the platform admin via grant rows and triggers on grant inserts. A fresh walled rig on that package will not auto-create its default organization between L4 landing and L3's re-point. In-repo paths are unaffected — plugin-auth's bootstrap is gated !postureEnforcesWall(...), measured.

    ⇒ Recorded, not resolved here. It rides with the PR to the contract reviewer, is named in the PR body, and is flagged on #11973, which is the card that owns closing it. ⭐ Note the shape: the reader census the brief demanded (assumption 3) is what found it — a census run to check whether deleting a write breaks a reader found the one reader that lives outside the repo, where no gate could have.

    ⛔ Where this stops — seat boundary, not a judgement about the work

    Path face is clean (no governed surface: nothing in docs/adr/**, .claude/**, skills/**, AGENTS.md, CLAUDE.md), so nothing bars this from the queue except the clause-② gate — and that gate is decisive:

    needs:contract-review is hung and this seat measures claude-opus-5, below CONTRACT_REVIEW_TIER (claude-fable-5). ⇒ ⛔ This seat will not clear the label, flip ready, enqueue, or arm auto-merge. The PR stays a draft awaiting a CONTRACT_REVIEW_TIER seat. That is the designed outcome. CI is kept green in the meantime — parking is about not advancing past review, not about CI.

    For the reviewer who picks it up, the three things worth your attention are: the bootstrap return-contract change (walled_config_derived; already_have_admin becomes single-only), the claimSeedOwnership no-longer-runs-under-walled consequence, and the interim window above. All three are declared in the PR body — ⛔ none of them is buried in the diff.

    ⇒ Card stays pm:dispatched with the PR open. ⛔ Not closed, ⛔ not moved to a queue state — the work is delivered but not landed, and the label that says so honestly is the in-flight one.


    Generated by Claude Code

  10. zhuangjianguo commented on Aug 31, 2026

    @zhuangjianguo
    Collaborator

    ⚖️ 契约复审 PASS — PR #13514(L4)(项目总监席,达档机读 last_served_model = claude-fable-5,维护者召唤「执行复审」)

    审的是契约增量:walled 姿态下 bootstrapPlatformAdmin 停铸 platform-admin grant 行、只读 platformAdmin 审计服务、legacy-grant 弃用指针、replay 收窄(#11663 已接受设计 leg L4,bundle 1A/2B/3A/4A/5A/6A/7A)。

    独立核验(对分支实测,非采信正文):

    1. 设计束逐项相符:2B(不可解析条目整变量 fail-closed,emails.length===0 折叠三态)✓;3A(服务 frozen 无可写成员,注册处 lazy 解引擎)✓;4A(single 首用户晋升与 grant 行逐字节不动,replay 对 single+insert 保留)✓;5A(walled 分支零写,仅报告 + 弃用指针走 reportLegacyPlatformAdminGrant 共享闩)✓。
    2. fail-closed 两半保留:walled_owner_email_undeclared 后备拒绝在(有 legacy 持有者时跳过重复错误行的取舍合理——部署确有管理员在旧锚上);REQUESTED 姿态作输入(降级运行不回退首注册者)照旧 fail-stricter。
    3. replay 收窄论证成立:single 晋升读最老 human、从不读 email/email_verified,[security] 围墙提权只按未验证邮箱匹配 —— #11184 落地后仍存在一条更窄的同形路径:抢在 owner 之前用其邮箱注册即可被提权 #11343 update 臂唯一存在理由随 walled 提权退役而消失;walled 恒不 replay 正确(无写可改答案)。
    4. P5 不撤销 + H4 窗口:legacy 行仍 confer;企业 orgs 包在 fresh walled rig 的空窗如实披露,设计 §6 依赖表不设 L3→L4 次序——有意识接受,归 L3(platform-admin re-anchor L3 (plugin-auth): re-point ensure-default-organization; re-price last-admin-guard as its own reviewed step #11973)。
    5. 落地前检发现并已修一处机械红:check-system-context-census 16 项全系本 PR 行漂(7 个 isSystem 读点 +19/+20,逐对与 merge-base 行内容全同后重锚;--fix 假拒复现 [finding] check-system-context-census --fix reports a POPULATION change when only ledger-excused non-read anchors shifted — a false refusal on a security-documentation gate #13490 的形状,佐证该卡)。修复推 033e01b,门回绿且判词行与基线逐字节同形(109/145/27)。

    一条不阻塞的观察(留给 L 族后续):platform-admin-service.ts 的 tryFind 吞读失败返回 []——审计面在权限库故障时会把管理员报成「not registered」。属 #13279 伪装类的信息面表亲(执法面已由 #13279-A 裁定修复);建议 L5/L6 顺带让 standing() 对读失败如实报「无法判定」,⛔ 不在本 PR 扩范围。

    处置(清标即落地):PR 侧清 needs:contract-review(卡侧未挂),转 ready + 挂 auto-merge(非受管 code PR)。


    Generated by Claude Code

  11. os-steve commented on Aug 31, 2026

    @os-steve
    Collaborator

    Patch-round follow-up (PR #13514, dev session session_016ZC5rNQj3WEet5HAmmAkMs):

    Gate: check-system-context-census under Lint & Repo Gates — 16 problems, all anchor rot in content/docs/permissions/system-context.mdx against security-plugin.ts after the L4 diff (+30/−11) shifted the file.

    The 8 anchor renumbers (page line numbers only; 7 table rows, 9 number substitutions — row 6 cites a pair, row 2 carries a secondary :1565 spelling): 1392→1412, 1414→1434, 1565→1585 (both spellings), 2491→2511, 3808→3827, 4295→4314, 4446→4465, 4524→4543.

    --fix DID refuse — stated plainly, not smoothed: "page anchors 8 distinct read line(s), census finds 7 -- the POPULATION changed". Measured before acting, the refusal's implication (an isSystem elevation read added or removed by L4) is false: git diff origin/main..HEAD -- security-plugin.ts contains zero added or removed lines mentioning isSystem (the +30/−11 is the service registration, one import, and a comment rewrite). The miscount's mechanism, read from the fixer's own code (check-system-context-census.mjs:~790): it excludes ledger-excused anchors by their page line, but the row-2 citation :2491 is a NON-read anchor whose NON_READ_ANCHORS needle already resolves to the shifted line :2511 — so the un-renumbered page anchor miscounted as an 8th read line against 7 census read sites. Pure +20/+19 shift; the renumbers above are exactly what --fix would have written. Gate re-run locally after the renumber: OK — 109 elevation read sites, 145 anchors resolve, 27 declared non-read. If review prefers to treat this as a population change anyway, the .mdx hunk reverts in one commit.

    Attribution note (shared identity): the branch head 033e01b is not this session's push — my equivalent fix (1b6bd2d, atop an origin/main merge) was still local when another session landed 033e01b. Verified byte-level: 033e01b carries the identical 8 security-plugin.ts renumbers (the only mdx differences between the two trees are main-side anchors for other files that arrive with the main merge, which CI's merge reproduces). Nothing further was pushed — a duplicate commit plus merge would only add review noise. Per this seat's contract I am reporting the other actor's write, not correcting it.

    Ledger correction on the derivation-gap question: dispatch-gates.mjs DID derive this gate in round 1 — node scripts/check-system-context-census.mjs was in its output, matched via security-plugin.ts. The gap was this seat's extraction: my grep captured only pnpm check:*-spelled gate lines and silently dropped all 16 node scripts/*.mjs-spelled ones. Not a dispatch-gates defect; no issue filed.

    PR remains draft with needs:contract-review; not flipped, not enqueued, no auto-merge.


    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

domain:servicesRetired 2026-10-22, alias of domain:server (services surface); in-flight cards keep it until landedpm:dispatchedDispatched to a dev agent by /pm-dispatch

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions