Skip to content

refactor(metadata-protocol): move getDiscovery's body into its facet, and settle the card's last facade-gate rows - #31177

Merged
objectstack-fleet[bot] merged 6 commits into
mainfrom
claude/issue-30147-phase3b-getdiscovery
Nov 7, 2026
Merged

objectstack-fleet[bot] merged 6 commits into
mainfrom
claude/issue-30147-phase3b-getdiscovery

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

Requested by 田騏 · project thread

Fixes #30147

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:把 getDiscovery 的方法体从 protocol.ts 搬进所在分区的 facet(ProtocolDiscoveryAndBasesFacet),类上只留签名和一行委托;并按裁决 6687801899 收尾 facade 门禁登记表里这张卡名下剩下的行。
  • 为什么改:这是本卡最后一个 PR。getDiscovery 靠 typeof this.searchAll === 'function' 决定是否对外宣告"支持搜索",codemod 的 host 转发会让这个判断恒为真,所以手工搬:类上读实例自己的 searchAll 再交给 facet 判断。
  • 风险与回滚:纯搬移,方法体除搜索探针改读参数外不变(撤销证明可逐字节重建中间态 X);公开 index.d.ts / index.d.cts 与 main 逐字节相同;回滚即 revert 本 PR。
  • 先看:packages/metadata-protocol/src/protocol.ts 中 getDiscovery 的存根(传 this.searchAll 那一行);protocol-discovery-and-bases.ts 中 facet 的 search: typeof searchAllOnInstance === 'function';scripts/facade-delegation-registry.json 的 8 处改动。
  • 两分钟验证:pnpm check:facade-delegation-only,预期末行 5 facade class(es) in 3 file(s) hold delegations only, 15 named exception(s).,退出码 0。
  • 需要你做的:无,席位落地。

What changes

getDiscovery, a hand move in three commits. The codemod's members pass
refuses this member on main: its body reads the instance method searchAll
as a value to set capabilities.search, and a host entry forwards a method
through a closure that is always a function, so a moved probe would advertise
search on every host. The route the card records (dev report 6686885545,
phase_3b):

  1. 43df6766ff is the intermediate X: the probe reads a parameter,
    searchAllOnInstance, instead of this.searchAll. Not a landing state on
    its own (the public signature carries the parameter there).
  2. 4a2e27e428 is node scripts/codemod-split-protocol.mjs --members getDiscovery --write
    run on X, unedited: the body goes to ProtocolDiscoveryAndBasesFacet by
    the E1 form (460 body lines), and the stub forwards protocolHost(this)
    and the parameter.
  3. e87a512b0e is the hand edit: getDiscovery() takes no parameter again,
    so its signature is main's byte for byte, and the stub hands the facet
    this.searchAll, read on the instance. The facet keeps
    typeof searchAllOnInstance === 'function'. The stub also gains a
    two-line comment that says why.

host-split.mjs's refusal of a method read as a value is unchanged.

The registry (scripts/facade-delegation-registry.json), per ruling
6687801899:

engine.ts and sql-driver.ts are not touched.

A patch changeset for @objectstack/metadata-protocol: the package's
built JavaScript changes (the body now runs from the facet module) while its
public .d.ts does not, and Metadata-protocol: none takes patch.

Tests

No test file changes. Measured on the final head 56dbba9841 (this branch
merged with main 56baf78e0c; the merge touched neither package):

  • @objectstack/metadata-protocol vitest: 321 files passed, 4 skipped;
    22,525 tests passed, 26 skipped. typecheck exit 0, build exit 0.
  • packages/rest vitest (it loads @objectstack/metadata-protocol
    through the built dist/, rebuilt from this head): 398 files, 7,782 tests
    passed, 354 skipped. discovery-search-capability-agreement.test.ts 4/4.
  • The same two suites on e87a512b0e (before the merge) gave the same counts.
  • Negative control: the stub handed a host-style forwarding closure
    instead of this.searchAll; the package rebuilt and the closure confirmed
    in dist/index.js and dist/index.cjs (ablation-dist-preflight.mjs);
    discovery-search-capability-agreement.test.ts failed 2 of 4 ("agrees on a
    protocol that cannot search" and the anti-vacuity case). Restored from
    HEAD (blob hash equal, git diff HEAD empty), rebuilt, the closure
    absent from dist/: 4/4 again.

Acceptance notes

  • The .d.ts bar. dist/index.d.ts and dist/index.d.cts built from
    main af3451b08b's two source files and from this branch's are byte-equal
    (sha256 1b94b057e16e19b5… on all four). getDiscovery is public with a
    written return type and no docblock, so nothing moved out of the printed
    declaration.
  • Reproducing the generated commit. git checkout 4a2e27e428 and
    node scripts/codemod-split-protocol.mjs --members --verify --base 43df6766ff
    exits 0. On the head the same command exits 1, naming exactly the
    hand-edited stub and signature (expected; that is the third commit).
  • triggerAutomation's reason now reads "accepted terminal exception
    (ruling 6687801899): accepted exception (Facade codemods: retire the codemod-limit exception rows in the facade gate registry (protocol.ts, engine.ts, sql-driver.ts) #30147 phase 3): …": the order was
    to prefix and keep the reason already written, and that reason already
    opened with its own label. A one-word tidy is the seat's call.
  • No open pull request touches packages/metadata-protocol/src/protocol*.ts
    or the registry that this branch could collide with; fix(objectql)!: a non-system write may name, in a lookup or user field, only a record the caller can read #30747 (engine.ts) is
    untouched here.

Verification

Suites on the final head

One locked run at 56dbba9841: pnpm --filter @objectstack/metadata-protocol build exit 0, typecheck exit 0, exec vitest run --maxWorkers=2 exit 0 (Test Files 321 passed, 4 skipped; Tests 22,525 passed, 26 skipped); pnpm --filter @objectstack/rest exec vitest run --maxWorkers=2 exit 0 (Test Files 398 passed; Tests 7,782 passed, 354 skipped); discovery-search-capability-agreement.test.ts verbose: 4 passed (the ordinary host, a host that does not mount the route, a protocol that cannot search, anti-vacuity).

Undo proof against X

node scripts/codemod-split-protocol.mjs --members --verify --base 43df6766ff on the tree of 4a2e27e428: exit 0.

undo proof (#30518, #30147): 1 moved member(s) (getDiscovery); forms: e1 1; host-split check: 1/1 E1 move(s) pass (the receiver forms move bodies unedited, proved byte-equal); protocol.ts 12606 -> 12147 lines; undoing the moves does rebuild the base protocol.ts, protocol-host.ts and section modules byte-for-byte once the 15 import binding(s) only moved bodies read are pruned from the base (ApiRoutes, CHANNEL_SURFACE_SLOTS, CORE_SERVICE_PROVIDER, CapabilityDescriptor, SERVICE_CONFIG, ServiceInfo, WellKnownCapabilities, engineCanRollBack, isSubscribableChannel, readAuthFamilies, readChannelRoute, readServiceSelfInfo, resolveDiscoveryEnvironment, resolveDiscoveryVersion, serviceUnavailableMessage)
Facade gate

pnpm check:facade-delegation-only at 1a84657c25: exit 0, 5 facade class(es) in 3 file(s) hold delegations only, 15 named exception(s).

dispatch-gates

node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at 56dbba9841: 65 families derived, all 65 run after a full pnpm build (plus a rebuild of the packages the main merge touched), every one exit 0, codes captured before any pipe. --ran: 65 derived, 65 run, 0 NOT-MEASURED (a derived zero: all 65 recorded an exit code), 0 UNRUN. pnpm --filter @objectstack/spec check:generated: all 14 artifacts up to date (a first run reported check:test-typecheck as tsc failed without diagnostics on a contended box; the gate alone and the re-run both pass). eslint on the two changed source files: exit 0.

Changed lines

1,033 changed lines (+554 / -479, 4 files, changeset included), under the 3,000 budget.

Session: https://claude.ai/code/session_017ihL2ebbZkr2QAEG1x7UC8

🤖 Generated with Claude Code

…obe reads a parameter

The codemod's members pass refuses getDiscovery on main: its body reads
the instance method searchAll as a value (`typeof this.searchAll`), and
a host entry forwards a method through a closure that is always a
function. This intermediate makes the probe read a parameter,
searchAllOnInstance, so the members pass can move the body; the next
commit is the pass's output on this tree and the commit after it the
hand edits that remove the parameter from the public signature again
(the stub passes this.searchAll, read on the instance).

`node scripts/codemod-split-protocol.mjs --members --verify --base X`
proves the generated commit against this one. Not a landing state on
its own: getDiscovery's public signature carries the parameter here.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ihL2ebbZkr2QAEG1x7UC8
…(codemod output on X)

`node scripts/codemod-split-protocol.mjs --members getDiscovery --write`
run on the intermediate X (the previous commit), unedited. The body goes
to ProtocolDiscoveryAndBasesFacet in protocol-discovery-and-bases.ts by
the E1 form; the stub forwards protocolHost(this) and the parameter.

`--members --verify --base X` exits 0: 1 moved member, host-split 1/1
E1, undoing the move rebuilds X's protocol.ts, protocol-host.ts and
section modules byte for byte (15 import bindings pruned). The next
commit is the hand edit that takes the parameter off the public
signature again.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ihL2ebbZkr2QAEG1x7UC8
…he instance (hand edits)

The hand edits on top of the codemod output:

- protocol.ts: getDiscovery takes no parameter again (its public
  signature is main's), and the stub hands the facet `this.searchAll`,
  read on the instance. The facet keeps
  `typeof searchAllOnInstance === 'function'`, so capabilities.search
  still answers whether this instance serves search; a host entry would
  have forwarded the method through a closure that is always a function.
- facade-delegation-registry.json, per ruling 6687801899: the
  getDiscovery row goes; triggerAutomation, sql-driver `get supports`
  and `static DIALECT_CONNECT_TIMEOUT` stay on #30147 as accepted
  terminal exceptions, each reason prefixed with the ruling; the four
  engine.ts rows are re-pointed to #30975.
- A patch changeset for @objectstack/metadata-protocol.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ihL2ebbZkr2QAEG1x7UC8
@github-actions github-actions Bot added size/xl documentation Improvements or additions to documentation tooling Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface labels Nov 7, 2026
@github-actions

github-actions Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/metadata-protocol, touching 11 documentable anchor(s).

27 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: node scripts/docs-audit/affected-docs.mjs --json 21c1f74850eade99b4cb30b86b271d6a9dbd71c7.

⛔ 12 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails.

What this run could not see
  • 2 anchor(s) matched too much of the corpus to be a work list: /api/v1/data (route, 50 pages), /api/v1/meta (route, 49 pages)
  • 1 name(s) were too generic to anchor anything (single lowercase words)
  • the SDK route bridge reached 63 of 226 client-bound route-ledger rows — the other 163 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 163: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 59 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 104 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 10 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 21c1f74850eade99b4cb30b86b271d6a9dbd71c7 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 21afdaa800c09005db431ab989580144053a1cda — the merge of head 1a84657c25aa12f010b0174281a43fd51420eb37 into base 21c1f74850eade99b4cb30b86b271d6a9dbd71c7, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 21afdaa800c09005db431ab989580144053a1cda && git checkout 21afdaa800c09005db431ab989580144053a1cda
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 21c1f74850eade99b4cb30b86b271d6a9dbd71c7 1a84657c25aa12f010b0174281a43fd51420eb37 && git checkout -B drift-repro 21c1f74850eade99b4cb30b86b271d6a9dbd71c7 && git merge --no-ff 1a84657c25aa12f010b0174281a43fd51420eb37

node scripts/docs-audit/affected-docs.mjs --json 21c1f74850eade99b4cb30b86b271d6a9dbd71c7

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 21c1f74850eade99b4cb30b86b271d6a9dbd71c7 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet

objectstack-fleet Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor Author

domain:devx#2 · marchtian · session_017ihL2ebbZkr2QAEG1x7UC8

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 1a84657c25aa12f010b0174281a43fd51420eb37
Local-runs: none
Scope: .changeset/30147-get-discovery-facet.md, packages/metadata-protocol/src/protocol-discovery-and-bases.ts, packages/metadata-protocol/src/protocol.ts, scripts/check-facade-delegation-only.mjs, scripts/facade-delegation-registry.json + packages/metadata-protocol/src/protocol-host.ts, packages/metadata-protocol/src/discovery-version.ts, packages/metadata-protocol/src/protocol-discovery-services.ts, packages/metadata-protocol/src/plugin.ts, packages/rest/src/discovery-search-capability-agreement.test.ts, scripts/codemod-split-protocol.mjs, scripts/pm/check-governed-merges.mjs, #30975

Round 1 was judged at 56dbba9841; Round 2 below carries it to the head named above.

Read: git diff origin/main...refs/review/pr-31177 (origin/main 21c1f74850, merge base 56baf78e0c), the three per-commit diffs (43df6766ff, 4a2e27e428, e87a512b0e) and the merge 56dbba9841; card #30147 body and all 20 comments (6686885545, ruling 6687801899, 6690277174, 6690327117, 6708253429, 6709547182 among them); PR #30954 (merged as 26f571911c) and its changeset; #30975; the head's check-runs. Nothing built, tested or re-run; the codemod's --verify was not re-run (read-only), so its byte proof is judged by reading, below.

① Derived judgments

1. Behaviour preserved — holds.

  • Moved body: main's getDiscovery body (protocol.ts 2525–2985 on main) and the facet's body (protocol-discovery-and-bases.ts 146–603 at head) differ in exactly four lines: this.getServicesRegistry ×2 → host.getServicesRegistry, this.engine ×2 → host.engine (the E1 closed set), and typeof this.searchAll === 'function' → typeof searchAllOnInstance === 'function'. No other byte of the body changed, so the services map, routes, capability flags and their key order are main's.
  • host.engine and host.getServicesRegistry are getters in the class's static host factory (protocol.ts 1227, 1249) that read the instance field at call time; protocol-host.ts is untouched. Calling host.getServicesRegistry() rebinds this from the instance to the host, but the only production caller passes an arrow (plugin.ts 249–251), and three facets on main already call it this way (protocol-class-head.ts 87, protocol-discovery-and-bases.ts 549, protocol-meta-list-reads.ts 582).
  • searchAll: the stub's argument this.searchAll is a property read on the instance at each call. An own-property shadow (the test's Object.defineProperty(protocol, 'searchAll', { value: undefined }), line 104), a subclass override or a prototype replacement is seen exactly as main's in-body read saw it. The facet only applies typeof, so passing the method unbound loses nothing. main's body has no await before the probe, so reading searchAll at stub entry instead of mid-body observes the same state. This is the property discovery-search-capability-agreement pins; the host-closure route the gate row warned about is not taken.
  • Stub: the signature is byte-identical to main's (51 lines compared, async kept, the written return type with its @deprecated key docblock), and this is the instance. A throw in the stub still becomes a rejection.
  • Imports: the 15 bindings pruned from protocol.ts have zero remaining uses there. Each is used in the facet body and imported by the facet. The new facet imports (discovery-version.ts, protocol-discovery-services.ts) do not import protocol.ts, so no cycle is added.
  • No by-path reader of the moved text exists: the auth-families pins, transactional-batch honesty, openapi and conformance tests do not read source, and no script reads getDiscovery out of protocol.ts.

2. Codemod honesty — holds, by reading.

  • 43df6766ff (X) changes exactly two lines of protocol.ts: the parameter searchAllOnInstance: unknown and the probe.
  • 4a2e27e428 has the members pass's E1 shape and nothing else. protocol.ts: four import hunks, plus the body replaced by the standard [#29985 codemod] marker and return ProtocolDiscoveryAndBasesFacet.getDiscovery(protocolHost(this), searchAllOnInstance). Facet: header list gains getDiscovery, the import block is added, and a /** The body of … */ static carries X's body under the E1 rewrites. These are the same marker and docblock forms as the getProjectId sibling and feat(scripts): codemod-split-protocol --members moves the bodies E1 refuses, unedited, and retires nineteen protocol.ts facade rows #30954's E1 moves. A byte re-run was not possible here; the body diff above is the closed set and nothing more.
  • e87a512b0e touches only what the recipe names (6686885545 phase_3b, 6690327117). In protocol.ts it restores main's signature and hands in this.searchAll; it also adds a two-line why-comment, which is benign. The facet is untouched. It also carries ruling 6687801899's registry edits and the house-rule changeset.
  • X leaves nothing unintended in the net diff. The public signature is main's again, and the facet parameter is the intended carrier. The merge 56dbba9841 touches none of the four PR files.

3. Registry against ruling 6687801899 — holds.

4. Public surface — unchanged, by reading. getDiscovery keeps its written return type on the class. ProtocolDiscoveryAndBasesFacet is not exported from the package entry (the exports map is . only, and only protocol.ts imports the facet), and no public type gained or lost a member. The changeset is '@objectstack/metadata-protocol': patch with Clause-②: no and Metadata-protocol: none, which is the house rule: kind none takes patch, and the built JS of a released package changes. It matches #30954's changeset shape.

5. Landing.

  • The body carries Fixes #30147 and Clause-②: no, and the changeset repeats both declaration lines.
  • The body matches the tree at head: four files, the three commits as described, the registry edits as listed, and engine.ts and sql-driver.ts untouched (absent from the diff).
  • The PR is not governed. None of the four paths matches a GOVERNED_SURFACES row, and the Governed Surface Queue Guard is green.
  • Ruling 6687801899 says the card closes when this PR lands, and it does.

Check-runs at head (polled 2026-11-07T16:12Z):

  • Green: Lint & Repo Gates; all Lint jobs, including CI, release & engine gates, ESLint, docs & code guards, repo & tooling gates, PM dispatch-gates and the scoped jobs; Type Check · source gates and · debt ledger; Check Changeset; Check PR Size; Governed Surface Queue Guard; PR-body guards; Dogfood Regression Gate; Live E2E UI; Test UI; Plan Test Core shards; Auto Label; Flag docs; filter.
  • Still in progress: Build Core, Test Core 1/8–8/8, Type Check · workspace and · consumer gates. Those verdicts are not yet in, and landing waits on them in any case.

Must-fix: none.

Should-fix:

  • S1 (protocol.ts 13–14): the codemod pruned import { resolveDiscoveryVersion } but left its two-line comment. "[commit 376c70f] The derived version this file's getDiscovery() serves…" now annotates the MetadataHostEngine import and misstates where the body lives. Delete it, or move it above the facet's resolveDiscoveryVersion import, as one more hand edit.
  • S2 (scripts/check-facade-delegation-only.mjs, ## Exceptions — named, carded, and dead once their card lands): after this PR lands, three rows cite a card that is closed and will never move them. The gate's prose still says every row names "the card that will move it" (ruling 6624345766 item 3). Add one sentence naming the accepted-terminal class and ruling 6687801899, so the rule and its gate read as one. This can be done here or as a follow-up.
  • S3 (PR body): "17 to 16 exceptions" and the two-minute check's expected 16 named exception(s) are true at merge base 56baf78e0c. On current main (after refactor(objectql): move the ObjectQL constructor body into the hooks-and-functions facet (E3) #31151) the landed tree prints 15. Refresh the line, or note it.

② Semver level

patch on @objectstack/metadata-protocol: a private body moves, the built JS changes, and the public .d.ts is unchanged. Metadata-protocol: none; no other package publishes a change. scripts/facade-delegation-registry.json is repo tooling and is not published.

③ Boundary flags

④ Design judgment

The move holds against the code it cites and its scenario. The hazard the registry row recorded was real: a host entry forwards a method through a closure that is always a function, so capabilities.search would always read true. The PR does not route the probe through the host. The class reads the member on the instance, the one place main read it, and hands the value to a facet that only asks typeof. That is the smallest deviation from the E1 form that keeps capabilities.search and the /search route answering one predicate (#7541). It also leaves host-split.mjs's refusal of a method read as a value intact, so no general rule was loosened for one member.

The registry edits implement ruling 6687801899 as written. The three terminal rows are justified on their own reasons: a one-statement facet, a public declaration change, and a class-evaluation-order hazard. #30975 holds the engine rows with its plan.

The should-fix items are hygiene. None changes what the code does.

Round 2 delta (56dbba9841 → 1a84657c25)

Read: git diff 56dbba9841..1a84657c25, the non-merge commit 2bb03299ef, the merge 1a84657c25 (parents 2bb03299ef and 21c1f74850), dev delta report 6710190320, the live PR body, and the check-runs on the new head.

  1. S1–S3 are resolved.
    • S1: the commit-376c70f98 comment is deleted from protocol.ts and now sits directly above the facet's import { resolveDiscoveryVersion }, reworded "this facet's getDiscovery()".
    • S2: one sentence was added to the gate header's Exceptions section.
    • S3: main 21c1f74850 is merged in. The live PR body now reads "16 to 15 exceptions, on main after refactor(objectql): move the ObjectQL constructor body into the hooks-and-functions facet (E3) #31151" and expects 15 named exception(s) at 1a84657c25. The seat patched the body; the dev's report says the dev deliberately did not.
  2. The S2 sentence is accurate against the gate's logic.
  3. The merge conflicts with nothing.
  4. Nothing else changed. Between the two heads, the PR's own files differ only by 2bb03299ef: +2/−2 comment lines in metadata-protocol and +4/−1 comment lines in the gate header. The registry change in that span is the constructor-row deletion from main. Everything else in the span is main's, unchanged. The net PR diff is now 5 files, +560/−482. No code, signature, registry row or changeset line changed this round, so Round 1's findings ①–④ stand.

Check-runs at 1a84657c25 (polled 2026-11-07T16:54Z):

  • Green: Build Core; Test Core 1/8–8/8 and the Test Core rollup; TypeScript Type Check and Type Check · workspace, consumer gates, source gates and debt ledger; every Lint job, including CI, release & engine gates, where the facade gate runs; Governed Surface Queue Guard; both PR-body guards runs; Dogfood Regression Gate; Live E2E UI; Test UI; Check PR Size; one Check Changeset run.
  • In progress: a second Check Changeset run, most likely started by the body edit.

Must-fix: none. Should-fix: none open; S1, S2 and S3 are resolved.

Implemented-by: claude/issue-30147-phase3b-getdiscovery
Reviewed-by: session_017ihL2ebbZkr2QAEG1x7UC8

Final verdict, at head 1a84657c25aa12f010b0174281a43fd51420eb37:

VERDICT: PASS

…t to the facet; name accepted terminal rows in the facade gate header

- protocol.ts kept the commit 376c70f comment that annotated its
  resolveDiscoveryVersion import after the members pass moved that
  import to the facet, so the comment sat above an unrelated import.
  It now annotates the facet's import of resolveDiscoveryVersion and
  names the facet.
- check-facade-delegation-only.mjs's header said every exception row
  names the card that will move it; it now also says a row may be an
  accepted terminal exception that cites the maintainer ruling which
  accepted it and stays after its card closes. Comment only, no gate
  logic change.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ihL2ebbZkr2QAEG1x7UC8
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:devx#2 · marchtian · session_017ihL2ebbZkr2QAEG1x7UC8

维护者速读

  • 改了什么:把 getDiscovery 从 protocol.ts 门面类搬进发现能力的分面模块,门面只留一行委托。门面例外登记表同步更新,例外从 16 项降到 15 项:
  • 为什么改:门面瘦身卡 Facade codemods: retire the codemod-limit exception rows in the facade gate registry (protocol.ts, engine.ts, sql-driver.ts) #30147 的最后一步(phase 3b)。完成后协议门面类里只剩委托和已登记的例外。
  • 风险与回滚:
    • 纯私有成员搬家,公开 .d.ts 与 main 逐字节相同。
    • 搜索能力的探测仍在调用时读实例上的 searchAll,子类或测试覆盖照样生效。
    • 反向对照已验证:故意改成宿主闭包时,rest 的发现搜索测试会变红。
    • 回滚:整体 revert 本 PR。
  • 先看:protocol.ts 里 getDiscovery 的委托桩,分面模块里搬过去的函数体,以及 scripts/facade-delegation-registry.json 的改动。
  • 两分钟验证:运行 pnpm check:facade-delegation-only,预期末行为 15 named exception(s),退出码 0。
  • 需要你做的:无。本 PR 不涉及受管面,席位在 CI 全绿后自行落地。复审已通过:Opus 审查 PASS 6709647239,Head-sha 1a84657c25。

席位意见:可以落地。行为不变的证据完整,包括函数体逐行对照、公开类型逐字节一致、反向对照。第一轮的 3 项应改已在第 2 轮全部修好,增量复审通过。

席位核对 — ACCEPT · domain:devx#2 · Head-sha 1a84657c25aa12f010b0174281a43fd51420eb37 · 2026-11-07T16:56Z

  • Shape: 5 files, +560/−482, the bulk being the moved body. The seat read the diff, not the report.
    • protocol.ts: the getDiscovery stub keeps main's signature and passes this.searchAll. 15 dead imports are removed.
    • The facet (protocol-discovery-and-bases.ts): carries the body. Exactly four lines differ from main's body: this. becomes host., and the search probe reads its parameter.
    • scripts/facade-delegation-registry.json: edited per ruling 6687801899 — getDiscovery row removed, three accepted terminal rows citing the ruling, four engine.ts rows re-pointed to objectql engine.ts: retire the four facade-gate exception rows #30147 hands over #30975.
    • scripts/check-facade-delegation-only.mjs: one header comment sentence on terminal rows.
    • A patch changeset.
  • How it was built: the commits show an intermediate X, the unedited codemod output, then the hand edits. --members --verify --base X exits 0, and the undo is byte-for-byte.
  • Review: this is code outside spec, skills and ADR, so it got an Opus review under the 2026-11-07 rule.
    • Round 1 PASSed with three should-fixes: a stale import comment, the gate header, and the PR-body counts.
    • All three were fixed in round 2. The seat patched the PR body itself, with an identical read-back.
    • The round-2 delta PASSed on this head, with no findings open (6709647239).
  • Gates:
    • Head checks: 37 success, 15 skipped, none red.
    • check-expected-skips: OK, all 15 skips are in main's roster (exit 0).
    • check-governed-merges: not governed (exit 0). 1042 changed lines, which is ≤ 3000.
    • The dev's dispatch-gates --commands: 76 derived, 76 run, all exit 0, on this head.
    • Proofs on the dev's round-1 head:
      • metadata-protocol: 321 files, 22,525 tests, all pass;
      • rest: 398 files, 7,782 tests, all pass, including discovery-search-capability-agreement 4/4;
      • the negative control fails 2 of those 4.
    • The facade gate reports 15 exceptions on the merged head.
    • git merge-tree against main (8acbfab9b4) is clean.
  • Out of scope:
  • Landing: not governed, Fixes #30147 (the card's last PR). The seat marks it ready and arms auto-merge.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review November 7, 2026 16:57
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge November 7, 2026 16:57
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 7, 2026
Merged via the queue into main with commit bd81a7a Nov 7, 2026
53 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-30147-phase3b-getdiscovery branch November 7, 2026 17:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/xl tooling Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Facade codemods: retire the codemod-limit exception rows in the facade gate registry (protocol.ts, engine.ts, sql-driver.ts)

1 participant