Repository navigation
Closed
Labels
area:studioChanging a running app without code — authoring, publish, docs and the portalChanging a running app without code — authoring, publish, docs and the portaldomain:specenhancementNew feature or requestNew feature or requestpriority:p1High: required for production / M2High: required for production / M2
Description
domain:spec#2 · os-steve · session_01ADHkmSduNGC2SZXszyrNut
Part-of #28722
Ruled: 6566915346 · letter E · 2026-11-02T01:30Z
Ruling-ref: 6566915346
Re-cut as the domain:spec p1 slice (spec seat 2, 2026-11-02T12:21Z), as the ruling's Execution line orders: "this card is re-cut as the domain:spec p1 slice (Part-of #28722, Ruling-ref: naming this comment)". The original domain:ui#3 body (the served nav owner-stamp ask, with its measure) is the prior revision of this body; the measure and the options are in comments 6556726236, 6556991855, 6559222926 and 6566865190.
What the ruling binds (letter E, quoted from 6566915346)
- "
GET /packages/:id/customizationscontributions(packages/spec/src/api/package-lifecycle.zod.ts:406, PR feat(runtime): the per-base customizations read names the package behind each field and flow another package contributes #28749) gainskind: 'nav'. A nav entry names the base-ownedappit was contributed to, thegroupwhen the contribution targets one, the nav item's id as itsname, andpackageId; the entry shape is per kind (objectforfield/flow,app+ optionalgroupfornav), spelled by the spec card.counts.contributionskeeps counting items." - "Served from the same
appNavContributionsregistry the fold reads … never by a client-side join on names. A disabled package's contributions are not listed (packages: an admin cannot disable a type:module sub-package of an installed app (422 WRITABLE_PACKAGE_REQUIRED), and a disabled package's nav contributions stay in the app #28117); the base and its<base>.custompair are not contributions, as the member already says." - "No key is added to any nav item: the served app's
navigationstays as declared andBaseNavItemSchemastays strict. NonavContributorsmap on the item read." - "This is a protocol addition:
Clause-②: yes (widening),Metadata-protocol: added, spec slice atCONTRACT_REVIEW_TIER."
This card (spec slice)
GetPackageCustomizationsResponseSchema.contributions(packages/spec/src/api/package-lifecycle.zod.ts) gains thenavkind with a per-kind entry shape; the member's and the schema's describes name the third kind and its ordering; a liveness row and the docs pages that list the member.- Declared ahead of its producer: until the server slice serves it, the
navarm says so in its describe (no served key without a reader of record, ADR-0049).
Not this card
domain:server: runtime: a served read naming which package contributes to an installed base — extension fields, flows on its objects, navigation entries — so Studio can draw contributed items greyed with their source (ADR-0029 D7, ADR-0146 D3) #28722 Wanted 3,readBaseContributionsreads theappNavContributionsregistry (server seat 3, after this lands).domain:ui: drawing the contributed entries greyed with the package label (Setup and Studio: suggestions from a full HotCRM browser pass on 18.2.0: user onboarding, packaged automation state, run-now for scheduled flows, admin lists, and Studio entry, field table, flow inspector wording and one designer per item #27356 row 20), filed by ui seat 4 after the server slice.
Metadata
Metadata
Assignees
Labels
area:studioChanging a running app without code — authoring, publish, docs and the portalChanging a running app without code — authoring, publish, docs and the portaldomain:specenhancementNew feature or requestNew feature or requestpriority:p1High: required for production / M2High: required for production / M2
Activity
objectstack-fleet commentedon Oct 30, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: p3 ·
domain:server·area:studio· first touch (retriage) · 2026-10-30T11:02Z⛔ Not a claim. This first touch was owed: a filer's labels with no triage audit.
packages/objectql/src/registry.ts, so the server lane stands. If serving the contributing package beside each folded nav entry is a new served key, it is a protocol addition and comes back here before code. p3, not dispatched on its own.pm:retriageremoved.Generated by Claude Code
objectstack-fleet commentedon Nov 1, 2026
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH
Claim: PM loop round 1 · card thread · 2026-11-01T10:24Z
Session:
session_01FEkQ5kE5BrPUPNMMyv6oCH(the seat); the card thread issession_01FEkQ5mmZYpLmZVtuxRHzKCAccount:
os-project-manager(the seat's linked user; the card's assignee)Branch:
claude/project-thread-tt1ra6(the card thread's harness-pinned branch; it names no issue, so this claim is the identity record)Worktree: the card thread's own container checkout
Domain:
domain:serverSeat:
domain:server#3Ruling-ref: the maintainer, 2026-11-01T03:46Z: 「server 车道现在就是你负责,任务有一大堆啊,都可以派,包括 p3」, with 2026-10-26T10:29Z 「p1 p2 处理完了,就可以处理 p3」, and 2026-11-01T06:39Z 「server 队列还是很多任务,再开一个席位吧」. Leehom 2026-11-01T10:18Z: every graded
pm:queue+domain:servercard is dispatchable. Triage6521106045binds: a new served key comes back to triage before code.File surface:
packages/objectql/src/registry.ts(applyNavContributions), the served app read tests, and a changeset, ONLY if the measure finds the owner stamp already declared. ⛔ Notpackages/spec.Container & model:
S(p3),mode:thread,model: opus(--tiernames no path mandate: PM's call, default),effort: highClause-②: no — expected only if the served nav item shape already declares an owner stamp; if the stamp is a new served key, the dev stops with
needs_decisionand the card goes back to triage as triage6521106045says.Metadata-protocol: none (expected; the dev measures and declares)
Responsibility: the code is the registry fold of
navigationContributions· the platform path is the served app read · reached by a Studio author whose nav groups are filled by other packages and show "No items in this package"Thread-read: 6521106045
Premise: holds (card body:
applyNavContributionsdropspackageId); measure-first on the spec question before any codeSerial constraints cleared: none: no open PR found on
applyNavContributionsat this read; the dev re-reads overlap at start and beforepr_create.Resume-from: none — fresh from
origin/mainState: →
pm:dispatched, assigned toos-project-manager, recorded by this claim. Order:pm-orders/server/order-27928.md(project folder).objectstack-fleet commentedon Nov 1, 2026
domain:server#3 · os-project-manager · session_01FEkQ5mmZYpLmZVtuxRHzKC
os-dev-report
{
"issue": 27928,
"status": "needs_decision",
"branch": "claude/project-thread-tt1ra6",
"pr": null,
"session": "session_01FEkQ5mmZYpLmZVtuxRHzKC",
"premise_still_valid": true,
"summary": "Measured on origin/main a798ae8, read-only, no code. The premise holds:
SchemaRegistry.registerAppNavContributionkeepspackageIdper contribution (packages/objectql/src/registry.ts:7240) andapplyNavContributions(registry.ts:7267-7307) pushesc.itemsinto the group or top level unchanged, so the served app cannot say who contributed an entry. The served nav item shape does NOT admit an owner stamp: every nav branch is astrictObjectoverBaseNavItemSchema(packages/spec/src/ui/app.zod.ts:303; keys id, label, icon, order, badge, badgeVariant, visible, dataSource, requiredPermissions, requiresObject, requiresService), the separator branch declares only type/id/order (app.zod.ts:842), andMetadataProtectionFields(_packageIdat packages/spec/src/kernel/metadata-protection.zod.ts:117) is spread only at the AppSchema level (app.zod.ts:2119). No passthrough exists either:getAppNavContributions(registry.ts:7252) has zero non-test readers, and no served key names a contributor. So any stamp on the entry or beside the item is a spec addition; per the order and triage 6521106045 this stops before code and goes back to triage.","tests": "n/a — measure-first reading, no code, no build. Readings are git show / git grep on origin/main a798ae8 (shallow checkout; no ancestry claims made).",
"gates": "n/a — no diff, so
dispatch-gates --commandsderives nothing and no gate ran.","dogfood_battery": "n/a — no PR",
"mcp_calls": "5 — mcp__github__issue_read x5 (get #27928 x1, get_comments #27928 x4, incl. reading claim 6556692704 which names this branch), all reads, no write tool",
"api_writes": "1 — POST issues/27928/comments (this os-dev-report, via scripts/pm/post-stamped.mjs)",
"open_questions": [
{
"question": "Where should the served answer name the package that contributed each folded nav entry? Every option is a spec addition except C and D. Measured facts the options rest on: (1) a stamped key inside a nav item would be REFUSED by the app's own schema on any parse, because
Registry.validate('app')runsAppSchema.parse(registry.ts:6185) and the save door answers 422 on an off-spec body; (2) Studio edits the layeredeffectivebody (ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx ~4572,client.layered('app', name)), which carries no contributions, and reads the served, folded answer only throughshellClient.list('app'); (3)GET /packagesalready serves each package'smanifest(packages/runtime/src/domains/packages.ts:316-317) includingnavigationContributions, plusenabled; (4) metadata-protocol folds on both reads (packages/metadata-protocol/src/protocol.ts:10449 list, :11590 by-name). Producers measured: 16 non-test source files declarenavigationContributions(packages/apps/setup, cloud-connection x2, mcp connect-ui, plugin-approvals/audit/auth/security/sharing/webhooks, service-automation/datasource/messaging/settings, examples/app-multi-package x2) and hotcrmobjectstack.config.ts. Reader today: none; the Studio half (#27356 row 20) is the named reader, filed after this lands.","options": [
"A — stamp on the entry: declare a machine-managed optional
_packageId(string) onBaseNavItemSchemaand the separator branch in packages/spec/src/ui/app.zod.ts, and haveapplyNavContributionsset it on each folded item fromc.packageId; the app's own items stay unstamped (the app's_packageIdalready names them). Owes: the liveness row (packages/spec/liveness/app.jsonnavigation),Metadata-protocol: added, and a save-door rule refusing the key on authored nav items, because_-prefixed keys are skipped by the authoring-key lint (packages/spec/src/data/authoring-key-lint.ts:264) and an AI copying a served app into source would otherwise author it silently. Work: M (spec + objectql + save door + tests).","B — serve it beside the item: add an optional
navContributorsrecord (nav item id to package id) toGetMetaItemResponseSchema(packages/spec/src/api/protocol.zod.ts:712), thedisabledActions/cascadeDeleteObjectsshape, present only on anappread and absent on a draft read; the registry returns the map from the same fold, metadata-protocol carries it on the by-name read, the rest cached arm folds it into the ETag. The authoring schema is unchanged. Studio readsGET /meta/app/:nameinstead of the list row for this. Metadata-protocol: none to my reading (a response envelope key nobody authors); the seat should confirm against the level table. Work: M (spec api + objectql + metadata-protocol + rest cached arm + tests).","C — no server change: the Studio card joins the served app with
GET /packagesmanifests (navigationContributions[].itemsby id, skipping packages withenabled: false). Zero spec. Costs: a second copy of the fold's ownership logic in ui (the #28117 disabled-package rule and any future rule must be mirrored), and I found no check that nav ids are unique across contributing packages into one app (unverified), so a join by id can be ambiguous. This card closes as not needed and the work moves to adomain:uicard.","D — do not build now: p3, zero reader today; close not planned (or on-hold with a Restart-when on the Studio row being ruled)."
],
"recommendation": "B. 长远合理性(权重最高):fold 是唯一生产者,它本来就握着 packageId,B 让同一个生产者在 API 信封里说出这个派生事实,沿用 disabledActions / cascadeDeleteObjects 的「beside item, never inside it」先例,作者可写的 nav schema 一个键都不加;C 在 ui 端复制一份 fold 的归属逻辑,正是 lint 注释里点名的漂移来源。防 AI 写错:A 把一个
_键加进作者 schema,而 authoring-key lint 跳过_前缀,AI 从 served app 抄回源码时会静默通过,还要另加一条保存门拒收;B 不增加任何可写面;C 的消费端推导出错时静默。实际业务需求:拉动是真的但还未兑现,16 个生产者文件把条目塞进 setup 和 HotCRM 的分组,Studio 在这些分组上显示「这个软件包里没有条目」(#27356 第 20 行实测);读者是随后的 ui 卡,今天零读者。创业阶段不扩散:D 最省,C 零 spec,B 只加一个可选响应键,A 最重(作者 schema + 保存门)。有实测拉动 ⇒ 荐长远形态一次付清,故荐 B;若维护者认为 p3 不值一个协议键,次选 D 而不是 C。"}
],
"out_of_scope_findings": []
}
Generated by Claude Code
objectstack-fleet commentedon Nov 1, 2026
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH
Release: claim
6556692704(session_01FEkQ5kE5BrPUPNMMyv6oCH, card threadsession_01FEkQ5mmZYpLmZVtuxRHzKC, branchclaude/project-thread-tt1ra6) · 2026-11-01T10:28Z · measure-first ended atneeds_decision, no codeProduce: none (no commit on the branch; os-dev-report 6556726236)
Resume-from: none — fresh from
origin/mainonce a ruling picks an optionorigin/maina798ae8f): every nav item branch is a strict object overBaseNavItemSchema(packages/spec/src/ui/app.zod.ts) with no owner key, and nothing passes one through. Any owner stamp is a new served key, so per triage6521106045the card comes back before code._packageIdon each entry; B serve anavContributorsmap beside the item in the item read (thedisabledActionsshape); C Studio joins theGET /packagesmanifests, no server change; D do not build. The dev recommends B, then D.pm:dispatched→pm:retriage, assignee cleared. The maintainer is asked for the ruling in the seat's thread; a B or A ruling makes it a spec-lane card at p1 under 「协议新增定 p1」.8 remaining items
objectstack-fleet commentedon Nov 2, 2026
domain:server#3 · os-steve · session_01ADHkmQJdgarUjPLNgFBY67
Exit stroke · #27928 · 2026-11-02T12:18Z
Ruling-ref: director record
6566915346(batch #451 item 2, letter E, maintainer 「同意」 2026-11-02T01:29Z); the director's notify on the server seat 3 mailbox #29125 (6576895608) names this stroke as owed by the lane.needs-user-decision→pm:queue. The ruling is made, so the card is ready to work.domain:server→domain:spec. Priority:priority:p3→priority:p1. Both come from the record itself: "per 「协议新增定 p1」 this card is re-cut as thedomain:specp1 slice (Part-of #28722)". The seat is applying the ruling's grade here, not grading the card itself.contributionsmember gainskind: 'nav'withapp, an optionalgroup,nameandpackageId; a liveness row; docs;Part-of #28722; and aRuling-ref:naming6566915346. Declaration:Clause-②: yes (widening),Metadata-protocol: added, contract review atCONTRACT_REVIEW_TIER.readBaseContributionsreads theappNavContributionsregistry. runtime: a served read naming which package contributes to an installed base — extension fields, flows on its objects, navigation entries — so Studio can draw contributed items greyed with their source (ADR-0029 D7, ADR-0146 D3) #28722 stayspm:blockeduntil then.objectstack-fleet commentedon Nov 2, 2026
domain:spec#2 · os-steve · session_01ADHkmSduNGC2SZXszyrNut
Claim: PM loop round 1 · 2026-11-02T12:26Z
Session:
session_01ADHkmSduNGC2SZXszyrNut(seat); dev = card threadsession_01ADHkmQ28WWiNo3u94yGTPbAccount:
os-steveBranch:
claude/project-thread-845vdnWorktree: the card thread's own checkout of
objectstack-ai/objectstackDomain:
domain:specSeat:
domain:spec#2File surface:
packages/spec/src/api/package-lifecycle.zod.ts(GetPackageCustomizationsResponseSchema.contributionsgains thenavkind, per-kind entry shape, describes and docblock) and its tests; the liveness row and the docs pages that list the member; regenerated references; root.changeset/; narrowing-guard edits in consumers only if a typecheck forces them (named in the PR body); ⛔ not the producerreadBaseContributions(#28722 Wanted 3,domain:server) (stop on breach; explain in the report)Container & model:
S,mode:thread,model: default — the tier is the PM's per-card call (floor sonnet · default opus · ceiling fable); Clause-② widening of a served response schema, one CONTRACT_REVIEW_TIER review by the seat before landing,effort: xhighClause-②: yes (widening)
Metadata-protocol: added
Responsibility:
n/a — not a defect cardThread-read: 6576949541
Premise: holds (on origin/main 12:20Z,
contributions[].kindisz.enum(['field', 'flow'])with a requiredobject, and nonavkind exists)Serial constraints cleared: none (no in-flight
domain:specclaim namespackage-lifecycle.zod.ts; the earlierdomain:server#3claim 6556692704 was released in 6556736104)Ruling-ref: 6566915346 (director record, batch #451 item 2, letter E, the maintainer's 「同意」); exit stroke 6576949541 (server seat 3); body re-cut by this seat as the spec slice.
objectstack-fleet commentedon Nov 2, 2026
domain:spec#2 · os-steve · session_01ADHkmQ28WWiNo3u94yGTPb
os-dev-report
{ "issue": 27928, "status": "done", "branch": "claude/project-thread-845vdn", "pr": "https://github.com/objectstack-ai/objectstack/pull/29401", "session": "session_01ADHkmQ28WWiNo3u94yGTPb", "premise_still_valid": true, "summary": "GetPackageCustomizationsResponseSchema.contributions is now a z.discriminatedUnion on kind: the field/flow arm (same members and describes, so it accepts exactly what it accepted; CONTROL pins) and a strict nav arm (kind 'nav', app, optional group, name = nav item id, packageId) whose describe opens [PLANNED — not yet served] and names ADR-0049, pinned in the test; the docblock carries the DECLARED AHEAD OF ITS PRODUCER paragraph with the MUSTs from ruling E (same appNavContributions registry, no disabled package, no key on any nav item). The member describe names the three kinds, the per-kind shape and an order (field/flow first as before, then nav by app, group with no-group first, name, package). Regenerated the package-lifecycle reference page and the api strictness count, named contributions on content/docs/api/metadata-api.mdx, governed the new union in packages/spec/variant-docs.json, spec minor changeset. The runtime producer needed one forced type-only edit (its local entry type excludes the nav arm) to compile; it lists the same entries and does not read the nav registry (that stays #28722 Wanted 3).", "tests": "At b6afae25 (the final commit 3bdb4133 only adds a variant-docs.json entry, which no test reads): spec build VERDICT 0; check:generated exit 1 naming check:docs + check:strictness-ledger, --fix VERDICT 0, then exit 0 in the gate run; pnpm --filter @objectstack/spec test VERDICT 0, Test Files 791 passed (791), Tests 23401 passed, 1 todo; package-lifecycle.test.ts 35 passed (10 new); spec typecheck VERDICT 0. Consumers (closure built, VERDICT 0): runtime typecheck exit 2 before the forced edit (TS2339 object x2, TS7053 kindOrder x2 in readBaseContributions), exit 0 after (also the reverse verification that the rebuilt spec .d.ts is read); runtime packages-customizations.test.ts + dispatcher-plugin.package-customizations-mount.test.ts Test Files 2 passed, Tests 19 passed; client typecheck exit 0; ui: turbo build @object-ui/app-shell^... VERDICT 0 (64 tasks), app-shell pnpm type-check VERDICT 0, the 4 app-shell files that build a customizations answer (run from ui/) Test Files 4 passed, Tests 34 passed. Scoped eslint over the 3 changed .ts files exit 0. Ablation in a side worktree under a trap: nav arm .strict() removed via ablation-replace (anchor 1->0, blob fd4561e7->bbc05a90) -> package-lifecycle.test.ts exit 1, 1 failed of 35 (nav entry carrying object refused); restored (blob = HEAD fd4561e7, git diff HEAD empty) -> exit 0, 35 passed. check-changeset-no-major --event with the PR body exit 0 (yes (widening) + added); check-partof-closing-keyword exit 0.", "gates": "Final head 3bdb4133: dispatch-gates --commands 105, all 105 exit 0 (stdin closed, exit captured before any pipe); --ran: 105 derived, 105 run, 0 NOT-MEASURED (derived zero), 0 UNRUN. First round at b6afae25: 104/105 exit 0, check:variant-docs exit 1 (undeclared discriminated union) fixed in 3bdb4133. Prereq: turbo build ./packages/** VERDICT 0 (78 tasks). Local-only: check:skill-frame-freshness exit 0; check:dev-prereqs exit 1 (8 of 106 workspace packages, ui examples/cli among them, have no dist in this container; machine state, spec dist fresh). CI check-runs: in_progress at report time, the seat reads them.", "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm", "mcp_calls": "8 — mcp__github__issue_read x4 (get #27928, get_comments x3), mcp__github__pull_request_read x4 (get_files #28749, get_files #28807, get #29218, get_files #29401); all reads, no write tool", "api_writes": "2 — POST /repos/objectstack-ai/objectstack/dispatches (relay pr_create, opened draft PR #29401, body read back 12575/12575 bytes identical); POST /repos/objectstack-ai/objectstack/issues/27928/comments (this report, via post-stamped.mjs). git push is not a REST write.", "files_changed": [ ".changeset/27928-customizations-contributions-nav-kind.md", "content/docs/api/metadata-api.mdx", "content/docs/references/api/package-lifecycle.mdx", "docs/audits/2026-07-unknown-key-strictness-ledger.counts/api.md", "packages/runtime/src/domains/packages.ts", "packages/spec/src/api/package-lifecycle.test.ts", "packages/spec/src/api/package-lifecycle.zod.ts", "packages/spec/variant-docs.json" ], "line_budget": "n/a — no skills/** or governed file in the diff; PR +228/-31 over 8 files", "deviations": [ "No liveness row: packages/spec/liveness governs metadata types only (its README), and no ledger names this API response or member (git grep). The planned marker on the nav arm's describe is the channel, pinned in the test.", "packages/spec/variant-docs.json is outside the claim's file surface; check:variant-docs reds on the new union without an entry. Bound to content/docs/api/metadata-api.mdx (governed), as the served flow-registration verdict is.", "Forced consumer edit in packages/runtime/src/domains/packages.ts (claim allows narrowing-guard edits a typecheck forces): type-only, plus a two-line comment. No runtime changeset. The PR body says no published byte moves; precisely, the emitted JS and .d.ts are unchanged, but the shipped index.js.map line mappings after that function shift by two lines (no sourcesContent). If the seat wants zero bytes, fold the comment onto the type line in one commit.", "Main moved 17 commits after the branch point 2f7977cd, none touching this diff's files; not merged before opening (the PR CI runs on the merge ref).", "No assignee and no reviewer set on the PR, and no PR-activity subscription: the standing order forbids MCP writes and os-dev forbids PR assignees; the seat reads CI.", "Skills-docs: none. skills/objectstack-platform/SKILL.md line 134 still lists the read as overrides, extensions and switched-off items (no contributions since #28749); governed surface, not touched." ], "open_questions": [ { "question": "Order of the nav entries inside contributions (the ruling leaves the spelling to this card).", "options": ["A (in the PR) — field/flow entries first in their existing order (object, kind, name, package), then nav entries by app, group (no group first), name, package", "B — one key for all kinds (kind first: field, flow, nav), which reorders today's served field/flow entries", "C — nav entries in contribution priority order, as the fold applies them"], "recommendation": "A, because it keeps the order of today's served entries unchanged and is deterministic without reading priority, which the entry does not carry." }, { "question": "What `group` names when the target app does not declare that group (the fold then appends the items at the top level and reports nav_contribution_group_missing).", "options": ["A (in the PR) — the group as the contribution declares it, always", "B — only the group the items actually land in; absent when the app lacks it"], "recommendation": "A, because it is the registry's recorded fact (c.group), the served navigation already shows where items land, and Studio finds an item by its id." }, { "question": "Entries for a contributed group's children.", "options": ["A (in the PR) — one entry per item of the contribution's items; a contributed group's children ride inside it", "B — one entry per item at any depth"], "recommendation": "A, because the contribution's items are what a package contributes; B would list the same package several times for one menu block. The server slice reads it either way." }, { "question": "New key names inside the entry (app, group): do they still need the maintainer's approval?", "options": ["A — no: ruling 6566915346 (letter E, 「同意」) names app, group, name and packageId itself", "B — ask again before landing"], "recommendation": "A, because the approved ruling spells these exact names." } ], "security_findings": "none", "out_of_scope_findings": [ "carrier: the server slice of #28722 (Wanted 3) · noted, not filed: skills/objectstack-platform/SKILL.md describes GET /packages/:id/customizations as listing overrides, extensions and switched-off items and has not named contributions since #28749; governed surface, so the slice that serves nav (or the seat) extends it." ] }Stamped 2026-11-02T14:08Z.
Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:spec#2 · os-steve · session_01ADHkmSduNGC2SZXszyrNut
Landed: PR #29401, merged as
0c640141at 2026-11-02T15:33Z.ACCEPT → PR #29401 comment 6580492378 · contract review PASS 6579472483 (
3bdb4133) and delta PASS 6580471213 (71941530).Follow-ups filed: #29411 (skills platform), #29412 (variant docs
z.enum). #28722 Wanted 3 is now unblocked fordomain:server; the seat tells server seat 3.