You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[finding] the layered view (/meta/:type/:name/layers, ?layers=true) answers an absent name 200 with every layer null, where an unpublished app answers 404: an existence oracle against ADR-0045 §3 #20507
Filing gate: ① a defect with a named landing site: createMetaLayeredAnswer in packages/rest/src/meta-item-read-gate.ts (PR #20505, #20478, in review), the one post-read chain both transports call for the layered view. Before that PR lands, the site is RestServer's /layers handler and ?layers=true flag in packages/rest/src/rest-server.ts. Finding class (b): it violates a declared contract, ADR-0045 §3: 「"Hidden" means externally unobservable, consistently across every surface」. reach: was measured at a public door by the #20478 dev, as a member through RestServer's registered route handlers. After PR #20505, the dispatcher answers identically, because that PR carries RestServer's reference answer across unchanged, as its dispatch required.
Filed by the domain:cli execution seat (#6024, session local_1d2a197c-c20e-4e90-9be8-413d4d432289) from the #20478 round. ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim.
Because an absent name answers 200 and an unpublished one answers 404, a member can tell that an unpublished app exists. The plain read does not leak this: it answers both with 404.
What the fix looks like (for the dispatch to confirm, not a ruling)
The dev's suggestion: when no layer is present, the shared chain answers the absence refusal, in one place for both transports. First, measure whether any reader depends on 200-with-nulls for an unsaved item. Studio's designer is the candidate, and it is unmeasured.
Duplicate check
Board search, open and closed, taken in the act that filed this card:
Path: permissions that actually hold — what is hidden stays unobservable | 缺项 (the layered view answers an absent name 200, an unpublished one 404) | P2
Triage: first grade — bug · security · priority:p2 · domain:cli · area:access · pm:queue. Direction: the shared chain answers an absent name with the same refusal as a hidden one
Triage: lands in packages/rest/src/meta-item-read-gate.ts (createMetaLayeredAnswer, :2586 on origin/main), the one post-read chain both transports call since PR #20505 landed ⇒ domain:cli, by the lane table's packages/rest row.
Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-09-28T21:56Z. ⛔ Not a claim, ⛔ not a dispatch.
Why p2, with security. ADR-0045 §3 declares a hidden item externally unobservable on every surface, and the plain read keeps that promise (404 for both). The layered view breaks it: a member can tell that an unpublished app exists. What leaks is existence only, not content or events. So it sits below #20378 and #20441 (p1 · security), which served draft content and draft-save events.
First step: measure the reader. The dev named Studio's designer as the candidate that may read 200-with-nulls for an unsaved item. Measure it before changing the answer.
Nothing depends on it: the absent name gets the plain read's 404 RESOURCE_NOT_FOUND, in the shared chain, once for both spellings and both transports.
The designer depends on it: it gets its own authoring-capable answer, report back, and triage rules. ⛔ Don't keep the 200 for members to serve it.
Pins: as a member, /layers and ?layers=true answer the same status and body for an absent name and an unpublished one, and a published item's control is unchanged. Cover both transports.
Not serial. PR #20505 (#20478) merged at 2026-09-28T20:54Z and built the shared chain this fix goes in.
Claim: PM loop round 1 of the domain:cli seat's session local_1d2a197c: priority:p2 · security, the older of the lane's two queued p2 cards (batch 2, beside #20516)
Session: local_1d2a197c-c20e-4e90-9be8-413d4d432289
Account: hotlong
Branch: claude/issue-20507-layers-absent-name-oracle
Worktree: objectstack-issue-20507
Domain: domain:cli
Seat: domain:cli#1
File surface:
packages/rest/src/meta-item-read-gate.ts: createMetaLayeredAnswer only (the absent-name answer, once for both spellings and both transports);
packages/rest/src/rest-server.ts and packages/runtime/src/domains/meta.ts: only if a transport's envelope mapping of the new refusal needs a line;
tests in packages/rest/src/ and packages/runtime/src/domains/;
one .changeset/20507-*.md.
Read-only: packages/metadata-core/**, packages/metadata-protocol/**, packages/spec/**, packages/core/**. Stop on breach and explain in the report
Container & model: S, mode:subagent, model: default tier.
Clause-②: no
Thread-read: 5879479871
Serial constraints cleared: The file lists of all open PRs were read in this act: none touches meta-item-read-gate.ts or runtime meta.ts. PR #20518 (the /diff default range) and PR #20512 (the OpenAPI info) touch other regions of rest-server.ts, which is ordinary same-file concurrency: merge main on conflict. The predecessor PR #20505 (#20478) landed at 9449512a. #20516 (this seat, beside) is in create-objectstack, disjoint
Taken 2026-09-28T22:45Z, origin/mainfb194c70e. Executes triage's grade (5879479871): measure the reader first (Studio's designer), then answer an absent name as a hidden one is answered (404 RESOURCE_NOT_FOUND) in the shared chain, and ⛔ never keep the 200 for members. Clause-②: no: a door is pulled back to the declared contract, ADR-0045 §3.
os-dev-report
{
"issue": 20507,
"status": "done",
"branch": "claude/issue-20507-layers-absent-name-oracle",
"pr": "#20527",
"session": "local_1d2a197c-c20e-4e90-9be8-413d4d432289 (the harness's CLAUDE_CODE_HOST_SESSION_ID, as the dispatch named it; commit trailers read Claude-Session: https://claude.ai/code/session_local_1d2a197c-c20e-4e90-9be8-413d4d432289)",
"premise_still_valid": true,
"summary": "createMetaLayeredAnswer (packages/rest/src/meta-item-read-gate.ts), the one post-read chain both transports call, now refuses a layered read with no layer present as 'absent', before the per-caller gate. It runs once, for both spellings on both transports. RestServer and the dispatcher already write 'absent' in the envelope they use for an unpublished app, so no transport file changed. H0: nothing depends on the 200. The only wire reader is objectui's MetadataClient.layered (metadata-client.ts:1289-1304 at pin dd3f7e1b), which already maps a 404 to the four null layers. Its 15 non-test call sites are all Studio or metadata-admin authoring screens. H1: re-measured, the old answers were 200-with-nulls against 404. H2: a builder now gets 404 RESOURCE_NOT_FOUND for an absent name and is still served an unpublished app. H3: under ablation, exactly the six absent-name pins went red, and the restore was proven. Worktree teardown follows this report.",
"tests": "At final head 32de5e6 (origin/main merged, closure rebuilt with pnpm --filter '@objectstack/runtime...' build): pnpm --filter @objectstack/rest exec vitest run --maxWorkers=2 gave 222 files / 4239 tests passed (40 skipped), both projects; pnpm --filter @objectstack/runtime exec vitest run --maxWorkers=2 gave 289 files / 4897 passed (1 skipped), both projects; pnpm --filter @objectstack/rest --filter @objectstack/runtime typecheck exited 0, with both check:test-typecheck: OK. New pins are in packages/runtime/src/domains/meta-list-projection-parity.test.ts (both transports): 4 member cases where an absent name and an unpublished app answer the same, 4 published-app controls, and 1 case where every caller gets 404 and a builder is still served launchpad. H1, the pins run on the unfixed chain (fb194c7): 6 failed, 4 passed; the absent name answered 200 with code/overlay/effective null plus lock/editable/deletable/resettable, and launchpad answered 404 RESOURCE_NOT_FOUND. H3 ablation: scripts/ablation-replace.mjs, WRAP mode, --delete of the new branch: anchor 1 to 0, blob 662d87187124 to af0967c88051. rest resolves from source (runtime vitest aliases @objectstack/rest to ../rest/src/index.ts), so dist was not on the path. Under the mutation, runtime full: 6 failed / 4885 passed, the 6 being exactly the absent-name pins, with all 4 controls green; rest full: 221 files passed. Restore: blob after restore == HEAD 662d87187124, git diff HEAD empty, git status --porcelain empty. Fixture triage: the parity ?package= case moved to crm?package=elsewhere (200, code null, overlay answers), and payroll?package=crm became an absence pin. The execctx census Proxy double gained a real getMetaItemLayered shape so its /layers row still measures 'serves on its own reading'.",
"mcp_calls": "0",
"api_writes": "3: (1) draft PR create, gh pr create under with-fleet.sh (gh's own transport), PR #20527; (2) POST /repos//issues/20527/assignees returned 201 through label-write.mjs, read back as hotlong; (3) POST /repos//issues/20507/comments, this os-dev-report comment, through post-stamped.mjs. Also 7 git pushes through with-fleet.sh --kind 'git push' (not REST).",
"open_questions": [],
"out_of_scope_findings": [
"carrier: the spec seat. GetMetaItemLayeredResponseSchema.effective's describe text in packages/spec/src/api/protocol.zod.ts says 'null when the item resolves to nothing at all'. Through the REST route that case now answers 404 instead of a body; the text still describes the protocol method's in-process return. It is outside this card's file surface (packages/spec/** read-only). Noted in the PR's Acceptance notes, not filed. Dedupe words: layered response effective null describe, GetMetaItemLayeredResponseSchema effective 404, layers absent name spec text"
],
"gates": "dispatch-gates --repo objectstack-ai/objectstack --commands, derived at 32de5e6: 61 families; 60 exited 0; pnpm check:dual-build-cjs-loads exited 3 (PREREQUISITE NOT MET: 36 packages have no dist) = NOT MEASURED. A narrowed probe showed require('packages/rest/dist/index.cjs') loads and exports createMetaLayeredAnswer. --ran reconciliation: '61 derived famil(ies) accounted for — 60 run, 1 NOT-MEASURED'. node scripts/check-issue-citations.mjs --base origin/main, after the merge: exit 0, 5 of 5 citations resolve. pnpm lint at 32de5e6: exit 0 in 35s. CI status: in_progress, not awaited.",
"line_budget": "132 changed lines (+117 / -15) across 4 files, against the 5000-line human-merge threshold: under.",
"deviations": [
"os-verify-lock.sh ran in its declared UNLOCKED mode for every build and test (no flock on this macOS host); its disclosure is pasted verbatim in the PR body.",
"pnpm check:dual-build-cjs-loads is NOT MEASURED: it needs a whole-repo pnpm build, which was not run on this shared host. The diff changes no import, export or module format. A narrowed CJS-load probe was run on the one package whose dist changed (@objectstack/rest).",
"The first label-write call ran without the fleet token in its environment and exited 3 (PREREQUISITE NOT MET; the tool states nothing was read and nothing was written). The re-run under with-fleet.sh made the one assignee write.",
"packages/qa/http-conformance and packages/qa/dogfood were not run locally and are left to CI. By git grep, neither makes an HTTP read of the layered view for an absent name.",
"PR assignee only; no labels were written, since the dispatch named none and the diff carries a patch changeset."
],
"files_changed": [
".changeset/20507-layers-absent-name-oracle.md",
"packages/rest/src/meta-item-read-gate.ts",
"packages/rest/src/execctx-consumer-census.test.ts",
"packages/runtime/src/domains/meta-list-projection-parity.test.ts"
]
}
ACCEPT: PR #20527 at 32de5e64, R1 of the domain:cli seat's new session
domain:cli execution PM seat #6024 · session local_1d2a197c-c20e-4e90-9be8-413d4d432289 · review of record, written 2026-09-28T23:34Z
Reviewed against GitHub and origin/main, not against the report.
Checklist:
PR shape: draft, base main. The first line is Fixes #20507, followed by a line-initial Clause-②: no. A scan of the whole body finds one closing keyword, Fixes #20507.
Scope: 4 files, all inside claim 5880083725:
one step in createMetaLayeredAnswer: no layer present answers absent, before the gate;
the parity census and the exec-ctx census fixtures;
one changeset (@objectstack/restpatch).
No transport file changed, because both transports already write absent in the unpublished-app envelope. check-governed-merges --pr 20527: NOT governed; +117 −15.
H0, the reader, measured first:
The only wire reader of /layers is objectui's MetadataClient.layered at pin dd3f7e1b, which already maps a 404 to the four null layers. Its 15 call sites are all authoring screens.
The SDK has no layered reader.
Nothing depends on the 200, so the absent name now answers the plain read's 404 RESOURCE_NOT_FOUND, as the grade directs.
Review route: changeset prose is a contract-review surface. The at-tier record on the PR is PASS at this head, and made four explicit judgments:
A member now gets the same status and body for an absent name and an unpublished one, on both spellings and both transports.
A published item, and a builder's read of an unpublished item, are unchanged.
The reader search holds, re-measured on objectui at the pin.
The two edited tests keep their intent. The one removed assertion pinned the defect's answer.
The seat verified its transcript: served at CONTRACT_REVIEW_TIER, read-only, no GitHub write.
Evidence:
The new pins run red on the unfixed chain (6 failed, 4 passed).
Ablation reddens exactly the 6 absent-name pins, and the restore was proven.
GetMetaItemLayeredResponseSchema.effective's describe text (「null when the item resolves to nothing at all」) still describes the protocol method's in-process return, which is unchanged. On the REST wire, that case is now the route's 404. Acceptance notes: a describe-precision item in the spec seat's surface. It is not false of the schema's own subject, so it is not a published defect.
Next: landing once the remaining checks complete green, as markPullRequestReadyForReview + enablePullRequestAutoMerge (SQUASH) as objectstack-fleet[bot].
Merged through the merge queue: readied and armed 2026-09-28T23:38Z, merged 2026-09-28T23:55Z. The landing is a squash (git rev-list --parents -n 1 gives 2 fields), and it is an ancestor of origin/main.
Content read on origin/main:createMetaLayeredAnswer in packages/rest/src/meta-item-read-gate.ts refuses a read with no layer present as absent (present.length === 0, 1 hit). A member now gets the same 404 for an absent name as for an unpublished one, on both spellings and both transports, per ADR-0045 §3.
Card: closed completed by the PR's Fixes #20507. pm:dispatched is stripped in this stroke; security, area:access, domain:cli and the type label stay.
Activity
objectstack-fleet commentedon Sep 28, 2026
Path: permissions that actually hold — what is hidden stays unobservable | 缺项 (the layered view answers an absent name 200, an unpublished one 404) | P2
Triage: first grade —
bug·security·priority:p2·domain:cli·area:access·pm:queue. Direction: the shared chain answers an absent name with the same refusal as a hidden oneTriage: lands in
packages/rest/src/meta-item-read-gate.ts(createMetaLayeredAnswer,:2586onorigin/main), the one post-read chain both transports call since PR #20505 landed ⇒domain:cli, by the lane table'spackages/restrow.Triage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-09-28T21:56Z. ⛔ Not a claim, ⛔ not a dispatch.Why p2, with
security. ADR-0045 §3 declares a hidden item externally unobservable on every surface, and the plain read keeps that promise (404 for both). The layered view breaks it: a member can tell that an unpublished app exists. What leaks is existence only, not content or events. So it sits below #20378 and #20441 (p1 ·security), which served draft content and draft-save events.First step: measure the reader. The dev named Studio's designer as the candidate that may read 200-with-nulls for an unsaved item. Measure it before changing the answer.
RESOURCE_NOT_FOUND, in the shared chain, once for both spellings and both transports.Pins: as a member,
/layersand?layers=trueanswer the same status and body for an absent name and an unpublished one, and a published item's control is unchanged. Cover both transports.Not serial. PR #20505 (#20478) merged at 2026-09-28T20:54Z and built the shared chain this fix goes in.
objectstack-fleet commentedon Sep 28, 2026
Claim: PM loop round 1 of the
domain:cliseat's sessionlocal_1d2a197c:priority:p2·security, the older of the lane's two queued p2 cards (batch2, beside #20516)Session:
local_1d2a197c-c20e-4e90-9be8-413d4d432289Account:
hotlongBranch:
claude/issue-20507-layers-absent-name-oracleWorktree:
objectstack-issue-20507Domain:
domain:cliSeat:
domain:cli#1File surface:
packages/rest/src/meta-item-read-gate.ts:createMetaLayeredAnsweronly (the absent-name answer, once for both spellings and both transports);packages/rest/src/rest-server.tsandpackages/runtime/src/domains/meta.ts: only if a transport's envelope mapping of the new refusal needs a line;packages/rest/src/andpackages/runtime/src/domains/;.changeset/20507-*.md.Read-only:
packages/metadata-core/**,packages/metadata-protocol/**,packages/spec/**,packages/core/**. Stop on breach and explain in the reportContainer & model:
S,mode:subagent,model: default tier.Clause-②: no
Thread-read: 5879479871
Serial constraints cleared:
The file lists of all open PRs were read in this act: none touches meta-item-read-gate.ts or runtime meta.ts. PR #20518 (the /diff default range) and PR #20512 (the OpenAPI info) touch other regions of rest-server.ts, which is ordinary same-file concurrency: merge main on conflict. The predecessor PR #20505 (#20478) landed at 9449512a. #20516 (this seat, beside) is in create-objectstack, disjointTaken 2026-09-28T22:45Z,
origin/mainfb194c70e. Executes triage's grade (5879479871): measure the reader first (Studio's designer), then answer an absent name as a hidden one is answered (404RESOURCE_NOT_FOUND) in the shared chain, and ⛔ never keep the 200 for members.Clause-②: no: a door is pulled back to the declared contract, ADR-0045 §3.objectstack-fleet commentedon Sep 28, 2026
os-dev-report
{
"issue": 20507,
"status": "done",
"branch": "claude/issue-20507-layers-absent-name-oracle",
"pr": "#20527",
"session": "local_1d2a197c-c20e-4e90-9be8-413d4d432289 (the harness's CLAUDE_CODE_HOST_SESSION_ID, as the dispatch named it; commit trailers read Claude-Session: https://claude.ai/code/session_local_1d2a197c-c20e-4e90-9be8-413d4d432289)",
"premise_still_valid": true,
"summary": "createMetaLayeredAnswer (packages/rest/src/meta-item-read-gate.ts), the one post-read chain both transports call, now refuses a layered read with no layer present as 'absent', before the per-caller gate. It runs once, for both spellings on both transports. RestServer and the dispatcher already write 'absent' in the envelope they use for an unpublished app, so no transport file changed. H0: nothing depends on the 200. The only wire reader is objectui's MetadataClient.layered (metadata-client.ts:1289-1304 at pin dd3f7e1b), which already maps a 404 to the four null layers. Its 15 non-test call sites are all Studio or metadata-admin authoring screens. H1: re-measured, the old answers were 200-with-nulls against 404. H2: a builder now gets 404 RESOURCE_NOT_FOUND for an absent name and is still served an unpublished app. H3: under ablation, exactly the six absent-name pins went red, and the restore was proven. Worktree teardown follows this report.",
"tests": "At final head 32de5e6 (origin/main merged, closure rebuilt with pnpm --filter '@objectstack/runtime...' build): pnpm --filter @objectstack/rest exec vitest run --maxWorkers=2 gave 222 files / 4239 tests passed (40 skipped), both projects; pnpm --filter @objectstack/runtime exec vitest run --maxWorkers=2 gave 289 files / 4897 passed (1 skipped), both projects; pnpm --filter @objectstack/rest --filter @objectstack/runtime typecheck exited 0, with both check:test-typecheck: OK. New pins are in packages/runtime/src/domains/meta-list-projection-parity.test.ts (both transports): 4 member cases where an absent name and an unpublished app answer the same, 4 published-app controls, and 1 case where every caller gets 404 and a builder is still served launchpad. H1, the pins run on the unfixed chain (fb194c7): 6 failed, 4 passed; the absent name answered 200 with code/overlay/effective null plus lock/editable/deletable/resettable, and launchpad answered 404 RESOURCE_NOT_FOUND. H3 ablation: scripts/ablation-replace.mjs, WRAP mode, --delete of the new branch: anchor 1 to 0, blob 662d87187124 to af0967c88051. rest resolves from source (runtime vitest aliases @objectstack/rest to ../rest/src/index.ts), so dist was not on the path. Under the mutation, runtime full: 6 failed / 4885 passed, the 6 being exactly the absent-name pins, with all 4 controls green; rest full: 221 files passed. Restore: blob after restore == HEAD 662d87187124, git diff HEAD empty, git status --porcelain empty. Fixture triage: the parity ?package= case moved to crm?package=elsewhere (200, code null, overlay answers), and payroll?package=crm became an absence pin. The execctx census Proxy double gained a real getMetaItemLayered shape so its /layers row still measures 'serves on its own reading'.",
"mcp_calls": "0",
"api_writes": "3: (1) draft PR create, gh pr create under with-fleet.sh (gh's own transport), PR #20527; (2) POST /repos//issues/20527/assignees returned 201 through label-write.mjs, read back as hotlong; (3) POST /repos//issues/20507/comments, this os-dev-report comment, through post-stamped.mjs. Also 7 git pushes through with-fleet.sh --kind 'git push' (not REST).",
"open_questions": [],
"out_of_scope_findings": [
"carrier: the spec seat. GetMetaItemLayeredResponseSchema.effective's describe text in packages/spec/src/api/protocol.zod.ts says 'null when the item resolves to nothing at all'. Through the REST route that case now answers 404 instead of a body; the text still describes the protocol method's in-process return. It is outside this card's file surface (packages/spec/** read-only). Noted in the PR's Acceptance notes, not filed. Dedupe words: layered response effective null describe, GetMetaItemLayeredResponseSchema effective 404, layers absent name spec text"
],
"gates": "dispatch-gates --repo objectstack-ai/objectstack --commands, derived at 32de5e6: 61 families; 60 exited 0; pnpm check:dual-build-cjs-loads exited 3 (PREREQUISITE NOT MET: 36 packages have no dist) = NOT MEASURED. A narrowed probe showed require('packages/rest/dist/index.cjs') loads and exports createMetaLayeredAnswer. --ran reconciliation: '61 derived famil(ies) accounted for — 60 run, 1 NOT-MEASURED'. node scripts/check-issue-citations.mjs --base origin/main, after the merge: exit 0, 5 of 5 citations resolve. pnpm lint at 32de5e6: exit 0 in 35s. CI status: in_progress, not awaited.",
"line_budget": "132 changed lines (+117 / -15) across 4 files, against the 5000-line human-merge threshold: under.",
"deviations": [
"os-verify-lock.sh ran in its declared UNLOCKED mode for every build and test (no flock on this macOS host); its disclosure is pasted verbatim in the PR body.",
"pnpm check:dual-build-cjs-loads is NOT MEASURED: it needs a whole-repo pnpm build, which was not run on this shared host. The diff changes no import, export or module format. A narrowed CJS-load probe was run on the one package whose dist changed (@objectstack/rest).",
"The first label-write call ran without the fleet token in its environment and exited 3 (PREREQUISITE NOT MET; the tool states nothing was read and nothing was written). The re-run under with-fleet.sh made the one assignee write.",
"packages/qa/http-conformance and packages/qa/dogfood were not run locally and are left to CI. By git grep, neither makes an HTTP read of the layered view for an absent name.",
"PR assignee only; no labels were written, since the dispatch named none and the diff carries a patch changeset."
],
"files_changed": [
".changeset/20507-layers-absent-name-oracle.md",
"packages/rest/src/meta-item-read-gate.ts",
"packages/rest/src/execctx-consumer-census.test.ts",
"packages/runtime/src/domains/meta-list-projection-parity.test.ts"
]
}
Generated by Claude Code
objectstack-fleet commentedon Sep 28, 2026
ACCEPT: PR #20527 at
32de5e64, R1 of thedomain:cliseat's new sessiondomain:cliexecution PM seat #6024 · sessionlocal_1d2a197c-c20e-4e90-9be8-413d4d432289· review of record, written 2026-09-28T23:34ZReviewed against GitHub and
origin/main, not against the report.Checklist:
PR shape: draft, base
main. The first line isFixes #20507, followed by a line-initialClause-②: no. A scan of the whole body finds one closing keyword,Fixes #20507.Scope: 4 files, all inside claim
5880083725:createMetaLayeredAnswer: no layer present answersabsent, before the gate;@objectstack/restpatch).No transport file changed, because both transports already write
absentin the unpublished-app envelope.check-governed-merges --pr 20527: NOT governed; +117 −15.H0, the reader, measured first:
/layersis objectui'sMetadataClient.layeredat pindd3f7e1b, which already maps a 404 to the four null layers. Its 15 call sites are all authoring screens.RESOURCE_NOT_FOUND, as the grade directs.Review route: changeset prose is a contract-review surface. The at-tier record on the PR is PASS at this head, and made four explicit judgments:
The seat verified its transcript: served at
CONTRACT_REVIEW_TIER, read-only, no GitHub write.Evidence:
Out-of-scope findings, one line each:
GetMetaItemLayeredResponseSchema.effective's describe text (「null when the item resolves to nothing at all」) still describes the protocol method's in-process return, which is unchanged. On the REST wire, that case is now the route's 404.Acceptance notes: a describe-precision item in the spec seat's surface. It is not false of the schema's own subject, so it is not a published defect.Next: landing once the remaining checks complete green, as
markPullRequestReadyForReview+enablePullRequestAutoMerge(SQUASH) asobjectstack-fleet[bot].objectstack-fleet commentedon Sep 28, 2026
Landed: PR #20527 →
b43a814d49domain:cliexecution PM seat #6024 · sessionlocal_1d2a197c-c20e-4e90-9be8-413d4d432289· landing record, written 2026-09-28T23:57Zgit rev-list --parents -n 1gives 2 fields), and it is an ancestor oforigin/main.origin/main:createMetaLayeredAnswerinpackages/rest/src/meta-item-read-gate.tsrefuses a read with no layer present asabsent(present.length === 0, 1 hit). A member now gets the same 404 for an absent name as for an unpublished one, on both spellings and both transports, per ADR-0045 §3.completedby the PR'sFixes #20507.pm:dispatchedis stripped in this stroke;security,area:access,domain:cliand the type label stay./meta/:type/:name/layers,?layers=true) answers an absent name 200 with every layer null, where an unpublished app answers 404: an existence oracle against ADR-0045 §3 #20507 and [finding]scaffold-e2e-boot-probe.test.tsboots its stub server on an advisorypickFreePort(38700)inside the Linux ephemeral range — "accepts the server it booted itself" exits 1 under load and dropped PR #20506 from the merge queue #20516 (landed a minute later) left the opendomain:cliset.fix(rest): the layered view answers an absent name with the plain rea…