Repository navigation
[PM seat] domain:services — 🟢 os-justin #6021
Description
This post is the single authoritative registry for the domain:services seat 1 (seat-post protocol; index label:pm:seat). Single writer: the incumbent only. Read side: this body plus every comment newer than the body's last edit. ⛔ Shift narrative does not belong in the body — this post carries current values only. Job description: .claude/skills/pm-dispatch/references/lanes/services.md. Seat 2 is #21118.
1. Current PM — 🟢 os-justin
- Account:
os-justin(GET /user). Session:session_011TdZ8GjixNZFLz1xJD9zzK. Seated: 2026-10-20T05:41Z, on the maintainer's invocation/pm-dispatch services seat 1(this session's first user turn). The previous term's scope (p1–p3, serial dispatch) was the maintainer's word to that session and ⛔ is not inherited; this term runs the defaultbatch3. - Wake Routine:
trig_01755ku8Ef2i5GbZgTkNRFrE(self-bound, hourly at :28,own_followup). It is the default wake; a round-endsend_lateris only an accelerator. - Write identity: the fleet relay (
objectstack-fleet[bot]) viascripts/pm/*, transportdispatch(route read at seating:CCR_AGENT_PROXY_ENABLEDset, session derived from the container, relay workflow onmainand active). - Harness currency: CURRENT at 2026-10-21T10:18Z on shared HEAD
2b1382a5b3(check-harness-currentexit 0; the round-boundary re-pin at 2026-10-20T14:52Z picked up.claude/hooks/*7e40e8a03a, fix(hooks): read a command substitution inside a double-quoted word as its own quoting context #24886, and the one at 2026-10-21T01:30Z picked upbe1fd311b1(docs(os-dev, pm-dispatch): a breaking PR runs the full dogfood battery on its final head; the review checklist reads the field before arming #24917:agents/os-dev.mdandreferences/review-checklist.md, thedogfood_batteryrule); the shared checkout is pinned to a detachedorigin/mainbefore each subagent batch, per PR docs(pm-dispatch): pin the shared checkout to a detached origin/main before a subagent batch #24685's runbook step). Touches:SKILL.mdc1f4093,execution-duties.mdc03b17d,lanes/services.mdf151ef2c9,agents/os-dev.mdcb8756b00; references read this term after landing mid-term:dispatch-runbook.md(c663245647),cross-repo-coordination.md(d20bf9b09b),filing-gate.md(a43405d59). - Previous incumbents:
marchtian·session_01Nk17Z26X5DB59iQztDBADH(seated 2026-10-17T13:57Z, signed off 2026-10-19T23:14Z; brief6279429458, handover check exit 0). Before it:os-bill·session_017WLmd5in9RXu7AjyHR8fKQ(briefs6188435608and6206660121);marchtian·session_01LxHPTb1LxL7a6WkQbALKnD(brief6173044890);os-warren·session_01CeRCvvvjxbxu2iYJAc5Cce(brief6127166372). ⛔ Earlier ones are not restated here.
2. Ledger — current values
- Maintainer's live words this term: 「新的 派」, 「你车道的p1 都派」, 「并发3」, 「24784 插队」, 「当前任务处理完,后续并发降到2」 (2026-10-20T13:01Z), then 「暂时只处理 p1 p2」 (2026-10-20T22:40Z), then 「后续改为串行派发」 (2026-10-21T10:07Z), all in this session's chat. Recorded by the director seat on cards, and binding here: 「暂时不考虑 v19,协议的调整原则上也是尽快,不考虑退役版本。」 (the amended 「甲」,
6303865025on [PM seat] triage (objectstack-wide) — 🟢 Routine · session_01AavokzJ5DndAwitDXvKy4U · trig_01NcnCtMS2tH46nUg1a5TaMJ (hourly) · state = body + the round records newer than it #6015: a narrowing no conversion carries ships now, in 18.x, as a BREAKING minor), and 「类似的问题都可以这样处理」 (6304303975on meta: thewebhookmetadata type has no redactor, so its secret-bearing fields are not masked on the meta read doors (detail withheld under the disclosure ruling) #24966: declare a per-type fact on the schema and derive the behaviour once in the kernel). Dispatch is serial (「后续改为串行派发」, superseding 「并发3」 and the later concurrency of 2): one card is in flight at a time, and the next is dispatched only when the current one has landed or been released. A card that rides an in-flight claim's dev and PR, as plugin-security: under one master-reference declaration, a write to a controlled_by_parent detail is not held to ADR-0055's master invariant on every write shape (reach measured; detail withheld under the disclosure ruling) #25068 rides plugin-security: the controlled_by_parent detail write gate may not ask the master-edit question on one more write shape, where ADR-0055 §3 requires it (reach not measured; detail withheld under the disclosure ruling) #25049's, counts as that one card. Scope is p1 and p2 only, until the maintainer says otherwise. ⛔ No p3 is dispatched, and no p3 execution card is filed for dispatch. Every dispatchablepm:queuep1 of this lane is dispatched or held on a declared serial constraint. When nothing is in flight, the next dispatch takes the top p1, else the top p2. - In flight from this seat (refreshed 2026-10-21T10:18Z): serial dispatch, one card.
- deps(plugin-auth): lift the better-auth family from 1.7.3 to 1.7.12 — security fixes published after the 2026-10-01 deferral #25096 (p1, security; triage
6313201609: the maintainer's own word lifts the better-auth family to 1.7.12, superseding deps: take the 2026-10 production-dependency group without the better-auth family (replaces Dependabot #21029) #21094's deferral): claim6313539804,mode:subagent,Clause-②: no (narrowing). It ships as a BREAKING minor, not the card's patch, because the lift adds refusals 1.7.3 did not make. The file surface includespnpm-workspace.yamland the regeneratedpnpm-lock.yaml, declared on the cross-domain exception path. No open PR or in-flight claim touches those files. - Next under serial dispatch, once deps(plugin-auth): lift the better-auth family from 1.7.3 to 1.7.12 — security fixes published after the 2026-10-01 deferral #25096 lands: the top p1, else the top p2, of this lane's
pm:queue(at 2026-10-21T10:18Z: p2 plugin-security: the controlled_by_parent detail write gate may not hold one more value of a master reference to ADR-0055 §1 and §3 (reach not measured; detail withheld under the disclosure ruling) #25095, mail templates: a hole an author places in a template body may not be encoded for the context it lands in (reach not measured; detail withheld under the disclosure ruling) #25082, A screen flow whose write node is refused shows the end user the engine's raw node text, in English, with the node id and the object API name ("Node 'create_account' failed: create_record(crm_account) failed: …") #24914 and Setup: a position's same-named permission set is in force but invisible — the set's Assigned Users panel is empty and the position reads as granting nothing #24757; plugin-security: a controlled_by_parent child's read loads every readable master id with no limit (twice per request), so its CPU grows with the master table and the read answers 500 "too many SQL variables" past ~32.8k masters #24932 is seat 2's by its own6304727839).
- deps(plugin-auth): lift the better-auth family from 1.7.3 to 1.7.12 — security fixes published after the 2026-10-01 deferral #25096 (p1, security; triage
- With the maintainer: none from this seat.
- Closed by the maintainer: feat(plugin-email,plugin-security): organization admins read their own organization's mail bodies again (option B), once one exported identity selector exists #24898, not planned (
6308427243, 「24898 直接关闭。」). Ruling B is withdrawn, and fix(platform-objects,plugin-audit,plugin-approvals)!: mail bodies are read only with manage_platform_settings, and the audit mirrors never copy them in clear #24688's body gate stands. This seat's cross-lane declaration6304826207was released (6308816325). - Ruled this term, executing in other lanes (each card
pm:blocked, closing when its execution card lands):- A declared webhook in a scaffolded app is silently inert: os validate passes without the 'webhooks' and 'realtime' capabilities, and with 'webhooks' alone the activation answers enabled while nothing is ever enqueued (WARN only) #24910: A (
6303779439), amended to ship now (6303859748). Execution: spec: refuse a declared webhook whoserequirescannot dispatch it —STACK_WEBHOOK_CAPABILITY_REQUIREDindefineStack, the third declared-capability refusal (ruling A on #24910; ships in 18.x by the maintainer's re-timing) #24997 (domain:spec, thedefineStackrefusal, BREAKING). spec: the loud half for a declared webhook whoserequirescannot dispatch it —os validate/os buildwarn, naming the missing token and the 19.0 refusal (ruling A on #24910 under 「甲」 rule 2; 18.x) #24995 was closed as superseded. - A screen flow whose write node is refused shows the end user the engine's raw node text, in English, with the node id and the object API name ("Node 'create_account' failed: create_record(crm_account) failed: …") #24914: B′ (
6303788292). Execution order: spec:FLOW_FAILEDcarries the refused write's inner refusal — an optionaluserMessageonAutomationResultand one declared details member{ code, message }on the trigger, resume, /actions and endpoint doors (ruling B′ on #24914) #24996 (domain:spec, theAutomationResultmembers) first, then THIS card in this lane, serial after PR feat(spec,objectql): report a caller value a stored expression replaced, as DroppedFieldsEvent reason stored_expression #24778 incrud-nodes.tswith a cli declaration on [PM seat] domain:cli · seat 2 — 🟢 os-justin · session_01LmjU2x1faLZ39DVTFyVca6 #22648, then FlowRunner: aFLOW_FAILEDenvelope is rendered by the record-save rule — the author'serrorMessage, thenuserMessage, then the declared inner refusal, thenmessage(the console half of objectstack#24914 ruling B′) objectui#13285. ⛔ This seat dispatches A screen flow whose write node is refused shows the end user the engine's raw node text, in English, with the node id and the object API name ("Node 'create_account' failed: create_record(crm_account) failed: …") #24914 only after spec:FLOW_FAILEDcarries the refused write's inner refusal — an optionaluserMessageonAutomationResultand one declared details member{ code, message }on the trigger, resume, /actions and endpoint doors (ruling B′ on #24914) #24996 lands. - meta: the
webhookmetadata type has no redactor, so its secret-bearing fields are not masked on the meta read doors (detail withheld under the disclosure ruling) #24966: B, amended to B+ (6304303975). Execution: spec:WebhookSchemamarkssecretandheadersas credential fields, and the kernel registry derives the meta read-door redaction for any marked type —webhookfirst, with a ratchet for unmarked credential-named fields (ruling B+ on #24966) #24994 (domain:spec, a schema credential marker plus a derived kernel redactor and a ratchet).
- A declared webhook in a scaffolded app is silently inert: os validate passes without the 'webhooks' and 'realtime' capabilities, and with 'webhooks' alone the activation answers enabled while nothing is ever enqueued (WARN only) #24910: A (
- Landed this term:
- plugin-approvals: the served approval request page's H1 still reads
flow:NAME · RECORD_ID— the approvals get serves nodisplay_title, and the title names the raw record id (blocks objectui#12484) #24665 → PR fix(plugin-approvals): an approval request is titled by its flow's label, never the raw record id or the flow's machine name #24708 (b9d0c48a5d). - security(explain): explain's record-grained update verdict refuses a row an app-authored update policy admits, while the PATCH of that row is admitted (ADR-0105 D3 deferral missing on explain's record path) #24647 → PR fix(plugin-security): explain's record-grained write verdict composes the by-id write gate's authored-row-write deferral #24713 (
71a8b5eed6). - plugin-security: the platform-admin promotion WITHHELD warning still points the operator at the organization-ownership migration, which 18.0 refuses on every database (#24637, domain:services row 2) #24709 → PR fix(plugin-security): the platform-admin promotion WITHHELD warning says what 18.0 supports for a v17 database #24718 (
d0514e6863). - plugin-security: organisation admins assign positions and permission sets to their own members inside the D12 boundary — gate branch, overrides, explain and my-delegable-scope, three-posture acceptance (ruling B on #23960) #24136 → PR feat(plugin-security): organization administrators assign positions and permission sets inside the D12 organization boundary #24732 (
b27f8ded5c; cloud session archived). - Decision needed: should the sys_attachment / sys_comment parent gates drop their own-depth sharing step now that they ask the parent's by-id update judgement (#7144 revisited)? #24646 → PR feat(service-storage, plugin-audit): the parent gates ask the parent's by-id update alone; explain composes the on-behalf-of write #24745 (
1f949daeda). Contract review of record6283270561(CONTRACT_REVIEW_TIER, PASS). - plugin-security: the shipped permission sets stop copying the identity objects' row-scope literals once those objects declare them as their default row scope (#24340 follow-up, ruling E′ item 3) #24484 → PR fix(plugin-security): the shipped sets stop copying the identity objects' declared row scopes #24761 (
7d45c8e29a), carryingCheck Changeset's designed red. - plugin-security: an on-behalf-of by-id write can admit a row the delegator's own by-id write refuses, where an app-authored row-level write policy narrows the delegator (ADR-0090 D10) #24746 → PR fix(plugin-security): an on-behalf-of by-id write never admits a row its delegator's own by-id write refuses (ADR-0090 D10) #24792 (
605b3e28b7). The reproduction stays in this session's scratchpad. - plugin-security: the delegated-administration gate's position walk does not count the permission set a position grants by its own name, so a delegate's allowlist check judges fewer sets than the assignment grants #24736 → PR fix(plugin-security): the delegated walk counts the permission set of the position's own name #24793 (
21301a3406). - security: the auth IP allow-list does not resolve the client IP the way the runtime's trust-proxy rule does, and admits an undetermined IP (detail withheld under the disclosure ruling) #24739 → PR fix(plugin-auth): the auth IP allow-list judges the client address the server established #24795 (
25e16ab00c). - plugin-approvals: the submitter is never notified of the final decision — approving or rejecting a request emits no notification to them #24753 → PR fix(plugin-approvals): the decision that ends an approval tells its submitter the outcome #24816 (
7282a950b1). - group posture: a member whose session has no active organization gets 500 ERR_SYSTEM_WRITE_ORGANIZATION_REQUIRED on a tenant-scoped create, where isolated answers 403 naming the missing organization #24784 → PR fix(plugin-security): under group, a no-active-organization insert gets the ADR-0123 D2 403, not a 500 #24819 (
8a058d85a3), the 18.0 queue-jump. - plugin-security: my-delegable-scope offers a platform administrator the built-in identity positions that sys_user_position refuses from every writer #24737 → PR fix(plugin-security): every delegable-scope branch leaves out the built-in identity positions #24826 (
1366740c6c). - Setup → Authentication: controls that contradict the system — self-service registration ON while the audience is invitation only; Google login ON with no client id or secret #24776 → PR fix(service-settings): Setup → Authentication says what the sign-up and Google toggles do #24842 (
4be7281311). - Setup → Email and SMS: Send test has nowhere to enter a recipient, and Email saves with its required fields empty #24767 → PR fix(plugin-email, service-sms): Send test goes to the signed-in admin when the request names no recipient #24848 (
abd5acdaf7, half A). Half B by seat ruling6289437546: the server keeps the TOUCH gate, and the renderer half is Settings pages: Save is accepted while a visible required field is empty — the console draws the required asterisk but never checks it, though the spec declaresrequiredas "renderer + server-side validation" objectui#13239. The card is closed; a veto reopens it. - plugin-auth: invite-member refuses an unknown role with no
code— the spec docstring and auth docs promiseROLE_NOT_FOUND, so an ADR-0112 client cannot recognise the refusal #24750 → PR fix(plugin-auth): invite-member refuses an unknown role with code ROLE_NOT_FOUND #24846 (de9cd1f17f). Contract review of record6289177621(CONTRACT_REVIEW_TIER, PASS, isolated reviewer); cloud session archived. - approvals: remind() reports
notifiedper slot, not per person — an approver listed twice on a per-group slate counts as two while one reminder is delivered #24751 → PR fix(plugin-approvals): a reminder's notified counts each approver address once, not once per slate slot #24855 (9a06f0be0f). - plugin-approvals: on a multi-step approval, every later step records the previous step's decider as its submitter, so submitter-only actions and submitter notices go to the wrong person (an unreleased regression of #24527) #24817 → PR fix(plugin-approvals): every step of a multi-step approval names the run's submitter, not the previous step's approver #24860 (
28ff8a9ed8), before the unreleased feat(automation)!: an approval decision resumes a flow as the person who decided #24527 regression shipped. - Impersonating a user who must change their password strands the admin on that user's change-password screen #24762 → PR fix(plugin-auth): a credential-scope posture does not hold an impersonation session (#24762) #24866 (
c2d4072281), B1 of ruling6288774214. C is console: the password-change overlay covers the impersonation banner, so an admin impersonating a held user can only sign out — "Stop impersonating" is hidden behind it objectui#13208. - On PostgreSQL every webhook delivery is dropped at enqueue — "[webhook-auto-enqueuer] enqueue failed … Converting circular structure to JSON (Timeout)" — and the loss is logged at WARN #24835 round 1 → PR fix(plugin-webhooks): report a webhook delivery the outbox could not record at error, once per webhook #24862 (
3fbef41b4a,Part of). - service-settings: on a deployment whose Google credentials come from GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET, saving "Enable Google login" ON is refused as missing the client id and secret, while the login page offers Google #24844 → PR fix(service-settings): Google login saves ON when its credentials come from the server #24874 (
fcb40ad673). - On PostgreSQL every webhook delivery is dropped at enqueue — "[webhook-auto-enqueuer] enqueue failed … Converting circular structure to JSON (Timeout)" — and the loss is logged at WARN #24835 round 2 → PR fix(driver-sql): update() stamps updated_at into a fresh object, never the caller's data #24906 (
eee65afc89), the producer fix indriver-sql(cross-lane, declared6289887999, landed note6293740758). The card is closed. - A scaffolded app pointed at PostgreSQL is refused with "Run pnpm install && pnpm build", which does not fix it: the missing optional peer pg is reported as a build precondition #24909 → PR fix(service-datasource): a missing database client (pg, mysql2, better-sqlite3) is refused with its install, not the unbuilt-workspace build advice #24933 (
ea08ce584c), the missing database client's install, plus the getting-started docs (round 2). - A declared webhook in a scaffolded app is silently inert: os validate passes without the 'webhooks' and 'realtime' capabilities, and with 'webhooks' alone the activation answers enabled while nothing is ever enqueued (WARN only) #24910 part (c) → PR fix(plugin-webhooks,runtime): a declared webhook the deployment can never deliver is reported at error and refused at the activation door #24946 (
19e5338cc8,Part of): the booterrorfor an undeliverable declared webhook. Its squash title's "refused at the activation door" is stale; the door is unchanged. - fix(cli,service-datasource): under bin/run-dev.js (NODE_ENV=development) an unopenable SQLite datasource steps down to an in-memory engine, so a dev-mode os migrate audit-mail-bodies reports an unreachable archive as examined and clean #24950 → PR fix(service-datasource): in development, a SQLite file that cannot be opened or created fails its connect instead of stepping down to an in-memory engine #24955 (
5d27d326c2): a development SQLite file-open failure no longer steps down to in-memory. - Setup: Notification Preferences and permission-set assignments are titled by raw user ids, not the person's name #24775 → PR fix(plugin-security): a permission-set assignment is titled by the person's name, not the raw user id #24885 (
6440cf1633): permission-set assignments are titled by the person. The prelude stays at 8 reads in 4 round trips. - service-datasource: a missing optional @objectstack/driver-* package (turso, mongodb, sqlite-wasm) is refused with two contradictory fixes, the factory's install and the appended 'build precondition ... Run pnpm install && pnpm build' #24937 → PR fix(service-datasource): a missing optional driver package (turso, mongodb, sqlite-wasm) is refused with the factory's install alone, not the unbuilt-workspace build advice #24971 (
b811c73696): a missing optional driver package ends on its install alone. It carriedCheck Changeset's DELIBERATE CORRECTION red under SKILL.md's three conditions, and corrected A scaffolded app pointed at PostgreSQL is refused with "Run pnpm install && pnpm build", which does not fix it: the missing optional peer pg is reported as a build precondition #24909's pending note. - Approvals show their flow and step names in the authoring language only: the request snapshots Flow.label / node.label at open, and the translation contract has no key for an approval step #24863 → PR fix(plugin-approvals): serve the approval flow, step and object labels in the reader's locale #24977 (
ba69b168be): the approval flow, step and object labels in the reader's locale. - plugin-security: a controlled_by_parent detail is readable by a caller with no read on its master object, where ADR-0055 refuses it (detail withheld under the disclosure ruling) #24962 → PR fix(plugin-security): a controlled_by_parent detail's read scope requires object-level read on its master #24985 (
9532e27886): acontrolled_by_parentdetail's read scope asks object-level read on its master first. The evidence is private, in this session's scratchpad. - plugin-security: the controlled_by_parent detail write gate's master-edit check may not ask the same question as the master's own write door (reach not measured; detail withheld under the disclosure ruling) #24986 → PR fix(plugin-security): the controlled_by_parent master-edit leg asks the master's own write-door question #25008 (
aaee0840be): the master-edit leg asks the master door's object-levelupdatequestion. Reach was measured privately; the unfixed path is plugin-security: one write path to a controlled_by_parent detail does not ask for edit access on its master, where ADR-0055 §3 requires it (reach measured; detail withheld under the disclosure ruling) #25012. - plugin-approvals: the approval notifications (approval.requested, reminder, sla_breached, approved/rejected, out-of-office) reach every approver as literal English sentences built at emit; no catalog holds them, so no recipient locale can apply #24978 → PR feat(service-messaging,plugin-approvals): keyed notification text, rendered per recipient at delivery, so approval notifications reach each recipient in their own language #25014 (
58cd58fa6c): keyed notification text, rendered per recipient at delivery. The seat ruled the snapshot-reservation question A; the maintainer's veto toward C stays open. os migrate apply's account-issuer pre-flight report labels every colliding row's issuer(none):probeAccountIdentityCollisionsreadsissuerthrough the engine, which no longer projects the undeclared column #25030 → PR fix(plugin-auth): os migrate apply's account-issuer pre-flight names each colliding row's stored issuer #25056 (4bf079c693):os migrate apply's issuer pre-flight names each colliding row's stored issuer, and both CLI doors read through one reader.Clause-②: yes (widening), withplugin-authas aminor. The optional retirement of the handed-find path was pointed to the cli seat (6309482297).- plugin-security: one more write to a controlled_by_parent detail is decided without asking for edit access on every master it involves, where ADR-0055 §3 requires it (reach measured; detail withheld under the disclosure ruling) #25044 → PR fix(plugin-security)!: an update of a controlled_by_parent detail also asks for edit access on the master its body names (ADR-0055 §3) #25066 (
f46ef4d70e): an update of acontrolled_by_parentdetail also asks for edit access on the master its body names. It is a verdict through the one chain walk, not a scope, and a BREAKING minor. Contract review of record:6310100720(PASS). Patch round 1 narrowed the headline before the queue. - outlets: every outlet that renders a text field into HTML escapes it by context (mail templates by default, HTML exports, integration payloads), pinned by an outlet list;
sys_user.namemaxLength held at the write seam (ruling 3C, #25040) #25061 → PR fix(service-messaging)!: an html or mjml notification template escapes every hole for markup, and each outlet package pins its outlet list (ruling 3C) #25076 (a39389eb51): an html or mjmlsys_notification_templatebody escapes every hole's value for markup (ruling 3C), and each package that holds an outlet pins its outlet list. A BREAKING minor (Clause-②: no (narrowing)by claim amendment6310385063), with the full dogfood battery green on its final head. Contract review of record:6310965376(PASS). - plugin-security: the controlled_by_parent detail write gate may not ask the master-edit question on one more write shape, where ADR-0055 §3 requires it (reach not measured; detail withheld under the disclosure ruling) #25049 + plugin-security: under one master-reference declaration, a write to a controlled_by_parent detail is not held to ADR-0055's master invariant on every write shape (reach measured; detail withheld under the disclosure ruling) #25068 → PR fix(plugin-security)!: a batch create of a controlled_by_parent detail asks for edit access on every row's master, and an update no longer empties the master reference (ADR-0055 §1, §3) #25090 (
3782b2df6e): a batch create of acontrolled_by_parentdetail asks for edit access on every row's master, and an update no longer empties the master reference. Both are verdicts through the one chain walk, shipped as a BREAKING minor. Contract review of record:6312751822(PASS). The seat redacted two clauses of it, and four passages of the dev's report, where they pointed at an unfixed path. - plugin-security: one write path to a controlled_by_parent detail does not ask for edit access on its master, where ADR-0055 §3 requires it (reach measured; detail withheld under the disclosure ruling) #25012 → PR fix(plugin-security)!: an update or delete of a controlled_by_parent detail asks for edit access to its master on every write shape (ADR-0055 §3) #25042 (
b2890909aa): an update or delete of acontrolled_by_parentdetail asks for edit access to its master on every write shape. It is a per-master verdict, not a scope, and a BREAKING minor. Contract review of record:6308053259(PASS). The changeset headline was narrowed to the verbs measured before the CHANGELOG published. - service-messaging: refuse sys_notification_template rows for a channel other than email or sms (the 19.0 half of ruling D) #24983 → PR fix(service-messaging)!: sys_notification_template refuses a channel other than email or sms, stored rows included #25028 (
d68aab6fde):sys_notification_templaterefuses a channel other than email or sms, stored rows included (BREAKING minor). The contract review of record is6306621951(CONTRACT_REVIEW_TIER, PASS). It carried the DELIBERATE CORRECTION red for the pending service-messaging: sys_notification_template takes only the channels that read it (email, sms), by the maintainer's ruling D on #24770 #24924 note it corrected (6306367946), and the full dogfood battery ran green on its final code.
- plugin-approvals: the served approval request page's H1 still reads
- Filed this term:
- From plugin-security: organisation admins assign positions and permission sets to their own members inside the D12 boundary — gate branch, overrides, explain and my-delegable-scope, three-posture acceptance (ruling B on #23960) #24136: plugin-security: the delegated-administration gate's position walk does not count the permission set a position grants by its own name, so a delegate's allowlist check judges fewer sets than the assignment grants #24736 (landed), plugin-security: my-delegable-scope offers a platform administrator the built-in identity positions that sys_user_position refuses from every writer #24737 (landed), app-shell: the published README and the Setup holder sections still say objectstack's organization administrator is read-only on the assignment objects — objectstack#24732 gave it create and delete objectui#13119.
- From Decision needed: should the sys_attachment / sys_comment parent gates drop their own-depth sharing step now that they ask the parent's by-id update judgement (#7144 revisited)? #24646: plugin-security: an on-behalf-of by-id write can admit a row the delegator's own by-id write refuses, where an app-authored row-level write policy narrows the delegator (ADR-0090 D10) #24746 (landed). Abstract only.
- From security: the auth IP allow-list does not resolve the client IP the way the runtime's trust-proxy rule does, and admits an undetermined IP (detail withheld under the disclosure ruling) #24739: plugin-auth: the vendored auth library's own client-address reader does not follow server.trustProxy, so the addresses it records and keys on are not the ones the server established (detail withheld under the disclosure ruling) #24799 (abstract only) and spec + ADR-0069 D5: server.trustProxy's describe names only the rate limiter, and ADR-0069 D5's mechanism cell names the old header list; since PR #24795 the auth IP allow-list and the login audit consume the same rule #24818.
- From plugin-approvals: the submitter is never notified of the final decision — approving or rejecting a request emits no notification to them #24753: plugin-approvals: on a multi-step approval, every later step records the previous step's decider as its submitter, so submitter-only actions and submitter notices go to the wrong person (an unreleased regression of #24527) #24817 (landed).
- From group posture: a member whose session has no active organization gets 500 ERR_SYSTEM_WRITE_ORGANIZATION_REQUIRED on a tenant-scoped create, where isolated answers 403 naming the missing organization #24784: a platform operator whose session has no active organization gets 500 ERR_SYSTEM_WRITE_ORGANIZATION_REQUIRED on an insert into a posture-permitting tenant object, under group and isolated alike #24821 (seat 2), group posture: a member's insert whose organization_id names another organization of its membership set is silently stored in the active organization (the engine's read-only strip), where #21666 ruled an explicit value meets the wall and is never rewritten #24822 and ADR-0123 D2 says "under group, no organization scope means an empty membership set"; since PR #24819 a union-scope insert with no active organization is refused too, so the ADR under-describes the runtime #24823.
- From Setup → Authentication: controls that contradict the system — self-service registration ON while the audience is invitation only; Google login ON with no client id or secret #24776: service-settings: on a deployment whose Google credentials come from GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET, saving "Enable Google login" ON is refused as missing the client id and secret, while the login page offers Google #24844 (landed).
- From Setup: Notification Preferences and permission-set assignments are titled by raw user ids, not the person's name #24775: service-messaging: sys_notification_preference.user_id is a text column holding a user id or the sentinel '*', so the preference's title can only show the raw id; naming the person means re-typing it as a user reference (an accept-set narrowing) #24895 (the
sys_notification_preference.user_idretype, breaking, the maintainer's) and core: the authz prelude reads sys_user_permission_set with no projection, so every formula on it runs per request; PR #24885's one-hop display title would add a sys_user read and a round trip for each principal with a direct grant #24896 (the engine lane: project the authz prelude's grant read). - From Setup → Email and SMS: Send test has nowhere to enter a recipient, and Email saves with its required fields empty #24767: Settings pages: Save is accepted while a visible required field is empty — the console draws the required asterisk but never checks it, though the spec declares
requiredas "renderer + server-side validation" objectui#13239. - From A scaffolded app pointed at PostgreSQL is refused with "Run pnpm install && pnpm build", which does not fix it: the missing optional peer pg is reported as a build precondition #24909: service-datasource: a missing optional @objectstack/driver-* package (turso, mongodb, sqlite-wasm) is refused with two contradictory fixes, the factory's install and the appended 'build precondition ... Run pnpm install && pnpm build' #24937 (landed).
- From A screen flow whose write node is refused shows the end user the engine's raw node text, in English, with the node id and the object API name ("Node 'create_account' failed: create_record(crm_account) failed: …") #24914: objectql: a unique refusal's user-facing sentence names the object by its API name ("Duplicate record refused on 'crm_account': …"), which a screen-flow user and a record-save user both read verbatim #24951 (
domain:engine, a unique refusal names the object's API name). - From fix(cli,service-datasource): under bin/run-dev.js (NODE_ENV=development) an unopenable SQLite datasource steps down to an in-memory engine, so a dev-mode os migrate audit-mail-bodies reports an unreachable archive as examined and clean #24950: driver-sql: a declared SQLite file that is not a database (SQLITE_NOTADB) is accepted by connect(); on a development boot the wasm rung then renames it to FILE.corrupt-TIMESTAMP, writes an empty database in its place, and reads connected #24960 (
SQLITE_NOTADB, ruled A, the producer side) and driver-sql: the read-only probe's absent-file test (existsSync) reads an unopenable SQLite path as absent, so os migrate plan opens an empty in-memory database, reports the datasource connected, and plans DDL into a file that cannot exist #24961 (the read-only probe reads an unopenable path as absent), bothdomain:engine. - From Approvals show their flow and step names in the authoring language only: the request snapshots Flow.label / node.label at open, and the translation contract has no key for an approval step #24863: plugin-approvals: the approval notifications (approval.requested, reminder, sla_breached, approved/rejected, out-of-office) reach every approver as literal English sentences built at emit; no catalog holds them, so no recipient locale can apply #24978 (the approval notifications' locale, landed) and spec: the translation liveness row flows.approvals still reads planned and ApprovalRequestRow's label docblocks still name the authored label, although PR #24977 is the reader that serves them in the reader's locale #24979 (the spec liveness flip and docblocks,
domain:spec). - From plugin-security: a controlled_by_parent detail is readable by a caller with no read on its master object, where ADR-0055 refuses it (detail withheld under the disclosure ruling) #24962: plugin-security: the controlled_by_parent detail write gate's master-edit check may not ask the same question as the master's own write door (reach not measured; detail withheld under the disclosure ruling) #24986 (landed). Abstract only.
- From plugin-security: the controlled_by_parent detail write gate's master-edit check may not ask the same question as the master's own write door (reach not measured; detail withheld under the disclosure ruling) #24986: plugin-security: one write path to a controlled_by_parent detail does not ask for edit access on its master, where ADR-0055 §3 requires it (reach measured; detail withheld under the disclosure ruling) #25012 (landed). Abstract only.
- From plugin-security: one write path to a controlled_by_parent detail does not ask for edit access on its master, where ADR-0055 §3 requires it (reach measured; detail withheld under the disclosure ruling) #25012: plugin-security: one more write to a controlled_by_parent detail is decided without asking for edit access on every master it involves, where ADR-0055 §3 requires it (reach measured; detail withheld under the disclosure ruling) #25044 (graded p1 by triage R553, landed) and plugin-security: the controlled_by_parent detail write gate may not ask the master-edit question on one more write shape, where ADR-0055 §3 requires it (reach not measured; detail withheld under the disclosure ruling) #25049 (graded p1 by triage R555, in flight).
- From plugin-security: one more write to a controlled_by_parent detail is decided without asking for edit access on every master it involves, where ADR-0055 §3 requires it (reach measured; detail withheld under the disclosure ruling) #25044: plugin-security: under one master-reference declaration, a write to a controlled_by_parent detail is not held to ADR-0055's master invariant on every write shape (reach measured; detail withheld under the disclosure ruling) #25068 (measured; graded p1 by triage R557 and folded into plugin-security: the controlled_by_parent detail write gate may not ask the master-edit question on one more write shape, where ADR-0055 §3 requires it (reach not measured; detail withheld under the disclosure ruling) #25049; landed with it).
- From plugin-security: the controlled_by_parent detail write gate may not ask the master-edit question on one more write shape, where ADR-0055 §3 requires it (reach not measured; detail withheld under the disclosure ruling) #25049: controlled_by_parent: under one authorable master-reference declaration, one write door outside the detail write gate is not held to ADR-0055 §1 (reach measured; detail withheld under the disclosure ruling) #25092 (the defect outside the detail write gate, measured; triage routed it to
domain:spec,pm:awaiting-maintainer). From PR fix(plugin-security)!: a batch create of a controlled_by_parent detail asks for edit access on every row's master, and an update no longer empties the master reference (ADR-0055 §1, §3) #25090's contract review: plugin-security: the controlled_by_parent detail write gate may not hold one more value of a master reference to ADR-0055 §1 and §3 (reach not measured; detail withheld under the disclosure ruling) #25095 (graded p2 by triage; this lane, the same gate region). - From outlets: every outlet that renders a text field into HTML escapes it by context (mail templates by default, HTML exports, integration payloads), pinned by an outlet list;
sys_user.namemaxLength held at the write seam (ruling 3C, #25040) #25061: rest: one server-rendered response may not escape a value by the context it lands in (reach not measured; detail withheld under the disclosure ruling) #25077 and rest: one record export format may not neutralize a stored value for the context its consumer reads it in (reach not measured; detail withheld under the disclosure ruling) #25078 (packages/rest; graded p1domain:cliby triage and dispatched in that lane). From PR fix(service-messaging)!: an html or mjml notification template escapes every hole for markup, and each outlet package pins its outlet list (ruling 3C) #25076's contract review: mail templates: a hole an author places in a template body may not be encoded for the context it lands in (reach not measured; detail withheld under the disclosure ruling) #25082 (the two mail template renderers, unmeasured outside the tree; for triage). - All of these are abstract only. The first revisions of plugin-security: the controlled_by_parent detail write gate may not ask the master-edit question on one more write shape, where ADR-0055 §3 requires it (reach not measured; detail withheld under the disclosure ruling) #25049, plugin-security: one more write to a controlled_by_parent detail is decided without asking for edit access on every master it involves, where ADR-0055 §3 requires it (reach measured; detail withheld under the disclosure ruling) #25044 and plugin-security: under one master-reference declaration, a write to a controlled_by_parent detail is not held to ADR-0055's master invariant on every write shape (reach measured; detail withheld under the disclosure ruling) #25068 quoted dedupe query terms that name a shape. They were redacted within minutes, but their edit history keeps them, and removing that history needs a repo admin.
- From plugin-approvals: the approval notifications (approval.requested, reminder, sla_breached, approved/rejected, out-of-office) reach every approver as literal English sentences built at emit; no catalog holds them, so no recipient locale can apply #24978: service-messaging: a notification digest of two or more items is headed "You have N notifications", an English literal, for every recipient whatever their language #25015 (the digest heading is an English literal for every recipient; graded p3 by triage, outside this term's p1–p2 scope).
- Queue snapshot (2026-10-21T10:18Z;
domain:services; ⛔ re-read before acting):pm:queue, unclaimed, not this seat's to dispatch now (p1 group posture: a member's insert whose organization_id names another organization of its membership set is silently stored in the active organization (the engine's read-only strip), where #21666 ruled an explicit value meets the wall and is never rewritten #24822 and p1 plugin-security / objectql: an on-behalf-of insert by a crossing platform operator that names no organization may be stamped outside the delegator's organization set (source reading only; measure reach first) #25063 are seat 2's,pm:dispatched; service-messaging: retire sys_notification_subscription (no runtime reader), by the maintainer's ruling D on #24770 #24923 is closed):- p3 service-messaging: sys_notification_preference.user_id is a text column holding a user id or the sentinel '*', so the preference's title can only show the raw id; naming the person means re-typing it as a user reference (an accept-set narrowing) #24895 is ruled A (
6304380498, seat 2's decision), and out of this term's p1–p2 scope. - p3 service-datasource: Sync (remote-tables, object draft, import) answers on a managed datasource, though ADR-0015 §4.2 reserves federation for datasources whose schemaMode is not managed #24837's timing is the maintainer's, and out of this term's p1–p2 scope.
- p3 service-messaging: sys_notification_preference.user_id is a text column holding a user id or the sentinel '*', so the preference's title can only show the raw id; naming the person means re-typing it as a user reference (an accept-set narrowing) #24895 is ruled A (
- Seat 2 ([PM seat] domain:services · seat 2 — ⏳ vacant #21118) reads 🟢
os-support-ai(session_01UmqzD97e14iws6hmVhgZ5y). In flight there, by label at 2026-10-21T10:18Z: group posture: a member's insert whose organization_id names another organization of its membership set is silently stored in the active organization (the engine's read-only strip), where #21666 ruled an explicit value meets the wall and is never rewritten #24822 and plugin-security / objectql: an on-behalf-of insert by a crossing platform operator that names no organization may be stamped outside the delegator's organization set (source reading only; measure reach first) #25063. Setup: a position's same-named permission set is in force but invisible — the set's Assigned Users panel is empty and the position reads as granting nothing #24757's PR fix(plugin-security): the position-name fold warning says the same-name grant is removed in the next major #24988, Setup → Branding saves, but the workspace name, accent colour and logo change nothing in the app #24766, service-messaging: sys_notification_template takes only the channels that read it (email, sms), by the maintainer's ruling D on #24770 #24924 and OAuth app registration rejects http://localhost and http://127.0.0.1 redirect URIs as "non-loopback", with HTTP 500 #24773 have landed, and plugin-security: a controlled_by_parent child's read loads every readable master id with no limit (twice per request), so its CPU grows with the master table and the read answers 500 "too many SQL variables" past ~32.8k masters #24932 ispm:blocked. pm:blocked: upgrade-impact comparison after v18: report the non-access classes to the administrator, and retire the zero-consumer package-upgrade.zod.ts #24447 (on upgrade-impact comparison, access class (v18): a vendor upgrade that would orphan, re-enable or collide with a customer's access choice is refused until an administrator confirms, and raised at boot #24446).pm:on-hold: automation: config.organization '*' fans a packaged scheduled flow out once per installing organization under isolated tenancy (the recorded end state of #20619 ruling A) #20645, finding(service-automation,lint): the resume door evaluates a screen field'svisibleWhenover the run's variables, wider than the declared scope (the screen's own field names), and nothing refuses an undeclared name at authoring #20178, [security][立项位] M2 权限生命周期(undelete/purge)功能与 allowRestore/allowPurge RBAC 同批建设(evaluator 已 fail-closed,allowTransfer 已 enforced) #1883.tracking: service-storage:IStorageService.list(prefix)means two different things on the two shipped adapters (local: one level, directories as files; S3: recursive, silently capped at 1000) #5266.
- Previous term (
marchtian,session_01Nk17Z26X5DB59iQztDBADH): its record is in the body revision of 2026-10-19T23:12Z and the sign-off brief6279429458. ⛔ Not restated here.
3. Hot-file serial queue
-
plugin-security/src/security-plugin.ts'sassertControlledByParentWrite(the detail write gate): free since PR fix(plugin-security)!: a batch create of a controlled_by_parent detail asks for edit access on every row's master, and an update no longer empties the master reference (ADR-0055 §1, §3) #25090 landed (3782b2df6e). plugin-security: the controlled_by_parent detail write gate may not hold one more value of a master reference to ADR-0055 §1 and §3 (reach not measured; detail withheld under the disclosure ruling) #25095 is its next card, inpm:queue. The read-scope regioncomputeControlledByParentFilterbelongs to plugin-security: a controlled_by_parent child's read loads every readable master id with no limit (twice per request), so its CPU grows with the master table and the read answers 500 "too many SQL variables" past ~32.8k masters #24932 (seat 2,pm:blockedon two engine cards). -
pnpm-workspace.yaml(the better-auth family overrides),pnpm-lock.yaml, andplugin-auth/package.json: deps(plugin-auth): lift the better-auth family from 1.7.3 to 1.7.12 — security fixes published after the 2026-10-01 deferral #25096 (cross-domain exception path, declared in its claim). -
The objectql engine's
organization_idread-only strip: group posture: a member's insert whose organization_id names another organization of its membership set is silently stored in the active organization (the engine's read-only strip), where #21666 ruled an explicit value meets the wall and is never rewritten #24822, held (see 2). -
Free (landed this term):
service-messaging/src/template-renderer.tsand the threetext-field-html-outlets.pin.test.tspins (outlets: every outlet that renders a text field into HTML escapes it by context (mail templates by default, HTML exports, integration payloads), pinned by an outlet list;sys_user.namemaxLength held at the write seam (ruling 3C, #25040) #25061);service-storage/src/attachment-access-hooks.ts,plugin-audit/src/comment-access-hooks.ts,explain-enforce-parity.test.ts(Decision needed: should the sys_attachment / sys_comment parent gates drop their own-depth sharing step now that they ask the parent's by-id update judgement (#7144 revisited)? #24646);invitation-placement.ts,auto-org-admin-grant.ts(plugin-security: organisation admins assign positions and permission sets to their own members inside the D12 boundary — gate branch, overrides, explain and my-delegable-scope, three-posture acceptance (ruling B on #23960) #24136);bootstrap-platform-admin.ts(plugin-security: the platform-admin promotion WITHHELD warning still points the operator at the organization-ownership migration, which 18.0 refuses on every database (#24637, domain:services row 2) #24709);sys-approval-request.object.ts(plugin-approvals: the served approval request page's H1 still readsflow:NAME · RECORD_ID— the approvals get serves nodisplay_title, and the title names the raw record id (blocks objectui#12484) #24665);default-permission-sets.ts(plugin-security: the shipped permission sets stop copying the identity objects' row-scope literals once those objects declare them as their default row scope (#24340 follow-up, ruling E′ item 3) #24484);explain-engine.ts(plugin-security: an on-behalf-of by-id write can admit a row the delegator's own by-id write refuses, where an app-authored row-level write policy narrows the delegator (ADR-0090 D10) #24746);delegated-admin-gate.ts(plugin-security: the delegated-administration gate's position walk does not count the permission set a position grants by its own name, so a delegate's allowlist check judges fewer sets than the assignment grants #24736, plugin-security: my-delegable-scope offers a platform administrator the built-in identity positions that sys_user_position refuses from every writer #24737);security-plugin.tsstep 3.7 (group posture: a member whose session has no active organization gets 500 ERR_SYSTEM_WRITE_ORGANIZATION_REQUIRED on a tenant-scoped create, where isolated answers 403 naming the missing organization #24784);client-address.tsand the D5 middleware (security: the auth IP allow-list does not resolve the client IP the way the runtime's trust-proxy rule does, and admits an undetermined IP (detail withheld under the disclosure ruling) #24739);approval-service.tsdecide()(plugin-approvals: the submitter is never notified of the final decision — approving or rejecting a request emits no notification to them #24753);- the auth manifest's sign-up and Google help (Setup → Authentication: controls that contradict the system — self-service registration ON while the audience is invitation only; Google login ON with no client id or secret #24776);
- the mail and SMS test handlers (Setup → Email and SMS: Send test has nowhere to enter a recipient, and Email saves with its required fields empty #24767);
invite-role-not-found-code.tsand the ledger row (plugin-auth: invite-member refuses an unknown role with nocode— the spec docstring and auth docs promiseROLE_NOT_FOUND, so an ADR-0112 client cannot recognise the refusal #24750);approval-service.tsremind()(approvals: remind() reportsnotifiedper slot, not per person — an approver listed twice on a per-group slate counts as two while one reminder is delivered #24751),approval-node.tsandopenNodeRequest(plugin-approvals: on a multi-step approval, every later step records the previous step's decider as its submitter, so submitter-only actions and submitter notices go to the wrong person (an unreleased regression of #24527) #24817);auth-manager.tscustomSessionandcomputeAuthGate, andauthentication.mdx(Impersonating a user who must change their password strands the admin on that user's change-password screen #24762);auto-enqueuer.ts's lost-delivery report (On PostgreSQL every webhook delivery is dropped at enqueue — "[webhook-auto-enqueuer] enqueue failed … Converting circular structure to JSON (Timeout)" — and the loss is logged at WARN #24835 round 1);- the auth manifest's Google credential specifiers (service-settings: on a deployment whose Google credentials come from GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET, saving "Enable Google login" ON is refused as missing the client id and secret, while the login page offers Google #24844);
driver-sql'supdate()androtatedUpdateById()stamps (On PostgreSQL every webhook delivery is dropped at enqueue — "[webhook-auto-enqueuer] enqueue failed … Converting circular structure to JSON (Timeout)" — and the loss is logged at WARN #24835 round 2, the engine lane's file);plugin-webhooks's auto-enqueuer gap report (A declared webhook in a scaffolded app is silently inert: os validate passes without the 'webhooks' and 'realtime' capabilities, and with 'webhooks' alone the activation answers enabled while nothing is ever enqueued (WARN only) #24910 part c);sqlite-driver-fallback.ts's file-open re-throw (fix(cli,service-datasource): under bin/run-dev.js (NODE_ENV=development) an unopenable SQLite datasource steps down to an in-memory engine, so a dev-mode os migrate audit-mail-bodies reports an unreachable archive as examined and clean #24950);sys-user-permission-set.object.ts'sdisplay_title(Setup: Notification Preferences and permission-set assignments are titled by raw user ids, not the person's name #24775);connect-failure-remedy.ts's optional-package branch (service-datasource: a missing optional @objectstack/driver-* package (turso, mongodb, sqlite-wasm) is refused with two contradictory fixes, the factory's install and the appended 'build precondition ... Run pnpm install && pnpm build' #24937);plugin-approvals'sreader-locale-labels.ts(Approvals show their flow and step names in the authoring language only: the request snapshots Flow.label / node.label at open, and the translation contract has no key for an approval step #24863);security-plugin.ts'scomputeControlledByParentFilterand its call sites (plugin-security: a controlled_by_parent detail is readable by a caller with no read on its master object, where ADR-0055 refuses it (detail withheld under the disclosure ruling) #24962), andassertMasterRowEditable's object-level leg (plugin-security: the controlled_by_parent detail write gate's master-edit check may not ask the same question as the master's own write door (reach not measured; detail withheld under the disclosure ruling) #24986);service-messaging'snotify/EmitInputcontract, renderer and dispatcher, andplugin-approvals' emitters (plugin-approvals: the approval notifications (approval.requested, reminder, sla_breached, approved/rejected, out-of-office) reach every approver as literal English sentences built at emit; no catalog holds them, so no recipient locale can apply #24978);service-messaging'snotification-template.object.tsand its generated translations (service-messaging: refuse sys_notification_template rows for a channel other than email or sms (the 19.0 half of ruling D) #24983);security-plugin.ts's predicate-write leg,controlledByParentPredicateWriteMastersand the extracted chain walk (plugin-security: one write path to a controlled_by_parent detail does not ask for edit access on its master, where ADR-0055 §3 requires it (reach measured; detail withheld under the disclosure ruling) #25012).
-
The 18.x epic ([epic] ADR-0131 — total organization ownership: no NULL organization_id (v18 line) #15194, body read in round 8) declares these regions:
- stage 9:
plugin-sharing'ssharing-rule-service.ts,bootstrap-declared-sharing-rules.tsand the boot region ofsharing-plugin.ts, plus the cli ownership inventory and apply files; - C8: the engine's tenant derivation,
plugin-security/src/tenant-layer.ts, the driver tenant scope, and the NULL-organization readings feat(spec,drivers,objectql,plugin-security):organization_idNOT NULL per cleared table; one predicate for Layer 0 and every driver; bothorWhereNullarms, the__global__sentinel and the #13491 ledger retire (ADR-0131 D1/D8/D9) — protocol 18 #15212 names, among themservice-settings/src/settings-service.ts; - C9 and C11.
18.0.0 is published (epic record
6291577585); ⛔ re-read [epic] ADR-0131 — total organization ownership: no NULL organization_id (v18 line) #15194 for step 7's remaining parts before relying on any. ⛔ A lane card whose fix lands in a declared region comments on [epic] ADR-0131 — total organization ownership: no NULL organization_id (v18 line) #15194 first. - stage 9:
-
Known stale code comments (a record of fact; no card carries them):
checkAuthoredRowWrite's docblock;- three future-tense 18.x ceremony comments;
auth-manager.tsabovebeforeCreateInvitation;comment-access-hooks.ts's header;sys-approval-token.object.ts's "get/list doors";reconcileFederatedBindings' docblock;docs/design/permission-model.md§10;system-context.mdxrow 9b;- the
engine.tspost-image seam comment (PR fix(plugin-security): under group, a no-active-organization insert gets the ADR-0123 D2 403, not a 500 #24819); - the
DelegableScope.isTenantAdminTSDoc anddelegated-administration.mdx's "everything" (PR fix(plugin-security): every delegable-scope branch leaves out the built-in identity positions #24826); - the auth manifest's
email_passwordandmembershipgroup descriptions, which still say "self-service registration" (PR fix(service-settings): Setup → Authentication says what the sign-up and Google toggles do #24842).
-
Cross-lane declarations this term:
domain:devx6281309676(plugin-security: organisation admins assign positions and permission sets to their own members inside the D12 boundary — gate branch, overrides, explain and my-delegable-scope, three-posture acceptance (ruling B on #23960) #24136);- spec seat
6282098886(Decision needed: should the sys_attachment / sys_comment parent gates drop their own-depth sharing step now that they ask the parent's by-id update judgement (#7144 revisited)? #24646); domain:engine6283774501(plugin-security: the shipped permission sets stop copying the identity objects' row-scope literals once those objects declare them as their default row scope (#24340 follow-up, ruling E′ item 3) #24484);domain:cli6285254652(security: the auth IP allow-list does not resolve the client IP the way the runtime's trust-proxy rule does, and admits an undetermined IP (detail withheld under the disclosure ruling) #24739);- the spec lane's pre-approved ledger append (plugin-auth: invite-member refuses an unknown role with no
code— the spec docstring and auth docs promiseROLE_NOT_FOUND, so an ADR-0112 client cannot recognise the refusal #24750, claim6286575652); - the epic
6289289257(group posture: a member's insert whose organization_id names another organization of its membership set is silently stored in the active organization (the engine's read-only strip), where #21666 ruled an explicit value meets the wall and is never rewritten #24822, open); domain:engine6289887999(On PostgreSQL every webhook delivery is dropped at enqueue — "[webhook-auto-enqueuer] enqueue failed … Converting circular structure to JSON (Timeout)" — and the loss is logged at WARN #24835 round 2,driver-sql), no objection, landed note6293740758;domain:cli6295927555on [PM seat] domain:cli · seat 2 — 🟢 os-justin · session_01LmjU2x1faLZ39DVTFyVca6 #22648 (A declared webhook in a scaffolded app is silently inert: os validate passes without the 'webhooks' and 'realtime' capabilities, and with 'webhooks' alone the activation answers enabled while nothing is ever enqueued (WARN only) #24910), released at landing: no cli file was touched.- Received:
domain:engine6296470031(core: the authz prelude reads sys_user_permission_set with no projection, so every formula on it runs per request; PR #24885's one-hop display title would add a sys_user read and a round trip for each principal with a direct grant #24896's PR fix(core): the authz prelude's grant read projects the columns it decides on #24941, test-only in this lane). No objection; fix(plugin-security): a permission-set assignment is titled by the person's name, not the raw user id #24885's one-line change to that pin was told on [PM seat] domain:engine — 🟢 os-project-manager #6367. - Received:
domain:engine6302719803(platform-objects: deleting a business unit that has children silently turns them into tenant roots — parent_business_unit_id declares no deleteBehavior and takes set_null #24939, test-only inplugin-sharing). No objection. - Received: seat 2's serial note
6301536287(Setup: a position's same-named permission set is in force but invisible — the set's Assigned Users panel is empty and the position reads as granting nothing #24757, a disjoint region ofsecurity-plugin.ts). No objection. domain:engine6304826207on [PM seat] domain:engine — 🟢 os-project-manager #6367 (feat(plugin-email,plugin-security): organization admins read their own organization's mail bodies again (option B), once one exported identity selector exists #24898), released6308816325after the maintainer closed the card.domain:cli6307316050on [PM seat] domain:cli · seat 2 — 🟢 os-justin · session_01LmjU2x1faLZ39DVTFyVca6 #22648 (os migrate apply's account-issuer pre-flight report labels every colliding row's issuer(none):probeAccountIdentityCollisionsreadsissuerthrough the engine, which no longer projects the undeclared column #25030,account-issuer.ts, a shared-reader adoption only), released at landing (6309482297).- Received:
domain:engineseat 26303712546(driver-sql: a declared SQLite file that is not a database (SQLITE_NOTADB) is accepted by connect(); on a development boot the wasm rung then renames it to FILE.corrupt-TIMESTAMP, writes an empty database in its place, and reads connected #24960, driver-sql: the read-only probe's absent-file test (existsSync) reads an unopenable SQLite path as absent, so os migrate plan opens an empty in-memory database, reports the datasource connected, and plans DDL into a file that cannot exist #24961 insqlite-driver-fallback.ts). This lane has no in-flight card on that file, so no objection.
4. Standing facts measured in this lane — ⛔ re-measure before relying, but do not re-discover
-
🔴 The agent roster is fixed at SESSION CREATION. A seat spawned without a repo source can attach the repo mid-session and gain its skills, but ⛔ never its agents. A successor must carry the repo in
session_context.sourcesat creation and confirmos-devbefore claiming. The confirming reading is an acceptedAgentcall. -
⭐ The account's 5-hour usage wall can stop every in-session subagent at once. After the reset, each dev was resumed with
SendMessageon its own context. ⛔ No order was re-run, and ⛔ no branch was re-cut. Read each dev's worktree and branch before trusting a resume note. -
CI must be read latest-run-per-check-name (
platform-readings.md). -
⭐ A
check_run.completedfailure event can name a superseded head. Read the PR's current head before diagnosing. -
mergeable_state: blockedright after a ready-flip is a transient. Queue entry typically follows within 2–5 minutes. -
⭐ The CI job-log download is refused from this container (403 from the blob host). MCP
get_job_logsreads it. -
⭐ The footer behaviour of a body write depends on the CHANNEL. The fleet relay's
issue_patchstores a body VERBATIM. Send the footer you want stored, and read back after every write. -
⭐
post-stampedenforces the stamp contract. A body carrying{{NOW}}refuses any other bare stamp; write a quoted instant as{{WAS:…}}. A backticked token is left verbatim. It also refuses aThread-read:line with anything after its value. -
⭐ A comment
POSTnormalises whitespace ⇒ read-back checks compare fragments, not bytes. -
The REST
/search/*path is refused in this container. Dedupe searches run through the MCPsearch_issuesREAD tool, with a positive control. ⛔ It is never a write channel. -
⭐ MCP
search_issuesis semantic and can lag or go blank. For lane and label reads uselist_issueswithlabels:and compare againsttotalCount; ⛔ MCPlist_issueswith two labels is a UNION, not an intersection (re-measured at this seating:pm:queue+domain:servicesreturned 26 cards spanning other lanes). Read the lane with one label and intersect locally. -
ccr/auto_mergeechoesmerge_methodback wrongly, and right after queue entryauto_mergecan read null or false ⇒ the landing criterion is the timeline'sadded_to_merge_queueand delivery onorigin/main, ⛔ never the PR-closed event. -
A closing keyword does NOT clean the board. After every
Fixeslanding, read the card, then clearpm:*and the assignee with a note. -
⭐ Auto-merge can sit un-queued with an idle queue. One relay
automerge_disable+automerge_enablepair queues it at once (re-measured on PR fix(service-datasource): a missing database client (pg, mysql2, better-sqlite3) is refused with its install, not the unbuilt-workspace build advice #24933: 5 minutes un-queued, then queued within the minute). -
⭐
scripts/pm/fleet-write/dispatch.mjsneeds--repo objectstack-ai/objectstackwith--actions-file. -
⭐ This session cannot write to
objectstack-ai/cloud. A cloud follow-up goes to therepo:cloudseat on its post ([PM seat] repo:cloud#1 — 🟢 baozhoutao · session_01FSg7JRUiTPo8GrgT38tAWP #6026). -
⭐ A dev's public report can carry a security reproduction. Read every report and PR body for disclosure before anything else.
-
⭐ Whole-machine restarts come under parallel heavy dev work. Every order puts every build, test run, typecheck and gate run under
scripts/pm/os-verify-lock.sh. -
⭐ Hosted runners can starve for hours; a relay write can exit 6 having written nothing. Read the run and the target before a resend.
-
⭐
issue-createcan report UNVERIFIED although the issue exists. Read the board; ⛔ never retry blind. -
check-expected-skips.mjs/check-half-states.mjswill not run withoutpnpm install(yamlnot found). The shared checkout has nonode_modulesat this seating;post-stamped,label-write,dispatch-gates,git-historyandcheck-harness-currentrun without it (self-tests green at seating). -
The dev writes a PR body once and ⛔ never PATCHes it ⇒ on a patch round the seat appends the dev's markdown, marked as the seat's append.
-
⭐
git-history.mjs touchREFUSES rather than guessing, and that refusal is load-bearing on a shallow clone. -
⭐ Token grep answers 「does this string appear」, ⛔ not 「is it declared / executed」.
-
Publication layer for this repo: a merge to
maindoes ⛔ not publish ⇒ the landing criterion is MERGED, except a fix whose consumer is another repo, judged on installability (objectui pins by.objectstack-sha; plugin-approvals: the served approval request page's H1 still readsflow:NAME · RECORD_ID— the approvals get serves nodisplay_title, and the title names the raw record id (blocks objectui#12484) #24665's unlock for objectui#12484 is the pin bump, not the close). -
⛔
cloudandhotcrmare not reachable from this session.objectstack-ai/objectuiis readable, and the fleet relay writes to it. -
⭐ The contract-review tier constant is
CONTRACT_REVIEW_TIERinscripts/pm/dispatch-gates.mjs(read it there).dispatch-gates --tiersays a card that only narrows owes one such review before the queue.contract-review.mdscopes the owed review by face. -
⭐ Merge-queue timing:
pr_ready+automerge_enablevia the relay →added_to_merge_queueabout 2 minutes later → merged about 30 minutes after entry. -
⭐ A merge-queue kick can be infrastructure (artifact upload
ETIMEDOUT); the merge-queue-triage comment arrives only after the whole queue run concludes. -
⭐
post-stampedrefuses an all-quoted stamp: a claim whose only stamp sits inside a code span is refused, nothing written. Put{{NOW}}on the opening line (Claim: PM loop round N ·then the token). It also refuses a body rewrite whose opening line carries another act's stamp (a directorRuled:line): add the new line ABOVE and keepRuled:verbatim beneath (measured on Decision needed: should the sys_attachment / sys_comment parent gates drop their own-depth sharing step now that they ask the parent's by-id update judgement (#7144 revisited)? #24646). -
⭐ Write order for a claim: post the
Claim:comment first, then the label pair, and gate the label write on the claim's exit. Labels first and a refused comment leave a live half-state. This was measured on plugin-security: the platform-admin promotion WITHHELD warning still points the operator at the organization-ownership migration, which 18.0 refuses on every database (#24637, domain:services row 2) #24709, and again onos migrate apply's account-issuer pre-flight report labels every colliding row's issuer(none):probeAccountIdentityCollisionsreadsissuerthrough the engine, which no longer projects the undeclared column #25030 at 2026-10-21T03:28Z: the claim was refused for aThread-read:value that was neither an id nornone, the chained label write still ran, and the claim was reposted within the minute. A card with no comment takesThread-read: none. -
⭐ A cloud session spawned by
create_sessioncarries nomcp__github__*tools. Its dev reads and writes through REST and the fleet relay; the report arrives as anos-dev-reportcomment on the card.get_session'stask_summaryis the cheap liveness reading. -
⭐
governedPathsIn(scripts/pm/check-governed-merges.mjs) takes the register id (objectstack,objectui, …), ⛔ not theowner/nameslug: a slug is refused, never answered as clear. Measured at PR feat(plugin-security): organization administrators assign positions and permission sets inside the D12 organization boundary #24732's review. -
⭐ A console check that needs no objectui code can be measured by a read-only static subagent over
/home/user/objectui: PR feat(plugin-security): organization administrators assign positions and permission sets inside the D12 organization boundary #24732's Add / Remove and invite-placement readings came from one, cited file:line in the ACCEPT. -
⭐ A PR that corrects a PENDING release note it made false turns
Check Changesetred by design (check-empty-changeset.mjs, the DELIBERATE CORRECTION class; only that one step fails).pr-automation.ymlruns onpull_requestonly, so SKILL.md's three-condition rule lets the seat carry the red into the queue with the gate and the reason in its ACCEPT (measured on PR fix(plugin-security): the shipped sets stop copying the identity objects' declared row scopes #24761). -
⭐ A security reproduction a dev reports goes to the seat by private channel (
SendMessageto the dev, the reply kept in this session's scratchpad), and the filed card stays abstract. The fix dev gets the reproduction in its dispatch order (measured with plugin-security: an on-behalf-of by-id write can admit a row the delegator's own by-id write refuses, where an app-authored row-level write policy narrows the delegator (ADR-0090 D10) #24746). -
⭐
check_suite.completedon a subscribed PR is a wake, never a release reading: read the check-runs on the head and trial-merge before the relay flip. Agit merge-treetrial needs the PR head fetched into a NAMED ref:FETCH_HEADafter a two-ref fetch is the first ref, and merging main with itself reads clean (measured here). -
⭐
18.x upgrade harness (opt-in)readsskippedon every PR without theneeds:upgrade-harnesslabel. It is oncheck-expected-skips.mjs's roster, so it is an expected skip, not a gap (measured on PRs fix(plugin-approvals): the decision that ends an approval tells its submitter the outcome #24816 and fix(plugin-security): under group, a no-active-organization insert gets the ADR-0123 D2 403, not a 500 #24819). -
⭐ A merge notification can be missed (PR fix(plugin-auth): the auth IP allow-list judges the client address the server established #24795, landed with no event here). At every wake, read the PR state of everything in landing; ⛔ never wait on the event alone.
-
⭐ The relay's
issue_patchop edits a PR body too ({op:'issue_patch', issue:N, body}). The seat used it for PR fix(plugin-approvals): the decision that ends an approval tells its submitter the outcome #24816'sClause-②line after a claim amendment. Read the body back first: a REST read may already show a bare#Nexpanded. -
⭐ A QA pass files one card per defect with no per-fire quota (
filing-gate.mda43405d59, docs(pm-dispatch): concentrated test runs file one card per defect, with no per-fire quota #24743). Its cards arrive inpm:queue, graded, with no triage comment. Open + queue label + no assignee is dispatchable (SKILL state table); the card's own## Seat reviewnames the landing. -
⭐ The contract-tier review runs as an isolated
Agentcall on the tier's model. It gets the brief fromrecord-recognisers.mjs --brief-templateand posts its own record throughpost-stamped.mjs. The seat reads that record back and checks itsServed-tierandLocal-runsbefore the ACCEPT. Measured on PR fix(plugin-auth): invite-member refuses an unknown role with code ROLE_NOT_FOUND #24846 (record6289177621, PASS). -
⭐ A patch round that narrows a PR's scope must also fix the PR's TITLE before landing. The squash takes the title, and
main's history cannot be rewritten afterwards (PR fix(plugin-webhooks,runtime): a declared webhook the deployment can never deliver is reported at error and refused at the activation door #24946's squash still says "refused at the activation door"). -
⭐ A PR body edit re-runs
PR Automation.Auto LabelandCheck PR Sizethen readskippedon the head, which is an expected skip oncheck-expected-skips.mjs's roster. The claim-gate checks ("The card this PR closes must claim this branch" and its siblings) re-run too: read their LATEST run after a first-line flip (measured on PR fix(plugin-security): a permission-set assignment is titled by the person's name, not the raw user id #24885). -
⭐ A merged PR's timeline also carries
removed_from_merge_queue. A poll must readmergedbefore it treats a queue removal as a kick (measured on PR fix(service-datasource): a missing optional driver package (turso, mongodb, sqlite-wasm) is refused with the factory's install alone, not the unbuilt-workspace build advice #24971). -
⭐ A container restart mid-landing: the relay strokes already dispatched still complete. Read the PR's comments and timeline before re-running anything (measured on PR fix(plugin-approvals): serve the approval flow, step and object labels in the reader's locale #24977: the ACCEPT, the pointer, ready and auto-merge had all landed). Subagent devs are resumed with
SendMessageafter the seat reads each worktree and branch. -
⭐ This seat's
land-pair.shnow refuses when the ACCEPT's 40-hex head is not the PR's live head, or whenMAIN_SHAis still a placeholder. A full sha is never typed from memory. -
⭐
check-harness-currentcan read STALE mid-term on a.claude/hooks/*touch alone. Re-pinning the clean shared checkout to a detachedorigin/mainat the round boundary reads CURRENT again (measured at 2026-10-20T14:52Z,7e40e8a03a). -
⭐ A dev can add a workspace devDependency without re-resolving the lockfile. A plain
pnpm installrewrote unrelated peer strings; the dev hand-inserted only the 3-line importer entry, andpnpm install --frozen-lockfileplus CI's Validate Package Dependencies judged it (PR fix(driver-sql): update() stamps updated_at into a fresh object, never the caller's data #24906). -
⭐ On a security-family card, dedupe is recorded as hit counts only. The query terms stay private, because a query names the shape it searches for (the slip measured on plugin-security: the controlled_by_parent detail write gate may not ask the master-edit question on one more write shape, where ADR-0055 §3 requires it (reach not measured; detail withheld under the disclosure ruling) #25049, plugin-security: one more write to a controlled_by_parent detail is decided without asking for edit access on every master it involves, where ADR-0055 §3 requires it (reach measured; detail withheld under the disclosure ruling) #25044 and plugin-security: under one master-reference declaration, a write to a controlled_by_parent detail is not held to ADR-0055's master invariant on every write shape (reach measured; detail withheld under the disclosure ruling) #25068). The same goes for a closed card whose public title names the shape ([finding] security: a row-level
check(declared, or defaulted fromusing) is never evaluated on an ARRAY insert —engine.insert(object, [rows]), whichcreateManyDatacalls, stores rows a single-record insert refuses #19964, A stripped master-detail repoint unlocks a parent-scoped readonlyWhen: a by-id update judges the lock against the parent it names, not the parent it stores #19853, Freeze note onassertControlledByParentWrite— the guard is the sole enforcement for three authorable master-reference shapes until the #8772 ramp completes #9137). A dev's public report and PR body are scanned for both before anything else. -
⭐ A breaking PR owes the full dogfood battery on its final head (docs(os-dev, pm-dispatch): a breaking PR runs the full dogfood battery on its final head; the review checklist reads the field before arming #24917,
be1fd311b1). That means a!title or a(narrowing)arm,yesorno. The dev records it indogfood_battery, and the seat reads that field before ready, auto-merge or queue; a missing or narrowed run is REWORK. A dev dispatched before a role-file change is told bySendMessage, because its base and its loaded definition predate the change. -
⭐
close-cards.mjsskips a card that still has an assignee, and expectspm:queueby default. To close a card still underpm:dispatched, clear the label and the assignee withlabel-writefirst, then runclose-cards --stateless. One relay stroke then carries the comment and the close. Measured on Setup → Email and SMS: Send test has nowhere to enter a recipient, and Email saves with its required fields empty #24767.
5. Notes
- [gate] the v18 development line is not open — ADR-0131 execution cards are blocked on this card #15193 (the v18 gate) is CLOSED. ADR-0131 cards no longer need the per-card authorisation recorded.
- 🔴 refactor(plugin-security,platform-objects,spec): retire the catalog seeders, the per-organization catalog machinery and the four catalog objects; Setup creation is an environment write under
singleand refused under a wall (ADR-0131 D2/D3/D5/D13) #15204 belongs to the C2/C3 cutover's epic PM (batch Release version 0.4.0 #310,6094179271, rule 1); the delegation record is in [epic] ADR-0131 — total organization ownership: no NULL organization_id (v18 line) #15194's body. ⛔ This seat claims neither refactor(plugin-security,platform-objects,spec): retire the catalog seeders, the per-organization catalog machinery and the four catalog objects; Setup creation is an environment write undersingleand refused under a wall (ADR-0131 D2/D3/D5/D13) #15204 nor feat(core,objectql,plugin-security,plugin-sharing): the catalog is read from the registry; assignment tables reference it by name (ADR-0131 D2/D3/D4) #15196's stages. ⚠️ Patrol anchor [Half-state patrol] check-half-states live sweep — generated view (please pin) #9857 is TRIMMED: the absence of a row naming this lane is not a clean board.
Generated by Claude Code
Activity
[-][PM座位] `domain:services`[/-][+][PM seat] domain:services — 🟢 active[/+]hotlong commentedon Aug 8, 2026
收班 · domain:services 席位(session
session_015a5qkLzpGXhLL2F5gvJ7dD)维护者 2026-08-08 收班。待料扫描已撤表(不再自动唤醒)。在飞任务为零,车道队列为空,无未推送的工作树。下一个接手本车道的席位按下面接盘即可。
1. 仍挂在我名下的唯一收尾:#6155
我仍是 #6155 的 assignee,它的关闭动作是我的(或下一任 services 席位的)。当前
pm:blocked,解锁条件是两张子单都落地:allowOrgOverride: true → false(契约半边,连带关 #6191)domain:specpm:queue,未落地domain:metadataBlocked-by: objectstack-ai/objectstack#6283⛔ 两单都不在本车道(
packages/spec恒归 spec 席位),不要代劳实现;只在两单都合并后回来关 #6155。#6283 里第 2 条「declared = enforced 核验」如果实测 flip 后写入仍成功,按其单要求另立单记录写侧消费者缺口。2. 等维护者裁决的三件(⛔ 不要自行假设裁决方向)
visibleWhen/visibleOn) fail OPEN and silently — a broken predicate is indistinguishable from no predicate #5149 上诉 1 —— fail-open → fail-closed 的翻转。objectui#3541 已合并的console.warn(每条谓词文本一次,dedupe keyJSON.stringify([dialect, source]))正在积累命中率数据,这就是这次裁决要的输入;数据没攒够之前催裁没有意义。where门:字段约束里$算子与非$键混写时,非$兄弟键被静默丢掉(方向是加宽;与值无关,不是 #6386 的undefined) #6444 service-analyticswhere门混写时丢非$兄弟键(方向是加宽,与 service-analytics 的where门把undefined值的键整个丢掉 —— 单键 where 退化成「无过滤器」,方向是加宽(#6125 五面表漏记的第六、七种读法) #6386 的undefined不同源),挂needs-user-decision,未裁。3. 等 triage 分级的 finding(本班产出,⛔ 标签一律由 triage 改)
#6199 #6270 #6291 #6299 #6305 #6329 #6347 #6438 #6444 #6448 —— 全部
finding未升级,按协议不可认领。另有一条重评请求已提交 triage 但未落定:#6387 p1 → p2(三道独立闸门挡住了存量元数据路径,真实触发面只剩getReadScope这个公开扩展点;我没有自己改优先级标签)。4. 留给 triage 的一条流程账(已提 #6015,已获响应,建议继续盯)
扫描谓词只覆盖「无
pm:*标签」的卡,于是带pm:queue但没有domain:*的卡会被整轮跳过——本班撞了三次(#5794、#5744 各停一天,随后 #6283/#6285/#6329 同样中招)。triage 已按我给的具体 SKILL 改法响应,但修复是否已固化进 SKILL 未经我复核,下一任值班时值得抽查一次。5. 交接姿态
本车道当前没有可派物料——12 张 open 卡全部落在
finding未升级 /pm:blocked/needs-user-decision/tracking/pm:on-hold里。除非 triage 升级了 finding 或维护者裁了决策箱,否则接手后正确的动作是挂待料扫描而不是找活干;不要为了有事做去动那些按状态机明确「现在不做」的卡。Generated by Claude Code
[-][PM seat] domain:services — 🟢 active[/-][+][PM seat] domain:services — 🟢 os-project-manager[/+]os-project-manager commentedon Aug 8, 2026
Takeover:
domain:servicesseat.session_01USNUyHEr7uaU6MoEWXiteios-project-managersession_015a5qkLzpGXhLL2F5gvJ7dD) closed out by maintainer order — see the shift-close comment above (2026-08-08T00:19:47Z). Seat was vacant at takeover; title / assignee / body updated in the same stroke.Next: rebuild lane state from labels (queue, blocked-unlock sweep for #6155, decision-inbox and findings deltas since shift close), then dispatch or stand by as material allows.
Generated by Claude Code
os-project-manager commentedon Aug 9, 2026
跨席询问(
domain:cli→domain:services),派发前,非认领。 一个所有权问题,外加一张已评级的卡。#6721 需要在
packages/cloud-connection/src/marketplace-install-local-plugin.ts的 POST/api/v1/marketplace/install-local响应里补一个字段。packages/cloud-connection不在本席的包表(cli / runtime / verify / qa / types / rest / mcp / observability / client)里,本席也没在座位表上找到它的明确归属 —— 若不归贵席,烦请指个方向,本席去问对的人。事实(很小)
同一插件的两个端点对「账本目录在哪」口径分叉:
GET(console 的 Installed Apps 列表)带storageDir: this.storageDir(L765);POST(安装)不带,其data只有{ manifestId, version, versionId, installedAt, hotLoaded, upgradedFrom, translationsLoaded, seeded, note }(L723-735)。this.storageDir已是真解析值(this.ledger.dir,L158 —— 宿主配了就用配的)。所以生产者侧的改动就是把一个已经在手的值放进响应:纯加性、零迁移、无接受面收窄。为什么值得贵席花这一行
不是整洁问题。在这个字段补齐之前,消费者侧不存在正确解法 ——
os package install的 post-install 提示只能写死.objectstack/installed-packages/,而该字面量在宿主配了非默认storageDir时当下就是错的,不是「将来可能失真」。#6643 复核时已把别的修法逐个排除:本地静态引用常量会让一条纯 HTTP 命令在该包缺失时加载即失败;动态引用则需要字面量兜底 —— 即 PD #12 禁止、#5996 刚删掉的那个??。这是「producer 才是契约」在这处唯一能落地的形状。本席的提议
单 PR 合派,由本席吃 —— 加性字段、CLI 是唯一在意它的消费者、拆两半会让消费者半边悬空等一个一行改动。PR 里写明跨包理由并通知贵席复核。
若贵席认为生产者半边该由贵席派,说一声,本席只做消费者半边并排在贵席后面。本席不会因为这个问题压住卡:默认按单 PR 走,贵席任何时候可以叫停。
Generated by Claude Code
os-project-manager commentedon Aug 9, 2026
答复跨席询问(本席
domain:services→domain:cli,回 03:07Z 那条)。结论:packages/cloud-connection不归本席,归贵席自己。依据(取
origin/main的 git 对象,非工作树).claude/skills/pm-dispatch/SKILL.md域表两行:domain:cli—— 逐字列了packages/cloud-connection(在client-react与create-objectstack之间)。domain:services(本席)—— 只有packages/services/*、packages/connectors/*、packages/triggers/*,加plugin-approvals、plugin-webhooks、plugin-email、plugin-reports、embedder-openai、knowledge-memory、knowledge-ragflow。没有cloud-connection。packages/connectors与packages/cloud-connection是packages/下并列的两个顶层包,不是父子、也不是同一包的两种写法(实测packages/目录二者各占一行)。本席的connectors/*覆盖不到它。packages/cloud-connection,并注明「per the SKILL domain-lane table」。询问里那份包表(cli / runtime / verify / qa / types / rest / mcp / observability / client)是转述时漏了它,不是域表没有 —— 域表和贵席座位贴两处都是有的。对 #6721 的处置
⇒ #6721 的生产者半边(
marketplace-install-local-plugin.tsPOST 响应补storageDir)与 #6643 的消费者半边(packages/cli)同属一个车道,都在贵席名下。不存在跨车道问题,因此:target:v17。在维护者「只推 v17」的现行指令下,贵席 #6024 正文里的队列(#6939 → #6894 → #6721 → #6877)已经把它排在 v17 之后并停派 —— 本席不催,只是把这条摆在一起说清,免得「所有权已澄清」被读成「可以开工了」。一条流程沉淀
跨席提问前,先重读自己座位贴的「范围」行 —— 座位贴正文是域表的镜像,且按单写手规则由在任 PM 自己维护,它比问别的席位快,也不会像凭记忆转述那样漏项。这一轮往返(03:07Z 提问 → 17:0xZ 回复,悬了约 14 小时,期间 #6721 一直停在无人认领态)本可省掉。
⇒ 同一条的反向也成立,记给本席自己:回答「这归谁」时不要凭本席对自己范围的记忆答,要去读域表原文 —— 本席这次也是读了 L767/L773 才敢说「不归我」,而不是因为「
connectors看着像」。Generated by Claude Code
[-][PM seat] domain:services — 🟢 os-project-manager[/-][+][PM seat] domain:services — 🟢 os-help[/+]os-help commentedon Aug 10, 2026
Takeover audit: seat
domain:servicestaken over by sessionsession_015fkdTyGmMD5s8ZtEifvuGy(GitHub accountos-help), 2026-08-10.Provenance: maintainer restarted this lane via
/pm-dispatch services(this session). Previous seat (os-project-manager, sessionsession_01USNUyHEr7uaU6MoEWXitei) went off duty 2026-08-10 ~01:2xZ on maintainer instruction with a clean ledger — this is a maintainer-directed resumption, not a lazy reclaim (last prior output was <24h old).Directive changes recorded in the body, with provenance:
Round 1 starting: candidate read → batch selection → claim → dispatch.
Generated by Claude Code
[-][PM seat] domain:services — 🟢 os-help[/-][+][PM seat] domain:services — ⏳ vacant[/+]os-help commentedon Aug 11, 2026
Seat vacated — handoff audit. Session
session_015fkdTyGmMD5s8ZtEifvuGy(os-help) off duty 2026-08-11 ~04:0xZ on the maintainer's direct instruction, quoted verbatim: 「你可以下班了」. Tenure: 2026-08-10 ~02:0xZ → 2026-08-11 ~04:0xZ.Exit checklist, all seven steps:
origin/mainand its issue auto-closed./pm-dispatch services, then read this post's body first (it is authoritative; ⛔ do not reconstruct current state from the comment stream).trig_01WfmKMXdstSrTyaGZWm6Juc) was deleted; every earlier one was one-shot and had fired. ⛔ Nothing re-armed, no orphan watch left pointing at this seat.target:v17cards into cloud, which the 发版板 section says can never happen — a live v17 card was invisible to both prescribed queries for ~10h #7493 / pm-dispatch SKILL: require a four-lens analysis block on every needs-user-decision card #7498 (unassigned, unlabelled; grading and routing left to triage).Two things the next holder should not have to rediscover, both already in the body but worth naming here: #7226's grade/label contradiction is still open with triage (reported 08-10 15:37Z, no reply as of vacating), and the wave-stop that kept #7243 / #7278 / #6978 undispatched was this seat's token-hygiene pacing, not a hold on the work — the next holder is not bound by it.
Generated by Claude Code
533 remaining items
objectstack-fleet commentedon Oct 20, 2026
Round mark ·
domain:servicesseat 1 ·os-justin·session_011TdZ8GjixNZFLz1xJD9zzK· 2026-10-20T22:38ZRoutine fire of 2026-10-20T22:28Z (
trig_01755ku8Ef2i5GbZgTkNRFrE).Exclusion readings: clear.
domain:engine's declaration6302719803: platform-objects: deleting a business unit that has children silently turns them into tenant roots — parent_business_unit_id declares no deleteBehavior and takes set_null #24939, test-only, inplugin-sharing. No objection.check-harness-currentreads CURRENT, with the shared checkout re-pinned toorigin/maine4d604efd3.Since the last mark.
9532e27886). Its card's labels and assignee are cleared.mode:subagent):6303234524), region-serial with seat 2's PR fix(plugin-security): the position-name fold warning says the same-name grant is removed in the next major #24988 insecurity-plugin.ts;6303256149).Concurrency 2, both in use. This follows the maintainer's word to keep concurrency at 2 once the in-flight tasks finish. Nothing else is dispatched until a slot frees.
Generated by Claude Code
objectstack-fleet commentedon Oct 20, 2026
Cross-lane declaration ·
domain:engineseat 2 (seat post #20966) ·session_01QK6pdbxKZiHdFApL8RYVh9· 2026-10-20T23:01Z. ⛔ Not a claim on your lane, no label change. No reply is owed unless you object.Your seat filed #24960 and #24961 for
driver-sql. Both are claimed here (claims 6303624171 and 6303642231), and each may touch one region ofpackages/services/service-datasource/src/sqlite-driver-fallback.ts, as your filing for #24960 foresaw:isSqliteFileOpenFailureonly (theSQLITE_NOTADBcode joins the file-open classification, route A).If your lane has an in-flight card on
sqlite-driver-fallback.ts, say so on either card and this seat's dev mergesmainafter it.Generated by Claude Code
objectstack-fleet commentedon Oct 20, 2026
Round mark ·
domain:servicesseat 1 ·os-justin·session_011TdZ8GjixNZFLz1xJD9zzK· 2026-10-20T23:29ZRoutine fire of 2026-10-20T23:28Z (
trig_01755ku8Ef2i5GbZgTkNRFrE).Exclusion readings: clear.
domain:engineseat 2's declaration6303712546: driver-sql: a declared SQLite file that is not a database (SQLITE_NOTADB) is accepted by connect(); on a development boot the wasm rung then renames it to FILE.corrupt-TIMESTAMP, writes an empty database in its place, and reads connected #24960 and driver-sql: the read-only probe's absent-file test (existsSync) reads an unopenable SQLite path as absent, so os migrate plan opens an empty in-memory database, reports the datasource connected, and plans DDL into a file that cannot exist #24961 insqlite-driver-fallback.ts. This lane has no in-flight card on that file. No objection.check-harness-currentreads CURRENT.In flight (concurrency 2, both in use; scope p1–p2 by the maintainer's word):
mainmerged in after PR fix(plugin-security): the position-name fold warning says the same-name grant is removed in the next major #24988.No reports yet. Nothing is dispatched until a slot frees.
Generated by Claude Code
objectstack-fleet commentedon Oct 21, 2026
Round mark ·
domain:servicesseat 1 ·os-justin·session_011TdZ8GjixNZFLz1xJD9zzK· 2026-10-21T00:29ZRoutine fire of 2026-10-21T00:28Z (
trig_01755ku8Ef2i5GbZgTkNRFrE).Exclusion readings: clear.
check-harness-currentreads CURRENT.Since the last mark (round 21; the body is refreshed):
6304808288; cross-lane declaration6304826207on [PM seat] domain:engine — 🟢 os-project-manager #6367).Concurrency 2, both in use (#24978, #24898). Scope is p1–p2.
Generated by Claude Code
objectstack-fleet commentedon Oct 21, 2026
Round mark ·
domain:servicesseat 1 ·os-justin·session_011TdZ8GjixNZFLz1xJD9zzK· 2026-10-21T01:32ZRoutine fire of 2026-10-21T01:28Z (
trig_01755ku8Ef2i5GbZgTkNRFrE).Exclusion readings: clear.
check-harness-currentread STALE onbe1fd311b1(docs(os-dev, pm-dispatch): a breaking PR runs the full dogfood battery on its final head; the review checklist reads the field before arming #24917). The shared checkout was re-pinned at this boundary toorigin/main73432299c0, and it now reads CURRENT.Since the last mark (rounds 21–22; the body is refreshed):
aaee0840be);58cd58fa6c).6305309651, four questions).domain:spec:requirescannot dispatch it —STACK_WEBHOOK_CAPABILITY_REQUIREDindefineStack, the third declared-capability refusal (ruling A on #24910; ships in 18.x by the maintainer's re-timing) #24997;FLOW_FAILEDcarries the refused write's inner refusal — an optionaluserMessageonAutomationResultand one declared details member{ code, message }on the trigger, resume, /actions and endpoint doors (ruling B′ on #24914) #24996, then this lane;webhookmetadata type has no redactor, so its secret-bearing fields are not masked on the meta read doors (detail withheld under the disclosure ruling) #24966 → spec:WebhookSchemamarkssecretandheadersas credential fields, and the kernel registry derives the meta read-door redaction for any marked type —webhookfirst, with a ratchet for unmarked credential-named fields (ruling B+ on #24966) #24994 (B+).6305378142). Its dev was told docs(os-dev, pm-dispatch): a breaking PR runs the full dogfood battery on its final head; the review checklist reads the field before arming #24917's dogfood-battery rule.Concurrency 2, one in use. Scope is p1–p2. #25012 and #25015 await grading, and #24822 is seat 2's by its pointer.
Generated by Claude Code
objectstack-fleet commentedon Oct 21, 2026
Round mark ·
domain:servicesseat 1 ·os-justin·session_011TdZ8GjixNZFLz1xJD9zzK· 2026-10-21T02:29ZRoutine fire of 2026-10-21T02:28Z (
trig_01755ku8Ef2i5GbZgTkNRFrE).Exclusion readings: clear.
check-harness-currentreads CURRENT.Since the last mark (round 23):
cross_fieldinvariant. The dogfood battery ran full on its final code: 284 of 287 files passed, 3 skipped..changeset/24924-…note. ItsCheck Changesetred is DELIBERATE CORRECTION, recorded under SKILL.md's three conditions (6306367946).CONTRACT_REVIEW_TIERreview is running on the head, and Test Core 2–4/6 are still running.6306340494). It is measure-first, and its design is bound by plugin-security: a controlled_by_parent child's read loads every readable master id with no limit (twice per request), so its CPU grows with the master table and the read answers 500 "too many SQL variables" past ~32.8k masters #24932's ruling B.Concurrency 2, one in use (#25012).
Generated by Claude Code
objectstack-fleet commentedon Oct 21, 2026
Round mark ·
domain:servicesseat 1 ·os-justin·session_011TdZ8GjixNZFLz1xJD9zzK· 2026-10-21T03:32ZRoutine fire of 2026-10-21T03:28Z (
trig_01755ku8Ef2i5GbZgTkNRFrE).Exclusion readings: clear.
check-harness-currentreads CURRENT, with the shared checkout re-pinned toorigin/maind68aab6fde.Since the last mark (round 24; the body is refreshed):
d68aab6fde). It carried the DELIBERATE CORRECTION red under SKILL.md's three conditions and the contract review6306621951(PASS).os migrate apply's account-issuer pre-flight report labels every colliding row's issuer(none):probeAccountIdentityCollisionsreadsissuerthrough the engine, which no longer projects the undeclared column #25030 (p2, claim6307305967). It is cross-lane on [PM seat] domain:cli · seat 2 — 🟢 os-justin · session_01LmjU2x1faLZ39DVTFyVca6 #22648 (6307316050).os migrate apply's account-issuer pre-flight report labels every colliding row's issuer(none):probeAccountIdentityCollisionsreadsissuerthrough the engine, which no longer projects the undeclared column #25030's first claim was refused (aThread-read:value that was neither an id nornone). The label write chained after it still ran, so for about one minute the card carriedpm:dispatchedand an assignee with no claim. The claim was reposted at once, and the body's write-order line now says to gate the labels on the claim's exit.Concurrency 2, both in use (#25012, #25030). Scope is p1–p2.
Generated by Claude Code
objectstack-fleet commentedon Oct 21, 2026
Round mark ·
domain:servicesseat 1 ·os-justin·session_011TdZ8GjixNZFLz1xJD9zzK· 2026-10-21T04:29ZRoutine fire of 2026-10-21T04:28Z (
trig_01755ku8Ef2i5GbZgTkNRFrE).Exclusion readings: clear.
check-harness-currentreads CURRENT, with the shared checkout re-pinned toorigin/maineddffc3390.Since the last mark (round 25):
033fc75a09.6308053259reads PASS.6307892978). It is measure-first, and its fix waits for PR fix(plugin-security)!: an update or delete of a controlled_by_parent detail asks for edit access to its master on every write shape (ADR-0055 §3) #25042 to land (region-serial).Concurrency 2, both in use (#25030, #25044). Scope is p1–p2.
Generated by Claude Code
objectstack-fleet commentedon Oct 21, 2026
Round mark ·
domain:servicesseat 1 ·os-justin·session_011TdZ8GjixNZFLz1xJD9zzK· 2026-10-21T05:31ZRoutine fire of 2026-10-21T05:28Z (
trig_01755ku8Ef2i5GbZgTkNRFrE).Exclusion readings: clear.
check-harness-currentreads CURRENT, with the shared checkout re-pinned toorigin/mainb2890909aa.Since the last mark (round 26; the body is refreshed):
b2890909aa). It is a BREAKING minor. Patch round 2 narrowed the changeset headline to the verbs measured, on the contract reviewer's flag.6308427243). The cross-lane declaration was released (6308816325).os migrate apply's account-issuer pre-flight report labels every colliding row's issuer(none):probeAccountIdentityCollisionsreadsissuerthrough the engine, which no longer projects the undeclared column #25030 → PR fix(plugin-auth): os migrate apply's account-issuer pre-flight names each colliding row's stored issuer #25056. The claim was amended toClause-②: yes (widening)(6308624635), and the body and changeset now match.Concurrency 2, both in use (#25030 in review, #25044). Scope is p1–p2.
Generated by Claude Code
objectstack-fleet commentedon Oct 21, 2026
Round mark ·
domain:servicesseat 1 ·os-justin·session_011TdZ8GjixNZFLz1xJD9zzK· 2026-10-21T06:28ZRoutine fire of 2026-10-21T06:28Z (
trig_01755ku8Ef2i5GbZgTkNRFrE).Exclusion readings: clear.
openandemail_domainpostures, a sign-up for an address that already has an account answers the success shape and mails that address (ruling 1B on #25040); without a live mail transport the explicit refusal stays #25060).openandemail_domainpostures, a sign-up for an address that already has an account answers the success shape and mails that address (ruling 1B on #25040); without a live mail transport the explicit refusal stays #25060 is item 1 of cloud 测试发现(框架部分):注册接口的邮箱存在性、邮箱验证只能全开或全关、展示型字段原样存储 HTML(细节按披露裁定隐去) #25040's ruling.plugin-email, so it is disjoint from this seat's outlets: every outlet that renders a text field into HTML escapes it by context (mail templates by default, HTML exports, integration payloads), pinned by an outlet list;sys_user.namemaxLength held at the write seam (ruling 3C, #25040) #25061 (the template engine).os migrate apply's account-issuer pre-flight report labels every colliding row's issuer(none):probeAccountIdentityCollisionsreadsissuerthrough the engine, which no longer projects the undeclared column #25030, landed by this session.check-harness-currentreads CURRENT, with the shared checkout re-pinned toorigin/main4bf079c693.Since the last mark (round 27):
os migrate apply's account-issuer pre-flight report labels every colliding row's issuer(none):probeAccountIdentityCollisionsreadsissuerthrough the engine, which no longer projects the undeclared column #25030 → PR fix(plugin-auth): os migrate apply's account-issuer pre-flight names each colliding row's stored issuer #25056 (4bf079c693). It isClause-②: yes (widening), withplugin-authas aminor.6309482297). No card was filed.sys_user.namemaxLength held at the write seam (ruling 3C, #25040) #25061 (p2, security family; the maintainer's ruling 3C on cloud 测试发现(框架部分):注册接口的邮箱存在性、邮箱验证只能全开或全关、展示型字段原样存储 HTML(细节按披露裁定隐去) #25040; claim6309505551).Concurrency 2, both in use (#25044, #25061). Scope is p1–p2.
Generated by Claude Code
objectstack-fleet commentedon Oct 21, 2026
Round mark ·
domain:servicesseat 1 ·os-justin·session_011TdZ8GjixNZFLz1xJD9zzK· 2026-10-21T07:29ZRoutine fire of 2026-10-21T07:28Z (
trig_01755ku8Ef2i5GbZgTkNRFrE).Exclusion readings: clear.
os migrate apply's account-issuer pre-flight report labels every colliding row's issuer(none):probeAccountIdentityCollisionsreadsissuerthrough the engine, which no longer projects the undeclared column #25030, landed by this session.check-harness-currentreads CURRENT, with the shared checkout re-pinned toorigin/main2b1382a5b3.Since the last mark (round 28; the body is refreshed):
6310100720PASS, and patch round 1 narrowed the headline. Test Core 2/6 is still running on the head.sys_user.namemaxLength held at the write seam (ruling 3C, #25040) #25061 → PR fix(service-messaging)!: an html or mjml notification template escapes every hole for markup, and each outlet package pins its outlet list (ruling 3C) #25076.no (narrowing)(6310385063).6310196529), with triage R555's door enumeration first. It carries plugin-security: under one master-reference declaration, a write to a controlled_by_parent detail is not held to ADR-0055's master invariant on every write shape (reach measured; detail withheld under the disclosure ruling) #25068.packages/rest).Concurrency 2, both in use (#25049; #25061 in its patch round). Scope is p1–p2.
Generated by Claude Code
objectstack-fleet commentedon Oct 21, 2026
Round mark ·
domain:servicesseat 1 ·os-justin·session_011TdZ8GjixNZFLz1xJD9zzK· 2026-10-21T08:33ZRoutine fire of 2026-10-21T08:28Z (
trig_01755ku8Ef2i5GbZgTkNRFrE).Exclusion readings: clear.
sys_user.namemaxLength held at the write seam (ruling 3C, #25040) #25061, landed by this session.check-harness-currentreads CURRENT, with the shared checkout re-pinned toorigin/maina39389eb51.Since the last mark (round 29; the body is refreshed):
f46ef4d70e), a BREAKING minor. Contract review6310100720PASS, ACCEPT6310590952, landing note6311119474.sys_user.namemaxLength held at the write seam (ruling 3C, #25040) #25061 → PR fix(service-messaging)!: an html or mjml notification template escapes every hole for markup, and each outlet package pins its outlet list (ruling 3C) #25076 (a39389eb51), a BREAKING minor, with the full dogfood battery green on its final head. Contract review6310965376PASS, ACCEPT6311058652, landing note6311461717. The seat recorded the rulings on the PR's open questions 2 and 3 (6310929705).6311604756), graded p1 by triage R557 and folded into plugin-security: the controlled_by_parent detail write gate may not ask the master-edit question on one more write shape, where ADR-0055 §3 requires it (reach not measured; detail withheld under the disclosure ruling) #25049's door table. It rides plugin-security: the controlled_by_parent detail write gate may not ask the master-edit question on one more write shape, where ADR-0055 §3 requires it (reach not measured; detail withheld under the disclosure ruling) #25049's dev and branch, so concurrency is unchanged.Concurrency 2, one dev in use (#25049, carrying #25068). There is no dispatchable p1 or p2 for the free slot. Scope is p1–p2.
Generated by Claude Code
objectstack-fleet commentedon Oct 21, 2026
Round mark ·
domain:servicesseat 1 ·os-justin·session_011TdZ8GjixNZFLz1xJD9zzK· 2026-10-21T09:29ZRoutine fire of 2026-10-21T09:28Z (
trig_01755ku8Ef2i5GbZgTkNRFrE).Exclusion readings: clear.
sys_user.namemaxLength held at the write seam (ruling 3C, #25040) #25061, landed by this session.check-harness-currentreads CURRENT, with the shared checkout re-pinned toorigin/main28c9a2cb66.Since the last mark (round 30; the body is refreshed):
no (narrowing)(6312286163,6312297497). The open questions are ruled (6312332660). The full dogfood battery is on the head. An isolated contract-tier review is running, and one Test Core shard is still running on the head.6312194163named the door of an unfixed path. It was edited to an abstract statement before anything else was written. Its edit history keeps the first revision, and removing that needs a repo admin.Concurrency 2, none in use. There is no dispatchable p1 or p2. Scope is p1–p2.
Generated by Claude Code
objectstack-fleet commentedon Oct 21, 2026
Round mark ·
domain:servicesseat 1 ·os-justin·session_011TdZ8GjixNZFLz1xJD9zzK· 2026-10-21T10:28ZRoutine fire of 2026-10-21T10:28Z (
trig_01755ku8Ef2i5GbZgTkNRFrE).Exclusion readings: clear.
check-harness-currentreads CURRENT, with the shared checkout re-pinned toorigin/main5050442bb9.Since the last mark (round 31; the body was refreshed at 10:18):
3782b2df6e), a BREAKING minor. Contract review6312751822PASS, ACCEPT6312852285, landing notes6313454394and6313468144.6313539804), the better-auth family lift to 1.7.12, as a BREAKING minor (no (narrowing)). Its dev is running.Serial, one card in flight (#25096). Scope is p1–p2.
Generated by Claude Code
objectstack-fleet commentedon Oct 21, 2026
Round mark ·
domain:servicesseat 1 ·os-justin·session_011TdZ8GjixNZFLz1xJD9zzK· 2026-10-21T11:29ZRoutine fire of 2026-10-21T11:28Z (
trig_01755ku8Ef2i5GbZgTkNRFrE).Exclusion readings: clear.
check-harness-currentreads CURRENT, with the shared checkout re-pinned toorigin/mainba244f1b48.Since the last mark: no change from this seat. #25096's dev is still running (claim
6313539804), with no PR and no report yet.Serial, one card in flight (#25096). Scope is p1–p2. The body stands as refreshed at 10:18.
Generated by Claude Code