Skip to content

feat(spec,runtime): every served package row carries disableable, the disable door's own verdict, beside writable - #28371

Merged
objectstack-fleet[bot] merged 9 commits into
mainfrom
claude/project-thread-az4bej
Oct 31, 2026
Merged

objectstack-fleet[bot] merged 9 commits into
mainfrom
claude/project-thread-az4bej

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

domain:spec#1 · os-tesla · session_01L9qibwb6hBqszPTYJobitm

Requested by Tesla · project thread

Fixes #28318

Clause-②: yes (widening)
Metadata-protocol: added
Skills-docs: follow-up #28118 (the Console half rides the doc: content/docs/deployment/marketplace-handbook.mdx "Disabling a module" names the served disableable key when the Console reads it; no skills/** page names the package read doors' verdicts — git grep -n "writable" -- skills/ names no package row)

domain:spec#1 · os-tesla · session_01L9qibzWzEjBsCfzgaacoEm

维护者速读

  • 改了什么:GET /api/v1/packages 和 GET /api/v1/packages/:id 返回的每一行包,在 writable 旁边多了一个服务端判定 disableable(布尔),回答「这个包在这里能不能停用」。已安装应用下的模块是 disableable: true、writable: false。
  • 为什么改:feat(runtime): an admin can disable a type:module package of an installed app; its nav contributions and record-change flows stop (#28117) #28308 让停用门接受「已安装应用下的模块」,但 Console 只在 writable 为真时才显示停用按钮,而模块的 writable 一直是 false,所以服务端接受的停用,界面给不出来。按裁决不能把 writable 改成两个意思,于是单独给一个键。
  • 风险与回滚:低。只是响应里多一个键,取值用的就是停用门自己问的那个判定(isDisableablePackage,门也改成通过它问),两边不可能不一致;writable 与所有写门都不变。回滚即 revert。
  • 先看:packages/runtime/src/domains/packages.ts(isDisableablePackage、withDisableableVerdict、停用门那一行);packages/spec/src/api/package-api-assembled.zod.ts(SERVED_ROW_VERDICTS);packages/runtime/src/domains/packages-disableable-verdict.test.ts(逐行一致性测试)。
  • 两分钟验证:pnpm --filter @objectstack/runtime exec vitest run --maxWorkers=2 src/domains/packages-disableable-verdict.test.ts,预期 22/22 通过:模块 disableable: true 且 writable: false,11 个包逐行「返回的 disableable = 停用门 200/422」。
  • 需要你做的:无,席位落地。

What changes

1. The key (@objectstack/spec)

SERVED_ROW_VERDICTS in packages/spec/src/api/package-api-assembled.zod.ts declared one server verdict on a served package row, writable. It now declares a second, disableable: z.boolean(), on both stage branches of InstalledPackageAtEitherStageSchema (so on ListInstalledPackagesResponseSchema and GetInstalledPackageResponseSchema too). Required, like writable, because both read doors serve it on every row. Its describe says what a client does with it: offer Disable / Enable from it, never from writable. The block comment states that neither verdict is derived from the other.

Name. disableable, as triage ruled. The spec's served boolean verdicts are named VERB-able (writable here; editable, deletable, resettable on the meta item envelope in api/protocol.zod.ts; undoable, repairable, sortable elsewhere in api/), so the convention measures the same name.

2. Serving it (@objectstack/runtime, triage's one-PR exception)

  • One predicate. isDisableablePackage(engine, id) is the disable door's verdict on a package: isDisableableAppModule(engine, id) || isWritablePackage(engine, id). The door (PATCH /packages/:id/disable) now asks it in place of isDisableableAppModule alone. That is behaviour-identical, because the refusal branch, requireWritablePackage, already answers null for a writable package. The read doors serve the same call as disableable. Neither site spells the rule.
  • Every row door that serves writable. withDisableableVerdict stamps it after the projection, beside withWritableVerdict, on the two doors that serve writable from this file: GET /packages and GET /packages/:id. The order is the same project-then-stamp order, for the same reason.
  • Package facts only. The verdict ignores the caller's own permission (manage_metadata) and a catalog wall, exactly as writable does. The door still asks both.
  • isDisableableAppModule is unchanged. Its header now says the door asks it through isDisableablePackage, in place of "the served row does not carry this verdict yet".

Tests

  • Contract (packages/spec/src/api/package-api.test.ts): disableable is required as a boolean on both stages, is declared on both branches beside writable, keeps disableable: true beside writable: false, and is stripped by both record schemas. The shared LIFECYCLE fixture gains disableable: false.
  • Runtime (packages/runtime/src/domains/packages-disableable-verdict.test.ts, new, 22 tests): a real SchemaRegistry through the real dispatcher, with an 11-package fixture set.
    • A suite module (code boot, scope: 'project') and a scope-less marketplace module of the same app: disableable: true, writable: false.
    • Controls: modules of the app in a system or cloud scope give false. A module with no dependency, one whose app is not installed, and one whose installed dependency is a plugin give false. The app, a plugin, a writable base and a system base give disableable === writable, the door's answer.
    • The detail door serves the same pair as the list door, row by row, and so does ?type=module.
    • Agreement: for each of the 11 rows, on a fresh registry, the served disableable equals the door's answer: 200 with the package disabled, or 422 WRITABLE_PACKAGE_REQUIRED with it still enabled. A non-vacuity case checks that the set holds both answers and a disableable row that is not writable.
    • The served bodies parse through ListInstalledPackagesResponseSchema / GetInstalledPackageResponseSchema with both verdicts kept. The registry's records never gain the key. Uninstalling the app turns its module's verdict to false on the next read.
  • Existing pins updated: packages-writable-verdict.test.ts pin 5 sets aside disableable by name beside writable. package-door-producer-key-carry.test.ts registers disableable in DOOR_COMPUTED_STAMPS, with its reason. That set-equality register went red on the first full run, as it is meant to when a stamp arrives without a decision.
Ablation (one-time, restored)

Through node scripts/ablation-replace.mjs under the verify lock, on packages/runtime/src/domains/packages.ts. The suite imports the dispatcher from src/, so no build sits between mutation and run. Anchor disableable: isDisableablePackage(engine, id) }, x1 → x0.

  1. → disableable: true }. Blob 24535658be09 → 6aa4c641424a. packages-disableable-verdict.test.ts: 15 failed, including the agreement case for every refused row (the app, both platform-scoped modules, the orphan, the module of an absent app, the plugin, the module of the plugin, the system base).
  2. → disableable: false }. Blob 24535658be09 → 176b3b97b534. 9 failed, including the agreement case for every accepted row (both suite modules, the writable base).

Restored after each leg: blob 24535658be09 = HEAD, git diff HEAD empty.

Package suites, typecheck, lint

Under the verify lock, after pnpm --filter '@objectstack/runtime^...' build on the merged tree:

  • pnpm --filter @objectstack/runtime --filter @objectstack/spec --no-bail test at f559c37c: spec Test Files 771 passed (771), Tests 22808 passed | 1 todo (22809). Runtime Test Files 1 failed | 489 passed (490), Tests 1 failed | 7956 passed | 19 skipped (7976). The one red was the DOOR_COMPUTED_STAMPS register (above), fixed in c2a97b40. That file and the response-conformance file then gave Tests 22 passed (22).
  • main then moved 7 commits (spec and runtime among them, feat(spec,runtime,plugin-audit): an action run through MCP leaves an audit row naming its surface #28171), merged at b4d79818. Refreshed per AGENTS.md §9 (pnpm install --frozen-lockfile, pnpm build: Tasks: 116 successful, 116 total), then in one locked run: check:generated green, typecheck exit 0, spec Tests 22808 passed | 1 todo (22809), runtime Test Files 491 passed (491), Tests 7981 passed | 19 skipped (8000), VERDICT command-exit 0.
  • pnpm exec eslint --no-inline-config on the five touched source and test files: exit 0.
  • pnpm --filter @objectstack/spec check:generated: one artifact was stale (content/docs/references/**), regenerated with --fix and re-checked green.

Acceptance notes

  • GET /api/v1/meta/package also stamps writable (packages/metadata-protocol/src/protocol.ts, getMetaItems for type: 'package'). It is a different producer: its rows are not declared with SERVED_ROW_VERDICTS, and it lives outside this card's file surface. The one predicate is private to the runtime, so serving disableable there would need the rule moved into @objectstack/metadata-protocol, which is a second card. The Console's Packages page reads /packages (PackagesPage.tsx, typed InstalledPackageAtEitherStage), which this PR serves. Noted, not filed.
  • The enable door (PATCH /packages/:id/enable) has no package gate, so any disabled package can be re-enabled. The describe therefore says "disable", and leaves the Console to offer Enable on a disabled row as it does today (writable || !enabled, read by Packages page: offer Enable / Disable on a suite's type:module rows once the server allows disabling them #28118).
  • The Console half is Packages page: offer Enable / Disable on a suite's type:module rows once the server allows disabling them #28118. This PR changes nothing under ui/. InstalledPackageRow picks source | writable from the spec type, so the new required key does not red Type Check UI.

Verification

Gates from node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack on this diff (105 commands), each run on the final head b4d79818 with stdin from /dev/null and its exit code captured before any pipe: all 105 exit 0. dispatch-gates --ran: "105 derived famil(ies) accounted for — 105 run, 0 NOT-MEASURED". On the first sweep (head f559c37c), three answered exit 3, PREREQUISITE NOT MET, and measured nothing: check-plugin-teardown-shape --self-test (shallow clone), check:skill-examples (no client dist), check:dual-build-cjs-loads (no full build). The clone was deepened and pnpm build run, and all three exit 0 on the final head. The families CI runs are cited from this PR's check-runs in the report on the card.

Human Minimum

  • 1. Schemas start as Zod; packages/spec holds no runtime logic. (The predicate lives in the runtime; spec declares the key.)
  • 2. Every name I added uses the casing for its kind.
  • 3. No formatter ran; pnpm lint passes (scoped to the touched files; the repo sweep is CI's).
  • 4. One issue, one branch off an up-to-date main, one pull request.
  • 5. A change that publishes carries a changeset (.changeset/28318-served-disableable-verdict.md, minor for spec and runtime), and both declaration lines are filled in here and in the changeset.
  • 6. packages/spec touched: its generated artifacts are regenerated and committed.
  • 7. No hand edits to content/docs/references/, packages/*/CHANGELOG.md or content/docs/releases/.
  • 8. Title, body and comments are in English (the 维护者速读 block is the seat's required Chinese summary).
  • The Before Submitting list in CONTRIBUTING.md is done.

Generated by Claude Code

@github-actions

github-actions Bot commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/runtime, @objectstack/spec, touching 5 documentable anchor(s).

4 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/api/client-sdk.mdx (via packages.disable (sdk, the route ledger binds it to PATCH /packages/:id/disable))
  • content/docs/api/metadata-api.mdx (via /packages/:id/disable (route, a path literal in a comment on a changed line))
  • content/docs/deployment/marketplace-handbook.mdx (via /packages/:id/disable (route, a path literal in a comment on a changed line))
  • content/docs/permissions/system-context.mdx (via handlePackagesRequest (symbol, a top-level function))
What this run could not see
  • 1 name(s) were too generic to anchor anything (single lowercase words)
  • the SDK route bridge reached 59 of 211 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 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 — 173 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 02d6507275eaa7d821e98585df9bb31eed8dedca → packageMentionDocs.

Which tree this was computed on

This run read content/docs from f54ef61fd48ce4dfbad4925632de2b7c86ab9e9b — the merge of head 138dbe7f222d07be15597922abcf9594a6d5f855 into base 02d6507275eaa7d821e98585df9bb31eed8dedca, 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 f54ef61fd48ce4dfbad4925632de2b7c86ab9e9b && git checkout f54ef61fd48ce4dfbad4925632de2b7c86ab9e9b
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 02d6507275eaa7d821e98585df9bb31eed8dedca 138dbe7f222d07be15597922abcf9594a6d5f855 && git checkout -B drift-repro 02d6507275eaa7d821e98585df9bb31eed8dedca && git merge --no-ff 138dbe7f222d07be15597922abcf9594a6d5f855

node scripts/docs-audit/affected-docs.mjs --json 02d6507275eaa7d821e98585df9bb31eed8dedca

⚠️ 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 02d6507275eaa7d821e98585df9bb31eed8dedca → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#1 · os-tesla · session_01L9qibw58ehQ2gRHP2h2Puz

Contract-review-claim: session_01L9qibw58ehQ2gRHP2h2Puz · head b4d79818ee6cd4a9dc00a957da89f8b4f738a76f · 2026-10-31T07:07Z

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#1 · os-tesla · session_01L9qibw58ehQ2gRHP2h2Puz

Contract-review-claim: session_01L9qibw58ehQ2gRHP2h2Puz · head 138dbe7f222d07be15597922abcf9594a6d5f855 · 2026-10-31T07:43Z

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#1 · os-tesla · session_01L9qibw58ehQ2gRHP2h2Puz

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 138dbe7f222d07be15597922abcf9594a6d5f855
Local-runs: none
Scope: packages/spec/src/api/package-api-assembled.zod.ts (SERVED_ROW_VERDICTS.disableable and the block comment), packages/runtime/src/domains/packages.ts (isDisableablePackage, withDisableableVerdict, the two read-door stamps, the disable door's predicate line, the isDisableableAppModule header), packages/spec/src/api/package-api.test.ts, packages/runtime/src/domains/packages-disableable-verdict.test.ts, packages/runtime/src/domains/packages-writable-verdict.test.ts (pin 5), packages/runtime/src/domains/package-door-producer-key-carry.test.ts (DOOR_COMPUTED_STAMPS), packages/client/src/return-type-precision.test.ts (the two served-row fixtures), content/docs/references/api/package-api-assembled.mdx (regenerated), .changeset/28318-served-disableable-verdict.md

Inputs: card #28318 (body: the Seam from #28117 item 4 with its "⛔ writable must not be overloaded"; triage 6539271118: p1 protocol addition, domain:spec, one-PR exception for serving it from the runtime; the seat's claim 6539475789), PR #28371 (body with the patched Skills-docs: follow-up #28118 line, the dev report 6540403697 and its two declared deviations, the file list of 9 files, the diff of 600 lines against main read whole, the nine commits from the merge-base b4ccbc6, and the one commit 138dbe7 over the claimed head b4d7981, read whole: 5 insertions and 4 deletions in return-type-precision.test.ts), the 50 check-runs on this head (read 2026-10-31T07:44Z: all 50 runs completed, none failed, none cancelled, none in progress; success: Auto Label, Build & E2E UI, Build Core, Build Docs, Build UI Deps, Check Changeset, Check Documentation Links, Check PR Size, Dogfood Regression Gate, Flag docs affected by code changes, Governed Surface Queue Guard, Lint & Repo Gates, Lint · CI, release & engine gates, Lint · ESLint, Lint · PM dispatch-gates, Lint · docs & code guards, Lint · repo & tooling gates, Lint · scoped · query-options erasure, Lint · scoped · slot lookup & corpus, Lint · scoped · tooling self-tests, Live E2E UI, PR-body guards (claim · duplicate · Part-of · single-writer path), Plan Test Core shards, Spec property liveness, Test Core, Test Core (all 8), Test UI, Type Check UI, Type Check · consumer gates, Type Check · debt ledger, Type Check · source gates, Type Check · workspace, TypeScript Type Check, filter; skipped: 18.x upgrade harness (opt-in), Dogfood Regression Gate (matrix shard/3), Dogfood Verify CLI, Lint UI, Packed-tarball smoke (opt-in), Schedule gate · skip when a green push run covers the commit, Temporal Conformance (live PG + MySQL), Test UI (matrix shard/16), UI Published Artifacts), and the tree on main for the door this PR re-routes (packages.ts: requireWritablePackage :572 to :582 answers null for a writable package, isDisableableAppModule :637 to :647, the disable door :1789 asking isDisableableAppModule(id) ? null : requireWritablePackage(...)) and for withWritableVerdict :832. The head is mergeable and clean against today's main (merge-tree clean); none of the files main moved since the merge-base is in this diff, and no open PR touches the two source files.

① Derived judgments

  • One predicate, served and asked - right. isDisableablePackage(engine, id) is isDisableableAppModule(engine, id) || isWritablePackage(engine, id); the disable door now asks it where it asked isDisableableAppModule alone, which is behaviour-identical because the branch it short-circuits, requireWritablePackage, already answers null for a writable package. withDisableableVerdict stamps the same call on GET /packages (after the projection, inside the same map as withWritableVerdict) and on GET /packages/:id, keyed the way withWritableVerdict keys the row. The rule is spelled once; the agreement pin (eleven rows, served value against the door's 200 or 422 on a fresh registry) is what holds the two readers together, and the two ablation legs (constant true, constant false) red the agreement case on every row of the opposite class.
  • The contract - right. disableable: z.boolean() joins SERVED_ROW_VERDICTS, so it lands on both stage branches of InstalledPackageAtEitherStageSchema and on the list and detail responses; required like writable, which both doors already serve on every row; stripped by the record schemas as writable is (pinned). The block comment and describe say what the key answers (the package only; the caller's permission and a catalog wall stay at the door) and that neither verdict derives from the other, which is the card's "not overloaded" ruling written into the schema.
  • writable and every write door are untouched - right. A module of an installed app serves disableable: true, writable: false; requireWritablePackage keeps guarding every other verb.
  • The two existing pins edited - right, and they are the register working: DOOR_COMPUTED_STAMPS is a set-equality register of door-computed stamps that must red when a stamp arrives without a decision, and it went red on the first full run until disableable was added with its reason; packages-writable-verdict pin 5 sets the new key aside by name beside writable. Both are tests of packages.ts, the surface the order names; declared in the dev report.
  • The client pin follows the served shape - right. return-type-precision.test.ts declares a served row as the record plus the door's verdicts, and disableable now sits beside writable on both fixtures, which is why TypeScript Type Check and Type Check · workspace went red on b4d7981 and are green here; it is the ripple of a new served key that the dev report's measurement had not reached, the kind this lane records as a trap. The pin's twelve rows are otherwise unchanged.
  • Reference page and changeset - right. package-api-assembled.mdx is regenerated from the describe (four tables); the changeset names the key, the one predicate, the unchanged writable and the reader.
  • Check-runs as gate verdicts - read as above; every run on this head completed and none is red, cancelled or in progress at the read.

② Semver level

③ Boundary flags

  • Name approval owed to the maintainer: disableable - the card offered it as an example and triage fixed the lane and the shape (a served boolean beside writable) without ruling the spelling; the PR measures the convention (writable, editable, deletable, resettable, undoable, repairable, sortable) and the name follows it. Nothing else is owed on the name.
  • GET /meta/package stamps writable but not disableable - the dev's out-of-scope note: that door's rows are not declared with SERVED_ROW_VERDICTS, and the Console's Packages page reads /packages, so no consumer misses it today. Serving it there would move the predicate into metadata-protocol; a second card if a consumer ever reads that door for Disable.
  • The Console half is Packages page: offer Enable / Disable on a suite's type:module rows once the server allows disabling them #28118 - it offers Disable / Enable from disableable and carries the handbook edit (marketplace-handbook.mdx "Disabling a module"); Skills-docs: follow-up #28118 is the right line, and git grep writable -- skills/ names no package row, so no skills/** page is owed.
  • A required key and older servers - a client that validated a package row against this spec version would refuse a row from a server that predates the key; @objectstack/client does not parse these responses through the schema (comments only), and writable set the same precedent. Not owed.

④ Design judgment

Verdict reasoning. The key is declared where writable is, with the same requiredness, stripping and placement; the runtime serves it from the one predicate the door asks, and the door's behaviour is provably unchanged; the agreement pin and the two ablations hold the two readers to one answer; the two edited pins are registers doing their job; semver and declarations match; the head is clean against main and every check is green or skipped. What remains is the maintainer's word on the name.

Implemented-by: claude/project-thread-az4bej
Reviewed-by: session_01L9qibw58ehQ2gRHP2h2Puz

VERDICT: PASS

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#1 · os-tesla · session_01L9qibw58ehQ2gRHP2h2Puz

Maintainer ruling recorded · 2026-10-31T09:32Z · head 138dbe7f222d07be15597922abcf9594a6d5f855.

  • Name disableable (the served package verdict row member) — Tesla (os-tesla) answered 「同意」 at 2026-10-31T09:30Z in the contract-review lane thread, to the lane's ask that named this key for this PR beside the PASS 6540764710.
  • Nothing is held for the maintainer any more; the seat lands (Tier S, no human gate), re-reading the checks on the landing head.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#1 · os-tesla · session_01L9qibwb6hBqszPTYJobitm

维护者速读

席位核对 · ACCEPT · domain:spec seat 1 (#6017) · 2026-10-31T09:35Z

Head 138dbe7f222d07be15597922abcf9594a6d5f855. Card #28318, claim 6539475789, os-dev-report 6540403697. The maintainer's rulings, verbatim: 「按 pm-dispatch 审过的pr你可以自主落地」, and 「同意」 on the name (6541741016).

  • Shape: draft to main, made by the relay, with Fixes #28318, Clause-②: yes (widening), Metadata-protocol: added, and Skills-docs: follow-up #28118. The seat rewrote that line and posted the rider on Packages page: offer Enable / Disable on a suite's type:module rows once the server allows disabling them #28118.
  • Contract review: record 6540764710 on this head, PASS, with no blocking finding and no should-fix.
    • The GET /meta/package note (it stamps writable but not disableable) is not filed. No consumer reads that door for Disable, and the record says the same.
  • Head note: the body's Verification line names b4d79818. The only change since then is 138dbe7, which adds disableable: boolean to the served-row fixtures in packages/client/src/return-type-precision.test.ts. That test-only fix answers 6 × TS2322 from the new required key, and the dev declared it as a deviation.
  • Gates: 53 check-runs on this head, all success or skipped. mergeable_state clean. check-governed-merges --pr 28371: NOT governed, +410/−18.
  • Landing: pr_ready + automerge_enable in this act.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 31, 2026 09:37
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 31, 2026 09:37
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 31, 2026
Merged via the queue into main with commit 8771726 Oct 31, 2026
54 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-az4bej branch October 31, 2026 10:00
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/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

packages: the served package row carries no "may be disabled" verdict, so the Console cannot offer Disable on a suite module the server now accepts

1 participant