Repository navigation
metadata-protocol: a same-named item in a dependent package replaces the base package's item for package-less reads and in the base app #28238
Description
epic:#28130#1 · hotlong · session_040dfd80c4c9411b895c698e785a6848
Filing gate: ① reproducible defect · reach: public HTTP reads and the console app, measured once with the wrong result (below). ⛔ Not a claim.
Part of #28236 (P0, child N-03) · lane: domain:server (packages/metadata-protocol) · size: M.
Governing text — read before ADR-0146. ADR-0146 on main (cdbf08d1) predates this epic's re-plan and is being rewritten in place by #28237. Its D2 (in-place overlay editing of a read-only package's item in Studio, the "customized" chip, Reset to package default), its D3 (<base>.customize; New and Clone landing there) and its Phase 2 rollout are superseded — ⛔ do not implement them on this card. Still standing: D1 (the catalog and the item tools belong to Studio), D4's ledger switch (#28148), D5, D7. Where the ADR and this card or epic #28236 disagree, the epic's rulings win.
Scope note (2026-10-31) — unbound overlays keep working. A stored row with no package (the ADR-0005 overlay Setup writes today) still wins over the code package on a package-less read; only a row bound to a different package is excluded. ⛔ Do not break Setup's existing customizations; pin both cases.
Business reason. Any installed package that depends on another can silently change the other's views by shipping the same name, with no declaration and no marker, and the vendor's own app renders it. Authors and users then see different things: Studio, which reads with the base package, shows the base; users see the dependent package's copy.
Measured on a local examples/app-showcase boot at d6c0a75f1a (2026-10-30), single posture:
- Writable package
com.default.acme-customwithdependencies: { "com.example.showcase": "*" }(without the dependency the publish is refused,list-view-object-outside-closure). PUT /api/v1/meta/view/showcase_task.default?mode=draft&package=com.default.acme-customwith the base body,config.columns=title, status;POST …/publish?package=com.default.acme-custom→ 200.?package=com.example.showcase→ 6 columns ·?package=com.default.acme-custom→ 2 · nopackage→ 2 (_packageId: com.example.showcase) ·/_console/apps/com.example.showcase/showcase_taskrenders 2.
CleanupDELETE …?package=com.default.acme-customrestores 6.
Where. protocol-environment-rows.ts#packagelessAddress: a package-less read whose stored rows bind exactly one package serves that package's row; the code package that ships the item is not a candidate. Reached through protocol.ts packagelessReadAddress → getMetaItem / getMetaItemLayered; the list side merges through servedOverlayRowCandidates (list path not re-measured).
Wanted.
- The code package that ships the name is a candidate of the package-less address; a stored row bound to another package never wins over it by being the only stored row.
- The package-less read, the read naming the base, the layered read and the base app's list agree (pin test across the three reads + the list).
- No change to declared overrides — that rule arrives with the epic's override core; this card only stops the undeclared leak.
Acceptance. The three steps above answer 6 / 2 / 6 and the app renders 6; existing protocol.item-read-overlay-cache.test.ts and meta-overlay-cache suites stay green.
Dedupe. Related, not duplicates: #22057 (closed; a read naming a package served another package's row on an unscoped kernel), #23291 (closed; a package-less read kept serving the unbound row). Searched open+closed package-less read overlay another package: 74 hits, none with this shape.
Links back: #28236, ADR-0048 §3.3/§3.4.
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 31, 2026
domain:server#2 · os-project-manager · session_0186vfjHHMsRXC9EUT9hTFMo
Claim: PM loop round 1 · card thread · 2026-10-31T03:04Z
Session:
session_0186vfjHHMsRXC9EUT9hTFMo(the seat); the card thread issession_01FEkQ5nQHuymasPwjX3mAr2Account:
os-project-manager(the seat's linked user; the card's assignee)Branch:
claude/project-thread-boxqo3(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#2Ruling-ref: none. The card's own "Wanted" 1–3 and "Acceptance" are carried verbatim in the order. It is a sub-issue of #28236 (N-03) and inherits the parent's first touch; "No change to declared overrides" is in force.
File surface:
packages/metadata-protocol/src/protocol-environment-rows.ts(packagelessAddress) and its read callers (packagelessReadAddress,servedOverlayRowCandidateson the list side), tests, and changesets.protocol.tsonly if unavoidable, re-reading the #25467 split's open PRs first. ⛔ No package-less write address change: a fork if the read needs one.Container & model:
M,mode:thread,model: opus(--tiernames no path mandate: PM's call, default),effort: highClause-②: no (expected: a package-less read serves the base package's row instead of an undeclared dependent's; nothing is refused or newly accepted; the dev measures and declares)
Metadata-protocol: none (expected
semanticornone; the dev measures against the AGENTS.md level table and declares)Responsibility: the code is
packagelessAddress's candidate set (metadata-protocol) · no platform path covers it today (#22057 and #23291 closed other shapes) · reached by public HTTP package-less reads and the console app of any installed package with a dependent writable package (measured on the card)Thread-read: none
Premise: holds (read 2026-10-31T03:04Z at
origin/main91fa06df8:protocol-environment-rows.tsL133packagelessAddresspresent; the card's repro is dated 10-30 atd6c0a75f1a); the dev re-measures firstSerial constraints cleared: open PR #28188 touches only
protocol.meta-types-degenerate-derivation.test.ts, disjoint. The #25467protocol.tssplit has no open PR at this read. The sibling claim #27884 is onmetadata-redaction.tsandprotocol-datasource-credentials-ref.ts, a disjoint file set in the same package; the later lander mergesmainResume-from: none — fresh from
origin/mainState:
pm:queue→pm:dispatched, assigned toos-project-manager(label write at 02:59Z), recorded by this claim.Generated by Claude Code
objectstack-fleet commentedon Oct 31, 2026
domain:server#2 · os-project-manager · session_01FEkQ5nQHuymasPwjX3mAr2
os-dev-report
{
"issue": 28238,
"status": "needs_decision",
"branch": "claude/project-thread-boxqo3",
"pr": "#28304",
"session": "session_01FEkQ5nQHuymasPwjX3mAr2",
"premise_still_valid": true,
"summary": "The by-name half is fixed and pinned: a read naming no package (getMetaItem) and the layered read's effective now take their stored content from packagelessContentPackage (protocol-environment-rows.ts), where the code package that ships the name is a candidate, so a dependent package's same-named row is not served for it; the package-unbound row still wins over the code item, and packagelessAddress (the write address, the read's version) does not move. Live on app-showcase the card's steps answer 7/2/7 (base 7/2/2; the showcase list has 7 columns now, not 6) and ?layers=true effective 7 (base 2). The app still renders 2 (Title, Status) on both base and head: the console reads views only from the list naming no package and keys them by name, last wins, and that list keeps one slot per package that holds the name (#21934), the dependent slot wearing the base's _packageId. Making the app render the base needs a list rule or a console merge rule, which is the open question; the PR therefore says Part of #28238, not Fixes.",
"tests": "New packages/objectql/src/protocol-packageless-read-dependent-package.test.ts (real ObjectQL + SchemaRegistry + in-memory driver; dependent package installed through installPackage with dependencies declared; its row written by draft save + per-item publish naming it): 5 cases. Red on base 69ce01d (production files at base blobs, metadata-protocol rebuilt): 3 failed | 1 passed of the 4 cases then, AssertionError expected [ 'title', 'status' ] to deeply equal [ Array(6) ]. Head: Tests 5 passed (5). Ablation via scripts/ablation-replace.mjs on protocol-environment-rows.ts (one-shipper answer back to address.packageId, marker ABL28238): anchor 1 to 0, blob 1a530197d936 to 992e059d588a, ablation-dist-preflight hit dist/index.js and dist/index.cjs, Tests 3 failed | 2 passed (5); restored blob == HEAD, git diff HEAD empty; restore leg rebuilt, preflight --absent (24 files), Tests 5 passed (5). Suites at head: metadata-protocol Test Files 284 passed | 4 skipped (288), Tests 21860 passed (includes protocol.item-read-overlay-cache, meta-overlay-cache, protocol.packageless-save-address); objectql --project local Test Files 501 passed (501), Tests 9755 passed; typecheck objectql + metadata-protocol exit 0; eslint --no-inline-config on packages/metadata-protocol and the new test exit 0. Live showcase (pnpm dev -- --fresh, HTTP + Playwright on /_console/apps/com.example.showcase/showcase_task): base 7/2/2, layered effective 2, render [Title, Status]; head 7/2/7, layered 7, render [Title, Status]; GET /meta/view with no package: two items named showcase_task.default (7 and 2), both _packageId com.example.showcase, on both.",
"gates": "Local, on 21fa3e7: dispatch-gates --commands --repo objectstack-ai/objectstack derived 62; all 62 run, each exit captured before any pipe; all exit 0 (check-plugin-teardown-shape --self-test first exit 3 on the shallow clone, exit 0 after git fetch --depth=1 of its control commit). dispatch-gates --ran: 62 derived, 62 run, 0 NOT-MEASURED, 0 UNRUN. pnpm lint scoped (eslint --no-inline-config) to the touched packages: exit 0. CI families: PR #28304 check-runs not yet read (in_progress at report time); test:repo (Test Core) declared to CI, not run locally.",
"dogfood_battery": "n/a — no
!in the PR title and no (narrowing) arm","mcp_calls": "4 — mcp__github__issue_read x4 (28238 get, 28238 get_comments x2, 28236 get); no write tool",
"api_writes": "2 — relay pr_create (#28304, draft, no labels, no assignees; read-back identical) and this os-dev-report comment via post-stamped; plus git push (not REST). Overlap reads via gh api pulls?state=open and pulls/N/files: no open PR touches the three edited files.",
"open_questions": [
{
"question": "The base app still renders the dependent package's 2 columns: the console reads views only from GET /meta/view with no package and keys them by name (MetadataProvider mergeViewsIntoObjects, last wins), and that list holds one slot per package that holds the name (#21934), the dependent slot wearing the base's _packageId (ADR-0010 envelope graft). Which rule makes the base app's list agree with the package-less read?",
"options": [
"A — Server, this card: the list naming no package serves, for a name exactly one code package ships, only the slot the package-less read serves (packagelessContentPackage); a dependent package's undeclared same-named row stays listed under ?package= naming it. One lane, metadata-protocol readFlattenedMetaItems/mergePackageAwareOverlay, about S-M. Cost: amends #21934's rule that the env-wide list holds every package's body of a name, for this shape only.",
"B — Console prefer-local: the console's view merge prefers the active app's package (ADR-0048 §3.3 says routed UI surfaces resolve prefer-local). Needs the list to say which package each slot's row is bound to, which today both slots hide behind the base's _packageId (ADR-0010 §3.3 graft): a new served field or an envelope rule change, plus a ui-lane card. Two lanes; app fixed only when both land.",
"C — Leave the list to the epic: N-09 (undeclared same-name refused at publish, ruling Q1) stops new copies at the source and N-10 (one effective read across package-less, base-named, layered, list and export) defines the list. This card closes on the by-name half once its acceptance is reworded; rows already stored keep rendering in the base app until N-10 or the N-16 migration."
],
"recommendation": "A. Real need (measured): every user of the base app sees the dependent copy today, and the console reads only the list naming no package, so the by-name fix alone changes nothing they see. Long-term: A is exactly the first step of N-10's one effective read and needs no new served field; B adds a provenance field the epic has not planned, and C leaves a P0 leak open until P1 lands. AI-error axis: A is weaker than a publish refusal, since it quietly drops a row from one list; N-09 then makes the same shape a loud refusal, so A is an interim read rule, not consumer tolerance. Startup focus: A is one lane and small; B is two lanes and a new surface. The cost to accept knowingly is the #21934 amendment for undeclared same-named rows only."
}
],
"out_of_scope_findings": [
"carrier: #28236 (N-10) · noted, not filed — a read naming the dependent package answers its own row under _packageId com.example.showcase (the ADR-0010 §3.3 envelope graft), live and in the new test; by the ADR the artifact's envelope wins over an overlay row, so it is recorded for N-10's effective-read definition, not as a defect"
]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 31, 2026
domain:server#2 · os-project-manager · session_0186vfjHHMsRXC9EUT9hTFMo
待裁:基础应用里,依赖包的同名视图仍然顶替基础包的视图 —— 列表规则放在哪一层
domain:server席位 2 · 2026-10-31T04:13Z · 来源:dev 报告6538793461(needs_decision,前提成立)· PR #28304(Part of #28238,按名读取那一半,在飞草稿)。一句话问题: 客户打开基础应用时,看到的仍是另一个依赖包悄悄存下的同名视图(2 列),而不是基础包自己的视图(7 列)。按名读取这一半已在 PR #28304 修好,但应用界面不走按名读取:它读的是“不点名包”的视图列表,并按名字后到者覆盖。所以界面上的症状不变,要再定一条列表规则。
背景与 Governing text
Governing text: 本卡 Wanted ②、Acceptance;ADR-0048 §3.3;
protocol.tsreadFlattenedMetaItems的[#21934]注释;ADR-0010 §4.1;史诗 #28236 的 Q1 与 N-10。protocol.tsreadFlattenedMetaItems的[#21934]注释):不点名包的环境级列表,对一个名字保留每个出品它的包各一条(「holds every package's body of a name」);注释写明理由:这份列表是匿名表单门禁判断撤回的那一层。_packageId、_packageVersion、_provenance);给列表项盖章的是代码规则mergeArtifactProtection(protocol.ts,其 docblock 标 ADR-0010 §3.3,该节实为 L3 项级锁)。实测结果:依赖包那一条挂的是基础包的_packageId,界面分不出它来自哪个包。Metadata-protocol: none或semantic,由 dev 实测声明);B 要新增一个对外的来源字段或改信封规则,按「改协议单独立卡」处理,本卡只能被它阻塞;C 不改。前提(实测于 PR #28304 head
21fa3e7f,showcase 实机)effective:基础 7/2/2 → head 7/2/7;?layers=trueeffective 基础 2 → head 7。re-check:卡上三步 +?layers=true,对照 PR fix(metadata-protocol): a dependent package's same-named row no longer replaces the base package's item on the read naming no package #28304 正文「Acceptance notes」表。GET /meta/view列表,按名合并,后到者赢。re-check:grep -n "EAGER_TYPES\|composeObjects\|mergeViewsIntoObjects" ui/packages/app-shell/src/providers/MetadataProvider.tsx;applyViewItem以view.name为键写bucket.listViews[key],后到覆盖。_packageId(实测:GET /meta/view不带包,showcase_task.default两项,7 与 2)。re-check:grep -n "\[#21934\]" packages/metadata-protocol/src/protocol.ts。选项 × 真实代价 × 工作量
packagelessContentPackage的答案;改点在readFlattenedMetaItems/mergePackageAwareOverlay);依赖包的那条仍在点名它的列表里业务含义直译
四维分析(业务立场)
推荐:A。 只看①选 A;②③④ 是否翻转:否。不取 B:为界面挑选新增一个对外字段,两个车道才修好,且与 N-10 的服务端单一答案方向相反,依据的 ADR-0048 §3.3 又在史诗的推翻清单上。不取 C:已存在的副本在 N-10 落地前一直顶替基础视图,而史诗把本卡列为 P0、N-10 列为 P1。需要明知的代价:A 改写 #21934 的列表规则,但只针对“恰好一个代码包出品、被未声明的同名行顶替”这一形状;#21934 注释写明这份列表是匿名表单门禁判断撤回的那一层,少列一条就可能让依赖包那一行里的撤回不被门禁看见,这一点 dev 报告与 PR 正文都未测。置信缺口:其一,撤回门禁是否经由这份不点名包的列表读取,未验证(见裁后执行的前提);其二,A 与 N-10 的最终列表定义是否完全一致,要等 N-10 定稿;若 N-10 选了不同规则,A 的这一形状由 N-10 接管。
裁后执行
Fixes。派发令挂一条可证伪前提:匿名表单撤回门禁(packages/metadata-core/src/anonymous-form-intake.ts及其在 metadata-protocol 的判定调用点)对一个名字的判断仍能看到依赖包那一行的撤回,或其读取路径不经由不点名包的列表;dev 先验,再动手。前提不成立就报 fork,⛔ 不许硬做,也不许悄悄退回 B 或 C。Blocked-by二者。os-decision-facets
① 长远:五种读取一个有效答案(N-10);A 是列表上的第一步,复用按名读取的同一条规则,不加字段,只收窄 #21934 的一条规则;B 依据的 ADR-0048 §3.3 在史诗推翻清单上
② 拉动:依赖包存了同名条目,基础应用的全部用户今天就看到被顶替的视图(实测);按名读取修好后界面仍不变
③ 防错:A 是过渡期读取规则,N-09 落地后转为发布时响亮拒绝;B 让服务端与界面两套答案;A 的撤回门禁可见性未测,挂前提
④ 不扩散:A 一车道一 PR 不加字段;B 两车道加一个永久对外字段
Prior rulings read: package-less list same-name dependent package one slot per package prefer-local → 1 hit (#28238 itself); package-less read serves another package's overlay row unbound row same view name → 15 hits (nearest #22057, #23291, #22058, #21638, #21334, all closed, none rules the package-less list); ADR-0048 §3.3, ADR-0010 §4.1; thread: none
Analysis-tier: opus draft, re-read at fable
Generated by Claude Code
objectstack-fleet commentedon Oct 31, 2026
domain:server#2 · os-project-manager · session_0186vfjHHMsRXC9EUT9hTFMo
Landing record · #28238 · PR #28304
domain:serverseat 2 ·session_0186vfjHHMsRXC9EUT9hTFMo· 2026-10-31T05:11Zgit ls-remote origin 'refs/heads/gh-readonly-queue/main/pr-28304-*'git merge-base --is-ancestor 5055b102 origin/maingit grep -c packagelessContentPackage origin/main -- packages/metadata-protocol/src/protocol-environment-rows.ts5055b102. The read naming no package and the layered read now take a name's content from the code package that ships it. A dependent package's same-named row no longer replaces the base's item on those reads.6538867716.Release: claim
6538170135(session_0186vfjHHMsRXC9EUT9hTFMo, card threadsession_01FEkQ5nQHuymasPwjX3mAr2, branchclaude/project-thread-boxqo3) · into the decision box.pm:dispatched→needs-user-decision, assignee cleared. The next dispatch takes a fresh claim and order under the letter the maintainer picks.mainat5055b102or later (the by-name half is in).Generated by Claude Code
2 remaining items
objectstack-fleet commentedon Oct 31, 2026
domain:server#1 · os-tesla · session_01L9qibz3ZUbZ8Qcn1rDw9yc
Claim: PM loop round 1 · card thread · 2026-10-31T09:56Z
Session:
session_01L9qibz3ZUbZ8Qcn1rDw9yc(the seat); the card thread issession_01L9qibzdcqVarNWXgmggykjAccount:
os-tesla(the seat's linked user; the card's assignee)Branch:
claude/project-thread-tf4y8u(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#1Ruling-ref: ruling A
6540076460on letter6538867716: the env-wide list naming no package serves only the entrypackagelessContentPackageserves for a name exactly one code package ships; the anonymous-form withdrawal premise is verified first, and a failed premise is reported asneeds_decision, never forced or swapped for B/C.File surface:
packages/metadata-protocol/src/protocol.ts(the list merge block only:readFlattenedMetaItems/mergePackageAwareOverlay),protocol-environment-rows.tsif the shared helper moves, tests, changeset.Container & model:
M, efforthigh,mode:thread,model: opusClause-②: no (expected; the dev measures and declares)
Metadata-protocol: none or semantic (expected; the dev measures against the AGENTS.md level table)
Thread-read: 6540076460
Premise: holds (read at
origin/main3ba520691:packagelessContentPackagepresent inprotocol-environment-rows.ts, 2 hits); the dev re-measures firstSerial constraints cleared: the #25467
protocol.tssplit is unclaimed with no open PR at this read; the hot-file queue on seat post #6367 listsprotocol.tsfor #25467 onlyResume-from: none — fresh from
origin/main3ba520691Order:
/mnt/project-files/server-seat-1/r2026-10-31/dispatch-28238.md(project file, not public)State:
pm:queue→pm:dispatched, assigned toos-tesla, recorded by this claim.objectstack-fleet commentedon Oct 31, 2026
domain:server#1 · os-tesla · session_01L9qibzdcqVarNWXgmggykj
os-dev-report
{
"issue": 28238,
"status": "needs_decision",
"branch": "claude/project-thread-tf4y8u",
"pr": null,
"session": "session_01L9qibzdcqVarNWXgmggykj",
"premise_still_valid": false,
"summary": "The ruling's premise does not hold, so no code was written (claim 6541947229, ruling 6540076460). Read at origin/main 3ba5206 (contains 5055b10): the anonymous form doors judge a withdrawal only against the env-wide view list naming no package, and no other path reaches a package-bound row. Ruling A removes the dependent package's same-named row from that list, so a withdrawal held only on that row would no longer be seen and the base package's form it withdrew would be served again. Trace: (1) the only runtime caller of anonymousFormIntakeWithdrawnIn is packages/rest/src/form-routes.ts:141 (the CLI v18 migration at packages/cli/src/utils/organization-ownership-apply.ts:1597 and :1791 builds its own layer and is not a door); packages/metadata-protocol/src has no call site, only the availability advisory (runtime-authoring-gate.ts:430-450) and the posture probe (protocol-authoring-posture-probes.ts:82). (2) Both doors resolve through resolveFormBySlug (form-routes.ts:175). (3) It reads p.getMetaItems with type view and no packageId (form-routes.ts:183-192); p is the kernel's protocol service (packages/rest/src/rest-server.ts:2374-2380). (4) getMetaItems (packages/metadata-protocol/src/protocol.ts:9440) calls readFlattenedMetaItems (:9451, :9491), whose mergePackageAwareOverlay (:9615, per-package loop at :3066) keeps one item per package of a name under the [#21934] rule (:9681-9686). (5) findPublicFormView (form-routes.ts:133-146) passes that same list as the layer to anonymousFormIntakeWithdrawnIn (packages/metadata-core/src/anonymous-form-intake.ts:285-303), which closes a form only when a body in that layer withdraws it; its docblock (:271-284) says a name closes in every package only when the layer holds every package's body. (6) The by-name reads already serve packagelessContentPackage (protocol-environment-rows.ts:198-212), the base's content, so they do not carry the dependent's body either. Breaking shape: code package P1 ships view X with an open public form; writable package P2 (depends on P1) publishes its own X keeping the link with sharing.enabled false. Today the form is closed; after A the list holds only P1's open X and the form is served. packages/rest/src/public-form-withdrawal.test.ts:242-275 pins the closed case but injects the list, so it would stay green under A.",
"tests": "None run: the order stops before code on a failed premise. The finding is a static trace at origin/main 3ba5206; no live measure was taken.",
"gates": "None run (no diff).",
"dogfood_battery": "n/a — no PR",
"mcp_calls": "3 — mcp__github__issue_read x3 (28238 get x1, get_comments x2: before the trace and to verify claim 6541947229); no write tool",
"api_writes": "1 — this os-dev-report comment via post-stamped; no push, no PR",
"open_questions": [
{
"question": "The anonymous form doors read only the env-wide view list naming no package, so ruling A as written would stop them seeing a withdrawal held on a dependent package's same-named row. Which way should the list half go?",
"options": [
"1 — A plus a withdrawal layer for the doors: the served env-wide list follows A; the doors judge against a layer that still holds every package's body of a name (for example a protocol read the door calls beside getMetaItems, built from the same merge before the A filter). Keeps the kill switch exactly as today. Touches packages/rest/src/form-routes.ts and protocol.ts (two packages, one lane), one extra internal read per anonymous form request, the [#21934] comment moves to the new read. About M.",
"2 — A as ruled, accepting the narrowing: a dependent package's undeclared copy no longer closes the base's form. Consistent with A (that copy is no longer effective in the base app), but it re-opens a form someone explicitly withdrew, a loosening of an anonymous-access boundary, so a maintainer floor. About S-M.",
"3 — C: the list goes to N-10, as in letter 6538867716; the base app keeps rendering the dependent copy until then."
],
"recommendation": "1, because it delivers the ruled base-app fix without loosening the withdrawal kill switch, stays in one lane, adds no spec key or served field, and N-10 can absorb the withdrawal layer when it defines the one effective read."
}
],
"out_of_scope_findings": [
"carrier: seat (the letter) · noted, not filed — packages/rest/src/public-form-withdrawal.test.ts injects the env-wide list, so no test in the real composition pins that a package-bound row's withdrawal reaches the doors; whichever option is ruled should add one that boots the real list"
]
}
objectstack-fleet commentedon Oct 31, 2026
domain:server#1 · os-tesla · session_01L9qibz3ZUbZ8Qcn1rDw9yc
待裁:裁决 A 的前提不成立 —— 匿名表单的撤回判断正是读这份"不点名包"的列表
domain:server席位 1 · 2026-10-31T10:04Z · 来源:dev 报告6542005100(needs_decision,premise_still_valid: false)· 裁决6540076460写明「前提不成立就报回来」。一句话问题: 照 A 原样做,基础应用会显示正确的视图,但依赖包里已经关掉的同名匿名表单会重新对外开放。要定一条既修显示、又不放开匿名表单的路。
前提实测(席位在
origin/main3ba520691复核过 dev 的追踪)packages/rest/src/form-routes.ts的resolveFormBySlug:它用getMetaItems({ type: 'view' })(不点名包)取列表,再在findPublicFormView里用同一份列表调用anonymousFormIntakeWithdrawnIn判撤回。anonymousFormIntakeWithdrawnIn的运行期调用点只有这里(另一处在 CLI 的 v18 迁移工具里,不是门禁)。没有别的路径能读到绑在依赖包上的那一行。sharing.enabled: false)。今天表单是关的;A 之后列表只剩基础包那条,/forms/<slug>重新可提交。packages/rest/src/public-form-withdrawal.test.ts里钉住"关闭"的用例是直接注入列表的,A 落地后它仍是绿的,CI 抓不到这个回退。选项
form-routes.ts+protocol.ts)四维分析(业务立场)
推荐:1。 只看①选 1;②③④ 不翻转。不取 2:放宽匿名访问边界是人工地板,且回退静默。不取 3:史诗把本卡列为 P0,显示问题已实测影响全部用户。置信缺口:撤回层的读取代价(每次匿名表单请求多一次带包的读取)未测,dev 在 PR 里报。
裁后执行
Fixes #28238),派发令写明撤回层的形状与一条走真实列表的撤回 pin(含消融)。os-decision-facets
① 长远:显示与撤回分开,显示取一个有效答案,撤回仍取最严;2 把显示改动变成权限放宽
② 拉动:显示问题影响基础应用全部用户(实测);撤回回退影响匿名访问者,属安全面
③ 防错:2 的回退在现有测试里静默;1 要求真实列表的撤回 pin + 消融
④ 不扩散:1 不加对外字段,多一次读取;3 零改动但显示问题延到 P1
Prior rulings read:
6540076460(this card, ruling A with the premise clause);6538867716(letter); form-routes.ts[ADR-0131 D6, C7]note; thread: noneAnalysis-tier: opus
objectstack-fleet commentedon Oct 31, 2026
domain:server#1 · os-tesla · session_01L9qibz3ZUbZ8Qcn1rDw9yc
Release: claim
6541947229(session_01L9qibz3ZUbZ8Qcn1rDw9yc, card threadsession_01L9qibzdcqVarNWXgmggykj, branchclaude/project-thread-tf4y8u) · into the decision box · 2026-10-31T10:05Z6540076460's premise does not hold (dev report6542005100, seat-verified); the ruling itself says to report a fork, so the letter above goes to the maintainer.pm:dispatched→needs-user-decision, assignee cleared. The card thread stays open with no code; the next dispatch takes a fresh claim under the option picked.objectstack-fleet commentedon Oct 31, 2026
epic:#28130#1 · hotlong · session_040dfd80c4c9411b895c698e785a6848
2026-10-31T11:39Z
Ruled: option 3 of the seat letter 6542017888 — no interim fix; this card closes on its by-name half, and the list half goes to epic child N-10 (one effective read).
Maintainer, verbatim, in the desktop PM session: 「不考虑过度的修法,直接一步到位」, then 「3」. Supersedes ruling A (6540076460) for the list half, whose premise the dev report 6542005100 falsified. Freshness gate: newest comment at recording is 6542025133; no later edit.
Why (as presented to the maintainer): the customer's in-system customization — today a package-less overlay row, after ADR-0146 an item of
<base>.custom— still overlays the base in the env-wide list (packages/metadata-protocol/src/protocol.ts#servedOverlayRowCandidates/mergePackageAwareOverlay: package-less rows enter as stand-ins), so it is untouched by this card. Only a same-named row bound to another dependent package is affected, and under #28390 ruling A (6542177429) plus N-09 that shape is refused at publish going forward. Both the list-display defect and the anonymous-form withdrawal regression touch only environments that already hold such rows (count not measured; N-09's dispatch counts them first, rider 5 of 6540351677). Building a withdrawal layer now would be transitional code N-10 redoes.Disposition:
needs-user-decisionremoved in the same pass.resolveFormBySlug(packages/rest/src/form-routes.ts) through the real list, not an injected one, with an ablation (the existingpackages/rest/src/public-form-withdrawal.test.tsinjects the list and would stay green through the regression).