You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
governance: objectui is a product-neutral renderer — products compose pages from generic blocks; no product-named widget, dialog, hook or i18n namespace; write it into AGENTS.md + an ADR and ratchet it with a test over the registry, the app-shell dirs and the locale bundles (maintainer ruling 2026-10-12) #12224
Filing gate: a maintainer ruling in chat, 2026-10-12. First 「现在转向」 (cloud's pages stay metadata; objectui ships only product-agnostic blocks; no new cloud:* widgets), then, on where the rule lives: 「规则应该写入 objectui 仓库,要不然每个项目都会有页面定制的需求」. Filed from the cloud maintainer's session. ⛔ Not a claim.
The rule (to be written into this repo, not into any consumer's)
objectui is a product-neutral renderer. A product (cloud, HotCRM, any app) composes its pages from the generic blocks in @objectstack/spec's page vocabulary and keeps its copy in its own bundles.
When a page cannot be composed, the fix is a generic block in objectui (named for what it draws: stat, usage-bar, checklist), or a contract door in @objectstack/spec (needs:contract-review). Never a widget, dialog, hook or i18n namespace named for the product that needed it.
What already exists stays until its page migrates, and may only shrink.
Why
The cloud control plane has accreted into this repo: registered widgets cloud:onboarding-next, cloud:plan-status, cloud:workspace-timezone-notice, cloud:ai-model-status; the packages/app-shell/src/environment/ directory (environment list toolbar, the paywall dialog, the entitlements hook) and packages/app-shell/src/console/organizations/; i18n namespaces cloudOnboarding, cloudPlanStatus, cloudWorkspaceTimezoneNotice, cloudConnection, environment.entitlement, organizations, workspace. Every cloud wording change became an objectui PR plus a pin bump; today a lane waited on cloud for one string (「团队版起」, objectui#12190 / #12197). The next consumer would do the same.
What to do
AGENTS.md: a section "Product-neutral renderer" stating the rule above and the escalation path (generic block here, or a spec door in objectstack). Governed file: a draft PR for the maintainer to merge.
docs/adr/0060-product-neutral-renderer.md (next free number at this write): the ruling, the inventory above as the frozen baseline, and the ratchet below.
Ratchet test (runs in CI with the app-shell suite): an allowlist file (product-specific.allowlist.json or similar) that lists today's product-named registrations, files and i18n namespaces verbatim. The test fails when: a ComponentRegistry.register name carries a product prefix not in the list; a file is added under app-shell/src/environment/, app-shell/src/console/organizations/ or matches console/home/Cloud*.tsx beyond the list; a locale file gains a top-level namespace, or a key under the listed namespaces, that the list does not carry. Removing entries is always allowed; the list is edited only to delete.
PR template: one checkbox, "Adds no product-specific widget, dialog, hook or string (see AGENTS.md › Product-neutral renderer)".
Rider, objectstack (governed .claude/ path, draft PR for the maintainer): one line in .claude/skills/pm-dispatch/references/filing-gate.md — a UI card must say what generic block or spec door it needs; a card asking objectui for a product-named widget is refiled.
Acceptance
AGENTS.md and the ADR merged by the maintainer; the PR template line present.
The ratchet test is green on main and red on each of: a new register('cloud:x'), a new app-shell/src/environment/Foo.tsx, a new key under cloudOnboarding in zh.ts (prove with three throwaway commits, screenshots or CI links on this card).
The allowlist shrinks when objectstack-ai/cloud#2801 retires cloud:onboarding-next and cloud:plan-status, and when objectstack-ai/cloud#2774 migrates the environment and organization pages.
Related
objectui#12197 (generic blocks) · objectstack-ai/objectstack#23016 (api element data source) · objectstack-ai/cloud#2772 · objectstack-ai/cloud#2777 (v1 on existing metadata) · objectstack-ai/cloud#2801 (v2) · objectstack-ai/cloud#2774 · objectui#2763 (approvals rebuilt on the standard renderer, the precedent)
Triage seat (seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-12T11:55Z. ⛔ Not a claim, ⛔ not a dispatch. Grade completed: domain:skills and area:devpath added. The maintainer's enhancement · priority:p1 · pm:queue stand.
Lane:AGENTS.md and docs/adr/** are the governed surface, so domain:skills takes it. The whole diff is judged at Tier H, including the ratchet test and the PR template: a draft PR, the maintainer's quick-read, and no queue before an authorised approval.
The ratchet is the maintainer's direction, so the new-gate default (no) does not apply here.
Claim: PM loop round 2 (#12224 — the product-neutral renderer rule, its ADR and its ratchet; Tier H) · 2026-10-12T12:33Z
Session: session_012dGTuJen61ECNHXYXKChoC
Account: os-justin (the seat's linked user as GET /user answers it; always the card's assignee)
Branch: claude/issue-12224-product-neutral-renderer (objectui) · claude/issue-12224-objectui-filing-gate-rider (objectstack, the card's rider item 5)
Worktree: objectui-issue-12224 · objectstack-issue-12224-rider
Domain: domain:skills
Seat: domain:skills#2
File surface: objectui — AGENTS.md (one new "Product-neutral renderer" section; nothing else in the file), docs/adr/0060-product-neutral-renderer.md (new; 0059 is the last ADR on origin/main21fdeb34d4, re-read at PR open), one new allowlist file and one new ratchet test under packages/app-shell/ (placement is the dev's), the test-input ledger rows objectui's own scripts/__tests__/*-inputs.test.ts gates demand for a test that reads packages/i18n/src/locales/, a new .github/pull_request_template.md (none exists today), one empty-frontmatter changeset; objectstack — one line in .claude/skills/pm-dispatch/references/filing-gate.md (stop on breach; explain in the report)
Container & model: M, mode:subagent, model: opus — the default judgment tier; dispatch-gates --tier --repo objectstack-ai/objectstack on the rider path at 9f4b652e3a printed 「Model tier — no path-derived mandate」 (floor sonnet · default opus · ceiling fable); the objectui paths are outside that tool's repo and outside the protocol-semantic surface, and the ratchet's design carries judgment, so the default tier, not the floor
Clause-②: no
Responsibility: n/a — not a defect card (a maintainer-directed governance card)
Thread-read: 6123756892
Ruling-ref: the maintainer's chat ruling quoted verbatim in the card body (「现在转向」; 「规则应该写入 objectui 仓库,要不然每个项目都会有页面定制的需求」), and triage's grade 6123756892 (the ratchet is the maintainer's direction; the whole diff is Tier H; the baseline is read at the PR's own head).
Resume-from: none
Serial constraints cleared: objectui open PRs — 8, with 156 changed files read: none touches AGENTS.md, docs/adr/**, a PR template, app-shell/src/environment/, console/organizations/, console/home/Cloud* or i18n/src/locales/. objectui in-flight claims — 8 pm:dispatched cards read; one hit, objectui#7611 (epic #15194, marchtian), which declares locale entries in packages/i18n/src/locales/. That is text-disjoint, because this card edits no locale file. The coupling is semantic: the ratchet's baseline is read at this PR's head, so what #7611 lands first enters the baseline, and what lands after must pass the ratchet, with no wave-through (triage 6123756892). objectui#12190 is closed. objectstack — no open PR touches filing-gate.md.
Delivery shape: objectui PR Fixes #12224, Tier H (draft until an authorized approval). The objectstack rider PR names objectstack-ai/objectui#12224 with no closing keyword; it is Tier S (.claude/**).
{
"issue": 12224,
"status": "blocked",
"branch": "claude/issue-12224-product-neutral-renderer",
"pr": "https://github.com/objectstack-ai/objectui/pull/12253",
"session": "session_012dGTuJen61ECNHXYXKChoC — subagent run; the parent PM session's id, as the Claude-Session trailer on both commits spells it",
"premise_still_valid": true,
"summary": "The objectui half is complete. Draft PR objectstack-ai/objectui#12253 (head 27c30c10, assignee os-justin; its body opens with the closing line for this card, then Clause-② no) adds: an AGENTS.md section 'Product-neutral renderer' in §1 (608→618 lines, no issue numbers); docs/adr/0060-product-neutral-renderer.md (0060 re-read free at origin/main 923504f4a); the ratchet packages/app-shell/src/__tests__/product-neutral-renderer.ratchet.test.ts (32 tests, unit project) with its live list product-specific.allowlist.json; two scripts/markdown-test-inputs.mjs ledger rows; .github/pull_request_template.md with the one checkbox; and an empty-frontmatter changeset. The ratchet reads registry keys through the repo's one registration derivation (deriveRegistryKeys), so both spellings are covered (H1 confirmed). It also reads non-test file paths and the ten locale catalogues. Two mechanisms carry the rules. First, the live list must equal the measurement exactly, so a stale entry is red and the list has to shrink. Second, every live entry must sit inside a ceiling block in ADR-0060, a governed file; that makes the card's edit-only-to-delete rule mechanical (M5 proof). The frozen baseline was measured, not copied, and holds 8 registrations, 28 files and 90 keys under 9 namespaces. It exceeds the card's inventory: cloud-connection:panel with its app-shell twins, console/cloud-connection/, console/diagnostics/CloudAiModelStatus.tsx, types' cloud.ts and zod/cloud.zod.ts, planTier, aiModelStatus, and the whole environment namespace. H3's literal reading contradicts rule 2, so a reading consistent with rule 2 was taken and recorded in ADR-0060 and in the PR's 速读. The rider half is BLOCKED. filing-gate.md sits at 58 lines against a check-skill-line-ratchet ceiling of 58 (headroom 0), and the drafted line makes it 59, measured red. The dispatch allowed one line with stop-on-breach, so no objectstack PR was opened and no label was written; branch claude/issue-12224-objectui-filing-gate-rider is pushed empty. The PM decision needed is in open_questions.",
"tests": "objectui at 27c30c10, each run through os-verify-lock, exit captured before any pipe. (1) pnpm exec vitest run --maxWorkers=2 scripts/__tests__/ packages/app-shell/src/__tests__/product-neutral-renderer.ratchet.test.ts → exit 0, 'Test Files 182 passed | 2 skipped (184)', 'Tests 5573 passed | 2 skipped (5575)'. An earlier run at 5298f952 was red, 1 failed: markdown-test-inputs 'EVERY tracked markdown document is an input' named .github/pull_request_template.md. 27c30c10 adds the ledger row. (2) pnpm exec vitest run --project unit --maxWorkers=2 packages/app-shell/ → exit 0, 'Test Files 277 passed | 1 skipped (278)', 'Tests 3839 passed | 9 skipped (3848)'. (3) turbo run build --filter='@object-ui/app-shell^...' --concurrency=2 → 28/28; then pnpm --filter @object-ui/app-shell type-check → exit 0, echoed '> @object-ui/app-shell@17.7.0 type-check' / 'tsc --noEmit && tsc -p tsconfig.test.json'; tsc --listFilesOnly lists the new test among 5366 files. (4) eslint --format json on the two lintable changed files → 1+1 files, 0 errors, 0 warnings; eslint.config.js has no parserOptions.project/projectService, so no untouched file's verdict can move. Mutation proofs: implementation committed first (5298f952); each mutation went through objectstack scripts/ablation-replace.mjs in WRAP mode (anchor must hit, blob change verified, restore proven by blob == HEAD and git diff HEAD empty), and M3 used a bash trap; git status --porcelain was empty after every leg, and nothing was committed or pushed. M1, a literal register('cloud:mutation-probe') in InstalledListWidget.tsx → '1 failed | 31 passed', 'no registry key leads with a product word…' naming cloud:mutation-probe. M2, register('mutation-probe', …, { namespace: 'cloud', skipFallback: true }) → the same red, same key. M3, a new packages/app-shell/src/environment/Foo.tsx → red 'no file is added under a frozen directory…' naming it. M4, a new cloudOnboarding.mutationProbe in zh.ts only → red 'zh: no key is added under a frozen namespace…'. M5, M1 plus the key appended to the live allowlist → the registration assertion passes and the ceiling assertion turns red ('registration cloud:mutation-probe'). The first M1 and M4 attempts used a replacement that contained the anchor; the tool refused them (anchor count 1 -> 1), so they were no-ops and not readings, and both were re-run with split anchors. Rider probe on objectstack@9f4b652e3 (ablation-replace WRAP, restored): check-skill-line-ratchet '✗ … filing-gate.md is 59 lines; the ratchet ceiling is 58' (exit 1); check:pm-skill-id-lint '87 file(s) clean' (exit 0). CI on PR #12253 at report time: 12 check runs completed with 0 failures, 20 in_progress.",
"mcp_calls": "0",
"api_writes": "2 relay dispatches, each POST /repos/objectstack-ai/objectstack/dispatches executed by fleet-write as objectstack-fleet[bot]. #1 pr_create: POST /repos/objectstack-ai/objectui/pulls (draft) + POST /repos/objectstack-ai/objectui/issues/12253/assignees; read back 18279 bytes sent, 18279 stored, identical. #2 comment: POST /repos/objectstack-ai/objectui/issues/12224/comments (this report). Pushes, which are git and not REST: objectui branch ×3, objectstack rider branch ×1 (empty probe push). Unused budget: objectstack pr_create and label-write (skip-changeset), because the rider is blocked.",
"gates": {
"objectui@27c30c10": [
"vitest scripts/__tests__/ + ratchet · exit 0 · Test Files 182 passed | 2 skipped (184)",
"vitest --project unit packages/app-shell/ · exit 0 · Test Files 277 passed | 1 skipped (278)",
"pnpm --filter @object-ui/app-shell type-check · exit 0 · tsc --noEmit && tsc -p tsconfig.test.json",
"eslint (2 changed lintable files) · exit 0 · 0 errors 0 warnings",
"node scripts/check-governed-queue-guard.mjs --test (7 paths) · exit 3 · ⛔ GOVERNED — 2 of 7 path(s) (docs/adr/**, AGENTS.md); expected",
"node scripts/check-changeset-presence.mjs · exit 0 · ✅ … declares 1 changeset(s) … EMPTY frontmatter",
"node scripts/check-changeset-no-major.mjs · exit 0",
"node scripts/check-changeset-claims.mjs · exit 0",
"node scripts/check-new-cross-file-line-citations.mjs · exit 0 · VERDICT … 0 new citation(s)",
"node scripts/check-control-bytes.mjs · exit 0 · OK (8511 files)",
"node scripts/check-test-path-roots.mjs · exit 0",
"node scripts/check-doc-links.mjs · exit 0 · Links are valid across 17 scan roots",
"node scripts/check-lint-coverage.mjs · exit 0 · 46/46",
"node scripts/markdown-test-inputs.mjs --audit · exit 0 · 123 candidates adjudicated; 87 entries present",
"node scripts/check-unreferenced-sources.mjs · exit 0",
"node scripts/check-published-tsconfig-tooling-exclude.mjs · exit 0",
"node scripts/check-doc-component-types.mjs · exit 0",
"control-byte self-scan (grep -naP) on the 7 changed files · exit 1 = none",
"NOT RUN, declared to CI: app-shell dom/dom-heavy projects, pnpm lint (repo-wide), pnpm check (CLI self-check), Test shard matrix"
],
"objectstack@9f4b652e3 (rider, nothing committed)": [
"node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack · exit 2 · 'this branch changes nothing against origin/main — nothing to derive'",
"same, with the hypothetical path filing-gate.md · exit 0 · 17 commands, incl. pnpm check:pm-skill-ratchet, check:pm-skill-id-lint, check:nul-bytes",
"rider probe: check-skill-line-ratchet · exit 1 · filing-gate.md is 59 lines; the ratchet ceiling is 58",
"rider probe: pnpm check:pm-skill-id-lint · exit 0",
"base: check-skill-line-ratchet · exit 0 · filing-gate.md is 58 lines (ceiling 58; headroom 0)"
]
},
"line_budget": {
"objectui AGENTS.md": "608 → 618 (+10; the dispatch asked ≤ +20)",
"objectstack filing-gate.md": "58 → 58, unchanged; with the drafted rider line it would be 59 against ceiling 58"
},
"files_changed": {
"objectui": [
"AGENTS.md",
"docs/adr/0060-product-neutral-renderer.md",
"packages/app-shell/src/__tests__/product-neutral-renderer.ratchet.test.ts",
"packages/app-shell/src/__tests__/product-specific.allowlist.json",
"scripts/markdown-test-inputs.mjs",
".github/pull_request_template.md",
".changeset/12224-product-neutral-renderer.md"
],
"objectstack": []
},
"deviations": [
"Route, PM suggestion bettered. Besides the live allowlist, the ratchet reads a ceiling and its rules (product words, frozen directories, frozen namespaces) from a fenced json block at the end of ADR-0060. Every live entry must be inside it, so a new product entry needs a governed ADR amendment, and appending to the allowlist alone stays red (M5). The cost is a markdown read, which is declared in markdown-test-inputs.",
"H1. The ratchet uses the repo's static registration derivation (deriveRegistryKeys, repo-wide, both spellings, fails closed on an unrecognised options shape) instead of a runtime enumeration after app-shell registers. A runtime enumeration would see only app-shell's import closure, while a product registration in any package must turn the ratchet red. A synthetic-tree control in the test pins both spellings.",
"H2. The frozen directories are recursive, so organizations/manage/ counts. Test paths (__tests__, __mocks__, __fixtures__, __benchmarks__, test, tests, e2e, and *.test/spec/stories) are outside the file half. Product-named files are matched repo-wide, a generalisation of the card's console/home/Cloud*.tsx.",
"H3. A product-led namespace or key at any depth is refused unless frozen. Frozen namespaces take no new key in any locale. A neutral new namespace passes. This is recorded in ADR-0060 and put to the maintainer in the 速读.",
"Frozen i18n set beyond the card: the whole environment namespace (every consumer sits in the frozen dir), planTier, and aiModelStatus. organization (singular), chatbotQuota, marketplace and connectAgent were considered and not frozen, with reasons in the ADR.",
"A second ledger row went into scripts/markdown-test-inputs.mjs for check-installed-spec-pin-claims.test.ts, which reads every tracked file and so reads the new PR template. The ledger is pinned total over tracked markdown. This sits inside the claim's declared ledger surface.",
"Rider not delivered: zero line-ratchet headroom plus the one-line, stop-on-breach surface. See open_questions.",
"Commit trailers use the repos' model-free pair (Claude-Session + Co-authored-by: Claude) instead of the harness reminder's model-named Co-Authored-By. AGENTS.md takes precedence.",
"The full root pnpm test was not run locally. Run instead: all of scripts/__tests__, the ratchet, and app-shell's unit project. The dom/dom-heavy projects and the shard matrix are declared to CI; this diff changes no source that those projects import."
],
"open_questions": [
{
"question": "How should the one rider line in .claude/skills/pm-dispatch/references/filing-gate.md be paid for? The file is at its line-ratchet ceiling (58/58). The drafted line is '- UI 卡写明所需通用块或 spec 契约门;要产品命名 widget/dialog/hook/命名空间的卡退回重立。' (116 bytes, id-lint green).",
"options": [
"A. Pay by deleting content in the same file. Candidate: the intro's self-description clause '本文是「什么才算一张卡」与定级、读数三组判据的执行说明', which the three headings already state. That turns the two-line intro into one, keeps the file at 58, and leaves the ceiling where it is. Cost: it touches a second line, beyond the dispatch's one-line surface. Effort: one small re-dispatch.",
"B. A maintainer ruling raises the ceiling 58 → 59, quoted in the rider PR. Cost: maintainer attention and corpus growth.",
"C. The dispatch names this a measurement-first zero-headroom ledger: land the line red and leave the ceiling line alone. Cost: a red Lint & Repo Gates context on a Tier S PR until a ruling."
],
"recommendation": "A. The ratchet's own discipline says a new line is paid for by deleting content, the clause restates the headings, and no ceiling moves."
}
],
"out_of_scope_findings": [
"carrier: the maintainer, on objectstack-ai/objectui#12253 (ADR-0060 review) · noted, not filed. Product copy that this reading leaves unfrozen: organization (singular, 116 keys, also read by layout and @object-ui/auth) and chatbotQuota (plugin-chatbot quota/credit copy). Freezing either is an ADR-0060 amendment."
]
}
PM answer to the os-dev report's open question (6125187793) · seat domain:skills#2 · session_012dGTuJen61ECNHXYXKChoC · 2026-10-12T13:26Z
Answer: A. The rider line in objectstack's .claude/skills/pm-dispatch/references/filing-gate.md is paid for by deleting the intro's self-description clause, "本文是「什么才算一张卡」与定级、读数三组判据的执行说明". The clause restates the file's three headings (## 立卡门, ## 定级判据…, ## 读数判据…), so its content keeps a home there. It is a description, not a rule, so no rule is lost. The freed line comes from deleting content, not from re-wrapping, and the ratchet ceiling (58) does not move. B (raising the ceiling) and C (landing red) are not taken.
This is a bookkeeping answer, not an escalation: it is a line-ratchet payment inside a lane's own text, with no product-visible change.
Claim file surface, amended in this act: the objectstack rider now covers filing-gate.md lines 3–4 (the intro, reduced to its pointer sentence) plus the one new line under ## 立卡门. Nothing else in that file changes. The same dev resumes the rider half on claude/issue-12224-objectui-filing-gate-rider.
{
"issue": 12224,
"status": "done",
"branch": "claude/issue-12224-objectui-filing-gate-rider",
"pr": "https://github.com/objectstack-ai/objectstack/pull/23051",
"session": "session_012dGTuJen61ECNHXYXKChoC — subagent run; the parent PM session's id, as the Claude-Session trailer on the rider commit spells it",
"premise_still_valid": true,
"summary": "Rider half only; the objectui PR objectstack-ai/objectui#12253 is untouched. Following PM answer A (comment 6125224340), one commit on claude/issue-12224-objectui-filing-gate-rider (6b43997f7, fast-forwarded from the empty 9f4b652e3 to origin/main 38d98d8d8 first) edits objectstack .claude/skills/pm-dispatch/references/filing-gate.md and nothing else. It deletes the intro's self-description clause 「本文是「什么才算一张卡」与定级、读数三组判据的执行说明」, which restates the three headings, so the intro becomes its pointer sentence on one line. It adds under ## 立卡门 the line 「- UI 卡写明所需通用块或 spec 契约门;要产品命名 widget/dialog/hook/命名空间的卡退回重立。」. The file stays at 58 lines against an unchanged ceiling of 58, with no re-wrap and no other line touched. Draft PR objectstack-ai/objectstack#23051 has assignee os-justin, the given title, and a body that names objectstack-ai/objectui#12224 and objectstack-ai/objectui#12253 with no closing keyword, a 维护者速读 section (席位意见 left blank) and Acceptance notes naming the deleted clause and the added line. It carries skip-changeset, written through label-write.mjs and read back. Body read back identical, 6258 bytes sent and 6258 stored.",
"tests": "At 6b43997f7, derivation: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths) → 17 commands; change set filing-gate.md, +2/-2. Every command ran with its exit code captured to disk first; --ran reconciliation: '17 derived, 17 run, 0 NOT-MEASURED, 0 UNRUN (a DERIVED zero — all 17 recorded an exit code and none of them is 3)'. Key verdicts: pnpm check:pm-skill-ratchet exit 0 '✓ … filing-gate.md is 58 lines (ceiling 58; headroom 0)'; pnpm check:pm-skill-id-lint exit 0 '87 file(s) clean'; pnpm check:nul-bytes exit 0 'OK (scanned 11047 text file(s) … no raw ASCII control bytes)'. The remaining 14 also exited 0: closing-keyword-parity and its self-test, comment-mask-corpus, check-harness-current --self-test, agent-test-spelling, cross-package-test-inputs, doc-authoring, driver-memory-census, gitlink-declared, pm-governed-merges, refd-timer-probe, skill-frame-sync, watch-hint-literal, and doc-formula-expressions. doc-formula-expressions first exited 3 with PREREQUISITE NOT MET (formula and lint not built), which measured nothing; after turbo run build --filter=@objectstack/formula --filter=@objectstack/lint (4/4, under os-verify-lock) the re-run exited 0. CI on #23051 at report time: 23 check runs completed with 0 failures, 13 in_progress.",
"mcp_calls": "0",
"api_writes": "3 relay dispatches (POST /repos/objectstack-ai/objectstack/dispatches, executed as objectstack-fleet[bot]). (1) pr_create: POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos/objectstack-ai/objectstack/issues/23051/assignees. (2) label-write labels_add: POST /repos/objectstack-ai/objectstack/issues/23051/labels; read back: documentation, size/xs, skip-changeset. (3) this comment: POST /repos/objectstack-ai/objectui/issues/12224/comments. Git pushes: rider branch ×2 (fast-forward to main, then the commit).",
"line_budget": { "objectstack filing-gate.md": "58 → 58 (ceiling 58, unchanged; −1 content line from the intro, +1 rule line)" },
"files_changed": { "objectstack": [".claude/skills/pm-dispatch/references/filing-gate.md"] },
"deviations": [
"The rider branch already existed as an empty push at 9f4b652e3. The worktree was re-attached to it and fast-forwarded to origin/main (38d98d8d8) before editing, so no force-push was needed. 'Built from current origin/main' holds.",
"The objectstack PR body opens with 'Clause-②: no' at line start, copied from the claim per os-dev.",
"The worktree was removed after the reports, with a clean tree and the head equal to the origin branch."
],
"open_questions": [],
"out_of_scope_findings": []
}
Diff: one file, .claude/skills/pm-dispatch/references/filing-gate.md, +2/−2. It is exactly the PM's answer A (6125224340):
the intro's self-description clause is deleted, and its content survives in the file's three headings;
one rule line is added under ## 立卡门.
The file stays at 58 lines against a ceiling of 58, and the ceiling does not move.
CI on this head: 38 check-runs completed: 26 success, 12 skipped by the paths filter, 0 red. The required Lint & Repo Gates, TypeScript Type Check, Test Core and Governed Surface Queue Guard are all success.
Contract review: PASS at CONTRACT_REVIEW_TIER on this head, record 6134365672 on the PR.
Landing: Tier S (check-governed-merges --pr 23051). This seat lands it now through the queue.
The objectui half (PR #12253, Tier H) is still under contract review. This card closes when that PR merges.
The at-tier contract review 6134399082 reads PASS on this head. The seat holds the ACCEPT for one item that review raised (its item 5). ADR-0060's "Consequences" bullet says every pull request's description carries the template's checkbox. That is false: GitHub prefills the template only for PRs opened in the web form, and every fleet PR, this one included, is opened through the API. Nothing enforces the checkbox. A governed record must not state a guarantee nothing delivers.
Patch round sent to the same dev on the same claim: narrow that bullet, and line 71's mention if it overclaims the same way. Nothing else in the PR changes. The review's other items are design calls for the maintainer: the H3 locale reading, the freeze scope beyond the card, the ceiling living in the governed ADR, the organizations/workspace vs organization/chatbotQuota split, and the two product words. They go to the maintainer in the final quick-read after the patched head's contract review.
{
"issue": 12224,
"status": "done",
"branch": "claude/issue-12224-product-neutral-renderer",
"pr": "https://github.com/objectstack-ai/objectui/pull/12253",
"session": "session_012dGTuJen61ECNHXYXKChoC — subagent run; the parent PM session's id, as the Claude-Session trailer on the rework commit spells it",
"premise_still_valid": true,
"rework": "patch round 1, contract review 6134399082 item 5 (① 11)",
"head": "5fed8ccc (full 5fed8ccc on claude/issue-12224-product-neutral-renderer, parent 27c30c10ae); no merge of origin/main, since the PR read mergeable/clean",
"summary": "Two sentences changed in docs/adr/0060-product-neutral-renderer.md; no other file changed. The Consequences bullet no longer claims every pull request carries the template's checkbox. Line 71 claimed the checkbox 'catches' the rest, the same overclaim, so it was narrowed in the same commit. The frozen-baseline section is byte-identical: sha256 of everything from '## Frozen baseline' to EOF was a7fb7087… before the edit and is the same after. AGENTS.md's sentence ('left to review and the pull-request template's checkbox') was left alone, because the patch scope said nothing else changes. The review's ① 11 also names it; it is the maintainer's call. The PR body was not edited.",
"changed_sentences": [
{
"where": "ADR-0060, The ratchet › What the ratchet cannot see, first bullet (line 71)",
"before": "are all it reads; the pull-request template's checkbox and review catch the rest;",
"after": "are all it reads; the rest is left to review, which the template's checkbox prompts only on web-form PRs;"
},
{
"where": "ADR-0060, Consequences, third bullet (lines 162–163)",
"before": "- Every pull request's description carries the template's checkbox: \"Adds no product-specific widget, dialog, hook or string\".",
"after": "- A pull request opened through the web form starts with the template's checkbox; one opened through the API, as the fleet's are, does not. The checkbox prompts human authors; it is not a gate."
}
],
"tests": "At 5fed8ccc, run from the repo root through os-verify-lock, with exit codes written to disk first. pnpm exec vitest run scripts/__tests__/markdown-test-inputs.test.ts → exit 0, 'Test Files 1 passed (1)' 'Tests 25 passed (25)'. pnpm exec vitest run packages/app-shell/src/__tests__/product-neutral-renderer.ratchet.test.ts → exit 0, 'Test Files 1 passed (1)' 'Tests 32 passed (32)'. Also: node scripts/check-new-cross-file-line-citations.mjs exit 0, '0 new citation(s)'; node scripts/check-doc-links.mjs exit 0.",
"mcp_calls": "0",
"api_writes": "1 relay dispatch: POST /repos/objectstack-ai/objectstack/dispatches executing POST /repos/objectstack-ai/objectui/issues/12224/comments (this comment). Git push ×1 (27c30c10..5fed8ccc).",
"open_questions": [],
"out_of_scope_findings": []
}
Checked against GitHub and objectui origin/main, not the reports (6125187793, rework 6134447475):
Shape: draft, base main, first line Fixes #12224, Clause-②: no, assignee os-justin. Empty-frontmatter changeset; objectui carries no skip-changeset. Seven files: AGENTS.md (+10, one new section), docs/adr/0060-product-neutral-renderer.md (new), the ratchet test and its live allowlist under packages/app-shell/src/__tests__/, two markdown-test-inputs ledger rows, .github/pull_request_template.md (new, one checkbox), and the changeset.
Content read by the seat:
The ratchet reads registrations through the repo's one derivation, so both spellings count, namespace: 'cloud' included.
The live list must equal the measurement, and must sit inside the ceiling block in the governed ADR. That makes "the list only shrinks" enforced, not declared.
The baseline is measured, not copied: 8 registrations, 28 files, 90 keys under 9 namespaces.
The H3 locale reading, which replaces the card's literal clause, is recorded in the ADR.
REWORK round 1 (6134419284): the ADR's checkbox guarantee is narrowed to what is true (web-form PRs only, not a gate). Delta is two sentences; the frozen-baseline block is byte-identical.
CI on this head: 33 check-runs, none red: 30 success, 3 path-skipped.
Contract review: PASS at CONTRACT_REVIEW_TIER on this head, record 6134585175 (previous head 6134399082, PASS). The record lists six design calls for the maintainer; they ride with the approval and are restated in the final quick-read on the PR.
Landing: Tier H (AGENTS.md, docs/adr/**). The PR stays draft; needs-user-decision on the PR; review requested from os-zhuang and hotlong. After an authorized APPROVED review this seat lands it.
Rider landed — objectstack PR objectstack-ai/objectstack#23051MERGED as dc08c609a (this seat's relay stroke, enqueued 2026-10-12T23:13Z, merged by the queue) · seat domain:skills#2 · session_012dGTuJen61ECNHXYXKChoC · 2026-10-12T23:39Z
Read on objectstack origin/main: filing-gate.md carries the rider line under ## 立卡门 (1 hit) and stays at 58 lines. This card stays open, pm:dispatched, for its objectui half: PR #12253 awaits an authorized approval (速读 6134603082). It closes when that PR merges.
Landed — objectui PR #12253MERGED as f228d710 (merged by os-zhuang through the queue: APPROVED review 5497622223 on f3369125bd, flipped ready, auto-merge, enqueued) · seat domain:skills#2 · session_012dGTuJen61ECNHXYXKChoC · 2026-10-13T01:24Z
The approved head is the reviewed content.f3369125bd is 5fed8ccc46 plus one merge of main by the approver. The PR's net diff against its merge base is byte-identical to the diff contract-reviewed at 5fed8ccc46 (record 6134585175), and none of the PR's seven files changed in the merge. CI on f3369125bd: 30 success, 3 skipped, plus one queue-guard run cancelled and superseded by a passing one. That includes the product-neutral ratchet against 24 newer main commits.
Content read on objectui origin/main after the merge:docs/adr/0060-product-neutral-renderer.md, the AGENTS.md "Product-neutral renderer" section, packages/app-shell/src/__tests__/product-neutral-renderer.ratchet.test.ts and .github/pull_request_template.md are all present.
Activity
objectstack-fleet commentedon Oct 12, 2026
Triage seat (seat post objectstack-ai/objectstack#6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-12T11:55Z. ⛔ Not a claim, ⛔ not a dispatch. Grade completed:domain:skillsandarea:devpathadded. The maintainer'senhancement·priority:p1·pm:queuestand.AGENTS.mdanddocs/adr/**are the governed surface, sodomain:skillstakes it. The whole diff is judged at Tier H, including the ratchet test and the PR template: a draft PR, the maintainer's quick-read, and no queue before an authorised approval.app-shell/src/environment/) lands first and enters the baseline, or rebases under the ratchet. ⛔ It is not waved through after.objectstack-fleet commentedon Oct 12, 2026
Claim: PM loop round 2 (#12224 — the product-neutral renderer rule, its ADR and its ratchet; Tier H) · 2026-10-12T12:33Z
Session:
session_012dGTuJen61ECNHXYXKChoCAccount:
os-justin(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-12224-product-neutral-renderer(objectui) ·claude/issue-12224-objectui-filing-gate-rider(objectstack, the card's rider item 5)Worktree:
objectui-issue-12224·objectstack-issue-12224-riderDomain:
domain:skillsSeat:
domain:skills#2File surface: objectui —
AGENTS.md(one new "Product-neutral renderer" section; nothing else in the file),docs/adr/0060-product-neutral-renderer.md(new; 0059 is the last ADR onorigin/main21fdeb34d4, re-read at PR open), one new allowlist file and one new ratchet test underpackages/app-shell/(placement is the dev's), the test-input ledger rows objectui's ownscripts/__tests__/*-inputs.test.tsgates demand for a test that readspackages/i18n/src/locales/, a new.github/pull_request_template.md(none exists today), one empty-frontmatter changeset; objectstack — one line in.claude/skills/pm-dispatch/references/filing-gate.md(stop on breach; explain in the report)Container & model:
M,mode:subagent,model: opus— the default judgment tier;dispatch-gates --tier --repo objectstack-ai/objectstackon the rider path at9f4b652e3aprinted 「Model tier — no path-derived mandate」 (floor sonnet · default opus · ceiling fable); the objectui paths are outside that tool's repo and outside the protocol-semantic surface, and the ratchet's design carries judgment, so the default tier, not the floorClause-②: no
Responsibility:
n/a — not a defect card(a maintainer-directed governance card)Thread-read: 6123756892
Ruling-ref: the maintainer's chat ruling quoted verbatim in the card body (「现在转向」; 「规则应该写入 objectui 仓库,要不然每个项目都会有页面定制的需求」), and triage's grade 6123756892 (the ratchet is the maintainer's direction; the whole diff is Tier H; the baseline is read at the PR's own head).
Resume-from: none
Serial constraints cleared: objectui open PRs — 8, with 156 changed files read: none touches
AGENTS.md,docs/adr/**, a PR template,app-shell/src/environment/,console/organizations/,console/home/Cloud*ori18n/src/locales/. objectui in-flight claims — 8pm:dispatchedcards read; one hit, objectui#7611 (epic#15194,marchtian), which declares locale entries inpackages/i18n/src/locales/. That is text-disjoint, because this card edits no locale file. The coupling is semantic: the ratchet's baseline is read at this PR's head, so what #7611 lands first enters the baseline, and what lands after must pass the ratchet, with no wave-through (triage 6123756892). objectui#12190 is closed. objectstack — no open PR touchesfiling-gate.md.Delivery shape: objectui PR
Fixes #12224, Tier H (draft until an authorized approval). The objectstack rider PR namesobjectstack-ai/objectui#12224with no closing keyword; it is Tier S (.claude/**).Generated by Claude Code
objectstack-fleet commentedon Oct 12, 2026
os-dev-report
{ "issue": 12224, "status": "blocked", "branch": "claude/issue-12224-product-neutral-renderer", "pr": "https://github.com/objectstack-ai/objectui/pull/12253", "session": "session_012dGTuJen61ECNHXYXKChoC — subagent run; the parent PM session's id, as the Claude-Session trailer on both commits spells it", "premise_still_valid": true, "summary": "The objectui half is complete. Draft PR objectstack-ai/objectui#12253 (head 27c30c10, assignee os-justin; its body opens with the closing line for this card, then Clause-② no) adds: an AGENTS.md section 'Product-neutral renderer' in §1 (608→618 lines, no issue numbers); docs/adr/0060-product-neutral-renderer.md (0060 re-read free at origin/main 923504f4a); the ratchet packages/app-shell/src/__tests__/product-neutral-renderer.ratchet.test.ts (32 tests, unit project) with its live list product-specific.allowlist.json; two scripts/markdown-test-inputs.mjs ledger rows; .github/pull_request_template.md with the one checkbox; and an empty-frontmatter changeset. The ratchet reads registry keys through the repo's one registration derivation (deriveRegistryKeys), so both spellings are covered (H1 confirmed). It also reads non-test file paths and the ten locale catalogues. Two mechanisms carry the rules. First, the live list must equal the measurement exactly, so a stale entry is red and the list has to shrink. Second, every live entry must sit inside a ceiling block in ADR-0060, a governed file; that makes the card's edit-only-to-delete rule mechanical (M5 proof). The frozen baseline was measured, not copied, and holds 8 registrations, 28 files and 90 keys under 9 namespaces. It exceeds the card's inventory: cloud-connection:panel with its app-shell twins, console/cloud-connection/, console/diagnostics/CloudAiModelStatus.tsx, types' cloud.ts and zod/cloud.zod.ts, planTier, aiModelStatus, and the whole environment namespace. H3's literal reading contradicts rule 2, so a reading consistent with rule 2 was taken and recorded in ADR-0060 and in the PR's 速读. The rider half is BLOCKED. filing-gate.md sits at 58 lines against a check-skill-line-ratchet ceiling of 58 (headroom 0), and the drafted line makes it 59, measured red. The dispatch allowed one line with stop-on-breach, so no objectstack PR was opened and no label was written; branch claude/issue-12224-objectui-filing-gate-rider is pushed empty. The PM decision needed is in open_questions.", "tests": "objectui at 27c30c10, each run through os-verify-lock, exit captured before any pipe. (1) pnpm exec vitest run --maxWorkers=2 scripts/__tests__/ packages/app-shell/src/__tests__/product-neutral-renderer.ratchet.test.ts → exit 0, 'Test Files 182 passed | 2 skipped (184)', 'Tests 5573 passed | 2 skipped (5575)'. An earlier run at 5298f952 was red, 1 failed: markdown-test-inputs 'EVERY tracked markdown document is an input' named .github/pull_request_template.md. 27c30c10 adds the ledger row. (2) pnpm exec vitest run --project unit --maxWorkers=2 packages/app-shell/ → exit 0, 'Test Files 277 passed | 1 skipped (278)', 'Tests 3839 passed | 9 skipped (3848)'. (3) turbo run build --filter='@object-ui/app-shell^...' --concurrency=2 → 28/28; then pnpm --filter @object-ui/app-shell type-check → exit 0, echoed '> @object-ui/app-shell@17.7.0 type-check' / 'tsc --noEmit && tsc -p tsconfig.test.json'; tsc --listFilesOnly lists the new test among 5366 files. (4) eslint --format json on the two lintable changed files → 1+1 files, 0 errors, 0 warnings; eslint.config.js has no parserOptions.project/projectService, so no untouched file's verdict can move. Mutation proofs: implementation committed first (5298f952); each mutation went through objectstack scripts/ablation-replace.mjs in WRAP mode (anchor must hit, blob change verified, restore proven by blob == HEAD and git diff HEAD empty), and M3 used a bash trap; git status --porcelain was empty after every leg, and nothing was committed or pushed. M1, a literal register('cloud:mutation-probe') in InstalledListWidget.tsx → '1 failed | 31 passed', 'no registry key leads with a product word…' naming cloud:mutation-probe. M2, register('mutation-probe', …, { namespace: 'cloud', skipFallback: true }) → the same red, same key. M3, a new packages/app-shell/src/environment/Foo.tsx → red 'no file is added under a frozen directory…' naming it. M4, a new cloudOnboarding.mutationProbe in zh.ts only → red 'zh: no key is added under a frozen namespace…'. M5, M1 plus the key appended to the live allowlist → the registration assertion passes and the ceiling assertion turns red ('registration cloud:mutation-probe'). The first M1 and M4 attempts used a replacement that contained the anchor; the tool refused them (anchor count 1 -> 1), so they were no-ops and not readings, and both were re-run with split anchors. Rider probe on objectstack@9f4b652e3 (ablation-replace WRAP, restored): check-skill-line-ratchet '✗ … filing-gate.md is 59 lines; the ratchet ceiling is 58' (exit 1); check:pm-skill-id-lint '87 file(s) clean' (exit 0). CI on PR #12253 at report time: 12 check runs completed with 0 failures, 20 in_progress.", "mcp_calls": "0", "api_writes": "2 relay dispatches, each POST /repos/objectstack-ai/objectstack/dispatches executed by fleet-write as objectstack-fleet[bot]. #1 pr_create: POST /repos/objectstack-ai/objectui/pulls (draft) + POST /repos/objectstack-ai/objectui/issues/12253/assignees; read back 18279 bytes sent, 18279 stored, identical. #2 comment: POST /repos/objectstack-ai/objectui/issues/12224/comments (this report). Pushes, which are git and not REST: objectui branch ×3, objectstack rider branch ×1 (empty probe push). Unused budget: objectstack pr_create and label-write (skip-changeset), because the rider is blocked.", "gates": { "objectui@27c30c10": [ "vitest scripts/__tests__/ + ratchet · exit 0 · Test Files 182 passed | 2 skipped (184)", "vitest --project unit packages/app-shell/ · exit 0 · Test Files 277 passed | 1 skipped (278)", "pnpm --filter @object-ui/app-shell type-check · exit 0 · tsc --noEmit && tsc -p tsconfig.test.json", "eslint (2 changed lintable files) · exit 0 · 0 errors 0 warnings", "node scripts/check-governed-queue-guard.mjs --test (7 paths) · exit 3 · ⛔ GOVERNED — 2 of 7 path(s) (docs/adr/**, AGENTS.md); expected", "node scripts/check-changeset-presence.mjs · exit 0 · ✅ … declares 1 changeset(s) … EMPTY frontmatter", "node scripts/check-changeset-no-major.mjs · exit 0", "node scripts/check-changeset-claims.mjs · exit 0", "node scripts/check-new-cross-file-line-citations.mjs · exit 0 · VERDICT … 0 new citation(s)", "node scripts/check-control-bytes.mjs · exit 0 · OK (8511 files)", "node scripts/check-test-path-roots.mjs · exit 0", "node scripts/check-doc-links.mjs · exit 0 · Links are valid across 17 scan roots", "node scripts/check-lint-coverage.mjs · exit 0 · 46/46", "node scripts/markdown-test-inputs.mjs --audit · exit 0 · 123 candidates adjudicated; 87 entries present", "node scripts/check-unreferenced-sources.mjs · exit 0", "node scripts/check-published-tsconfig-tooling-exclude.mjs · exit 0", "node scripts/check-doc-component-types.mjs · exit 0", "control-byte self-scan (grep -naP) on the 7 changed files · exit 1 = none", "NOT RUN, declared to CI: app-shell dom/dom-heavy projects, pnpm lint (repo-wide), pnpm check (CLI self-check), Test shard matrix" ], "objectstack@9f4b652e3 (rider, nothing committed)": [ "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack · exit 2 · 'this branch changes nothing against origin/main — nothing to derive'", "same, with the hypothetical path filing-gate.md · exit 0 · 17 commands, incl. pnpm check:pm-skill-ratchet, check:pm-skill-id-lint, check:nul-bytes", "rider probe: check-skill-line-ratchet · exit 1 · filing-gate.md is 59 lines; the ratchet ceiling is 58", "rider probe: pnpm check:pm-skill-id-lint · exit 0", "base: check-skill-line-ratchet · exit 0 · filing-gate.md is 58 lines (ceiling 58; headroom 0)" ] }, "line_budget": { "objectui AGENTS.md": "608 → 618 (+10; the dispatch asked ≤ +20)", "objectstack filing-gate.md": "58 → 58, unchanged; with the drafted rider line it would be 59 against ceiling 58" }, "files_changed": { "objectui": [ "AGENTS.md", "docs/adr/0060-product-neutral-renderer.md", "packages/app-shell/src/__tests__/product-neutral-renderer.ratchet.test.ts", "packages/app-shell/src/__tests__/product-specific.allowlist.json", "scripts/markdown-test-inputs.mjs", ".github/pull_request_template.md", ".changeset/12224-product-neutral-renderer.md" ], "objectstack": [] }, "deviations": [ "Route, PM suggestion bettered. Besides the live allowlist, the ratchet reads a ceiling and its rules (product words, frozen directories, frozen namespaces) from a fenced json block at the end of ADR-0060. Every live entry must be inside it, so a new product entry needs a governed ADR amendment, and appending to the allowlist alone stays red (M5). The cost is a markdown read, which is declared in markdown-test-inputs.", "H1. The ratchet uses the repo's static registration derivation (deriveRegistryKeys, repo-wide, both spellings, fails closed on an unrecognised options shape) instead of a runtime enumeration after app-shell registers. A runtime enumeration would see only app-shell's import closure, while a product registration in any package must turn the ratchet red. A synthetic-tree control in the test pins both spellings.", "H2. The frozen directories are recursive, so organizations/manage/ counts. Test paths (__tests__, __mocks__, __fixtures__, __benchmarks__, test, tests, e2e, and *.test/spec/stories) are outside the file half. Product-named files are matched repo-wide, a generalisation of the card's console/home/Cloud*.tsx.", "H3. A product-led namespace or key at any depth is refused unless frozen. Frozen namespaces take no new key in any locale. A neutral new namespace passes. This is recorded in ADR-0060 and put to the maintainer in the 速读.", "Frozen i18n set beyond the card: the whole environment namespace (every consumer sits in the frozen dir), planTier, and aiModelStatus. organization (singular), chatbotQuota, marketplace and connectAgent were considered and not frozen, with reasons in the ADR.", "A second ledger row went into scripts/markdown-test-inputs.mjs for check-installed-spec-pin-claims.test.ts, which reads every tracked file and so reads the new PR template. The ledger is pinned total over tracked markdown. This sits inside the claim's declared ledger surface.", "Rider not delivered: zero line-ratchet headroom plus the one-line, stop-on-breach surface. See open_questions.", "Commit trailers use the repos' model-free pair (Claude-Session + Co-authored-by: Claude) instead of the harness reminder's model-named Co-Authored-By. AGENTS.md takes precedence.", "The full root pnpm test was not run locally. Run instead: all of scripts/__tests__, the ratchet, and app-shell's unit project. The dom/dom-heavy projects and the shard matrix are declared to CI; this diff changes no source that those projects import." ], "open_questions": [ { "question": "How should the one rider line in .claude/skills/pm-dispatch/references/filing-gate.md be paid for? The file is at its line-ratchet ceiling (58/58). The drafted line is '- UI 卡写明所需通用块或 spec 契约门;要产品命名 widget/dialog/hook/命名空间的卡退回重立。' (116 bytes, id-lint green).", "options": [ "A. Pay by deleting content in the same file. Candidate: the intro's self-description clause '本文是「什么才算一张卡」与定级、读数三组判据的执行说明', which the three headings already state. That turns the two-line intro into one, keeps the file at 58, and leaves the ceiling where it is. Cost: it touches a second line, beyond the dispatch's one-line surface. Effort: one small re-dispatch.", "B. A maintainer ruling raises the ceiling 58 → 59, quoted in the rider PR. Cost: maintainer attention and corpus growth.", "C. The dispatch names this a measurement-first zero-headroom ledger: land the line red and leave the ceiling line alone. Cost: a red Lint & Repo Gates context on a Tier S PR until a ruling." ], "recommendation": "A. The ratchet's own discipline says a new line is paid for by deleting content, the clause restates the headings, and no ceiling moves." } ], "out_of_scope_findings": [ "carrier: the maintainer, on objectstack-ai/objectui#12253 (ADR-0060 review) · noted, not filed. Product copy that this reading leaves unfrozen: organization (singular, 116 keys, also read by layout and @object-ui/auth) and chatbotQuota (plugin-chatbot quota/credit copy). Freezing either is an ADR-0060 amendment." ] }Generated by Claude Code
objectstack-fleet commentedon Oct 12, 2026
PM answer to the os-dev report's open question (
6125187793) · seatdomain:skills#2·session_012dGTuJen61ECNHXYXKChoC· 2026-10-12T13:26ZAnswer: A. The rider line in objectstack's
.claude/skills/pm-dispatch/references/filing-gate.mdis paid for by deleting the intro's self-description clause, "本文是「什么才算一张卡」与定级、读数三组判据的执行说明". The clause restates the file's three headings (## 立卡门,## 定级判据…,## 读数判据…), so its content keeps a home there. It is a description, not a rule, so no rule is lost. The freed line comes from deleting content, not from re-wrapping, and the ratchet ceiling (58) does not move. B (raising the ceiling) and C (landing red) are not taken.This is a bookkeeping answer, not an escalation: it is a line-ratchet payment inside a lane's own text, with no product-visible change.
Claim file surface, amended in this act: the objectstack rider now covers
filing-gate.mdlines 3–4 (the intro, reduced to its pointer sentence) plus the one new line under## 立卡门. Nothing else in that file changes. The same dev resumes the rider half onclaude/issue-12224-objectui-filing-gate-rider.Generated by Claude Code
objectstack-fleet commentedon Oct 12, 2026
os-dev-report
{ "issue": 12224, "status": "done", "branch": "claude/issue-12224-objectui-filing-gate-rider", "pr": "https://github.com/objectstack-ai/objectstack/pull/23051", "session": "session_012dGTuJen61ECNHXYXKChoC — subagent run; the parent PM session's id, as the Claude-Session trailer on the rider commit spells it", "premise_still_valid": true, "summary": "Rider half only; the objectui PR objectstack-ai/objectui#12253 is untouched. Following PM answer A (comment 6125224340), one commit on claude/issue-12224-objectui-filing-gate-rider (6b43997f7, fast-forwarded from the empty 9f4b652e3 to origin/main 38d98d8d8 first) edits objectstack .claude/skills/pm-dispatch/references/filing-gate.md and nothing else. It deletes the intro's self-description clause 「本文是「什么才算一张卡」与定级、读数三组判据的执行说明」, which restates the three headings, so the intro becomes its pointer sentence on one line. It adds under ## 立卡门 the line 「- UI 卡写明所需通用块或 spec 契约门;要产品命名 widget/dialog/hook/命名空间的卡退回重立。」. The file stays at 58 lines against an unchanged ceiling of 58, with no re-wrap and no other line touched. Draft PR objectstack-ai/objectstack#23051 has assignee os-justin, the given title, and a body that names objectstack-ai/objectui#12224 and objectstack-ai/objectui#12253 with no closing keyword, a 维护者速读 section (席位意见 left blank) and Acceptance notes naming the deleted clause and the added line. It carries skip-changeset, written through label-write.mjs and read back. Body read back identical, 6258 bytes sent and 6258 stored.", "tests": "At 6b43997f7, derivation: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths) → 17 commands; change set filing-gate.md, +2/-2. Every command ran with its exit code captured to disk first; --ran reconciliation: '17 derived, 17 run, 0 NOT-MEASURED, 0 UNRUN (a DERIVED zero — all 17 recorded an exit code and none of them is 3)'. Key verdicts: pnpm check:pm-skill-ratchet exit 0 '✓ … filing-gate.md is 58 lines (ceiling 58; headroom 0)'; pnpm check:pm-skill-id-lint exit 0 '87 file(s) clean'; pnpm check:nul-bytes exit 0 'OK (scanned 11047 text file(s) … no raw ASCII control bytes)'. The remaining 14 also exited 0: closing-keyword-parity and its self-test, comment-mask-corpus, check-harness-current --self-test, agent-test-spelling, cross-package-test-inputs, doc-authoring, driver-memory-census, gitlink-declared, pm-governed-merges, refd-timer-probe, skill-frame-sync, watch-hint-literal, and doc-formula-expressions. doc-formula-expressions first exited 3 with PREREQUISITE NOT MET (formula and lint not built), which measured nothing; after turbo run build --filter=@objectstack/formula --filter=@objectstack/lint (4/4, under os-verify-lock) the re-run exited 0. CI on #23051 at report time: 23 check runs completed with 0 failures, 13 in_progress.", "mcp_calls": "0", "api_writes": "3 relay dispatches (POST /repos/objectstack-ai/objectstack/dispatches, executed as objectstack-fleet[bot]). (1) pr_create: POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos/objectstack-ai/objectstack/issues/23051/assignees. (2) label-write labels_add: POST /repos/objectstack-ai/objectstack/issues/23051/labels; read back: documentation, size/xs, skip-changeset. (3) this comment: POST /repos/objectstack-ai/objectui/issues/12224/comments. Git pushes: rider branch ×2 (fast-forward to main, then the commit).", "line_budget": { "objectstack filing-gate.md": "58 → 58 (ceiling 58, unchanged; −1 content line from the intro, +1 rule line)" }, "files_changed": { "objectstack": [".claude/skills/pm-dispatch/references/filing-gate.md"] }, "deviations": [ "The rider branch already existed as an empty push at 9f4b652e3. The worktree was re-attached to it and fast-forwarded to origin/main (38d98d8d8) before editing, so no force-push was needed. 'Built from current origin/main' holds.", "The objectstack PR body opens with 'Clause-②: no' at line start, copied from the claim per os-dev.", "The worktree was removed after the reports, with a clean tree and the head equal to the origin branch." ], "open_questions": [], "out_of_scope_findings": [] }Generated by Claude Code
objectstack-fleet commentedon Oct 12, 2026
ACCEPT (rider half) — objectstack PR objectstack-ai/objectstack#23051 @
6b43997f77· seatdomain:skills#2·session_012dGTuJen61ECNHXYXKChoC· 2026-10-12T23:10ZChecked against GitHub and
origin/main, not the report (6125436892):Shape: draft, base
main, assigneeos-justin,skip-changeset,Clause-②: noon the first line. The body names this card and objectui PR docs(governance): objectui is a product-neutral renderer — AGENTS.md rule, ADR-0060, and a ratchet over registry keys, files and locale keys #12253 with no closing keyword.Diff: one file,
.claude/skills/pm-dispatch/references/filing-gate.md, +2/−2. It is exactly the PM's answer A (6125224340):## 立卡门.The file stays at 58 lines against a ceiling of 58, and the ceiling does not move.
CI on this head: 38 check-runs completed: 26 success, 12 skipped by the paths filter, 0 red. The required
Lint & Repo Gates,TypeScript Type Check,Test CoreandGoverned Surface Queue Guardare all success.Contract review: PASS at
CONTRACT_REVIEW_TIERon this head, record6134365672on the PR.Landing: Tier S (
check-governed-merges --pr 23051). This seat lands it now through the queue.The objectui half (PR #12253, Tier H) is still under contract review. This card closes when that PR merges.
Generated by Claude Code
objectstack-fleet commentedon Oct 12, 2026
REWORK, round 1 (one sentence) — objectui PR #12253 @
27c30c10ae· seatdomain:skills#2·session_012dGTuJen61ECNHXYXKChoC· 2026-10-12T23:13ZThe at-tier contract review
6134399082reads PASS on this head. The seat holds the ACCEPT for one item that review raised (its item 5). ADR-0060's "Consequences" bullet says every pull request's description carries the template's checkbox. That is false: GitHub prefills the template only for PRs opened in the web form, and every fleet PR, this one included, is opened through the API. Nothing enforces the checkbox. A governed record must not state a guarantee nothing delivers.Patch round sent to the same dev on the same claim: narrow that bullet, and line 71's mention if it overclaims the same way. Nothing else in the PR changes. The review's other items are design calls for the maintainer: the H3 locale reading, the freeze scope beyond the card, the ceiling living in the governed ADR, the
organizations/workspacevsorganization/chatbotQuotasplit, and the two product words. They go to the maintainer in the final quick-read after the patched head's contract review.Generated by Claude Code
objectstack-fleet commentedon Oct 12, 2026
os-dev-report
{ "issue": 12224, "status": "done", "branch": "claude/issue-12224-product-neutral-renderer", "pr": "https://github.com/objectstack-ai/objectui/pull/12253", "session": "session_012dGTuJen61ECNHXYXKChoC — subagent run; the parent PM session's id, as the Claude-Session trailer on the rework commit spells it", "premise_still_valid": true, "rework": "patch round 1, contract review 6134399082 item 5 (① 11)", "head": "5fed8ccc (full 5fed8ccc on claude/issue-12224-product-neutral-renderer, parent 27c30c10ae); no merge of origin/main, since the PR read mergeable/clean", "summary": "Two sentences changed in docs/adr/0060-product-neutral-renderer.md; no other file changed. The Consequences bullet no longer claims every pull request carries the template's checkbox. Line 71 claimed the checkbox 'catches' the rest, the same overclaim, so it was narrowed in the same commit. The frozen-baseline section is byte-identical: sha256 of everything from '## Frozen baseline' to EOF was a7fb7087… before the edit and is the same after. AGENTS.md's sentence ('left to review and the pull-request template's checkbox') was left alone, because the patch scope said nothing else changes. The review's ① 11 also names it; it is the maintainer's call. The PR body was not edited.", "changed_sentences": [ { "where": "ADR-0060, The ratchet › What the ratchet cannot see, first bullet (line 71)", "before": "are all it reads; the pull-request template's checkbox and review catch the rest;", "after": "are all it reads; the rest is left to review, which the template's checkbox prompts only on web-form PRs;" }, { "where": "ADR-0060, Consequences, third bullet (lines 162–163)", "before": "- Every pull request's description carries the template's checkbox: \"Adds no product-specific widget, dialog, hook or string\".", "after": "- A pull request opened through the web form starts with the template's checkbox; one opened through the API, as the fleet's are, does not. The checkbox prompts human authors; it is not a gate." } ], "tests": "At 5fed8ccc, run from the repo root through os-verify-lock, with exit codes written to disk first. pnpm exec vitest run scripts/__tests__/markdown-test-inputs.test.ts → exit 0, 'Test Files 1 passed (1)' 'Tests 25 passed (25)'. pnpm exec vitest run packages/app-shell/src/__tests__/product-neutral-renderer.ratchet.test.ts → exit 0, 'Test Files 1 passed (1)' 'Tests 32 passed (32)'. Also: node scripts/check-new-cross-file-line-citations.mjs exit 0, '0 new citation(s)'; node scripts/check-doc-links.mjs exit 0.", "mcp_calls": "0", "api_writes": "1 relay dispatch: POST /repos/objectstack-ai/objectstack/dispatches executing POST /repos/objectstack-ai/objectui/issues/12224/comments (this comment). Git push ×1 (27c30c10..5fed8ccc).", "open_questions": [], "out_of_scope_findings": [] }Generated by Claude Code
objectstack-fleet commentedon Oct 12, 2026
ACCEPT (objectui half) — PR #12253 @
5fed8ccc46· seatdomain:skills#2·session_012dGTuJen61ECNHXYXKChoC· 2026-10-12T23:28ZChecked against GitHub and objectui
origin/main, not the reports (6125187793, rework6134447475):main, first lineFixes #12224,Clause-②: no, assigneeos-justin. Empty-frontmatter changeset; objectui carries noskip-changeset. Seven files:AGENTS.md(+10, one new section),docs/adr/0060-product-neutral-renderer.md(new), the ratchet test and its live allowlist underpackages/app-shell/src/__tests__/, twomarkdown-test-inputsledger rows,.github/pull_request_template.md(new, one checkbox), and the changeset.namespace: 'cloud'included.6134419284): the ADR's checkbox guarantee is narrowed to what is true (web-form PRs only, not a gate). Delta is two sentences; the frozen-baseline block is byte-identical.CONTRACT_REVIEW_TIERon this head, record6134585175(previous head6134399082, PASS). The record lists six design calls for the maintainer; they ride with the approval and are restated in the final quick-read on the PR.AGENTS.md,docs/adr/**). The PR stays draft;needs-user-decisionon the PR; review requested fromos-zhuangandhotlong. After an authorized APPROVED review this seat lands it.6134379319) is enqueued by this seat.Generated by Claude Code
objectstack-fleet commentedon Oct 12, 2026
Rider landed — objectstack PR objectstack-ai/objectstack#23051 MERGED as
dc08c609a(this seat's relay stroke, enqueued 2026-10-12T23:13Z, merged by the queue) · seatdomain:skills#2·session_012dGTuJen61ECNHXYXKChoC· 2026-10-12T23:39ZRead on objectstack
origin/main:filing-gate.mdcarries the rider line under## 立卡门(1 hit) and stays at 58 lines. This card stays open,pm:dispatched, for its objectui half: PR #12253 awaits an authorized approval (速读6134603082). It closes when that PR merges.Generated by Claude Code
objectstack-fleet commentedon Oct 13, 2026
Landed — objectui PR #12253 MERGED as
f228d710(merged byos-zhuangthrough the queue: APPROVED review 5497622223 onf3369125bd, flipped ready, auto-merge, enqueued) · seatdomain:skills#2·session_012dGTuJen61ECNHXYXKChoC· 2026-10-13T01:24Zf3369125bdis5fed8ccc46plus one merge ofmainby the approver. The PR's net diff against its merge base is byte-identical to the diff contract-reviewed at5fed8ccc46(record6134585175), and none of the PR's seven files changed in the merge. CI onf3369125bd: 30 success, 3 skipped, plus one queue-guard run cancelled and superseded by a passing one. That includes the product-neutral ratchet against 24 newermaincommits.origin/mainafter the merge:docs/adr/0060-product-neutral-renderer.md, the AGENTS.md "Product-neutral renderer" section,packages/app-shell/src/__tests__/product-neutral-renderer.ratchet.test.tsand.github/pull_request_template.mdare all present.dc08c609a).6134603082) land as the PR stood.Fixes;pm:dispatchedis stripped in this act.Generated by Claude Code