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
.custom export installed on another environment reports success and the override is not applied #30106
Found in a real-user walkthrough of the development flow, asked for by the maintainer: 「你站在真实用户实际使用的角度完整的走一遍具体的开发流程,再看一下还有什么问题」 (2026-11-04).
Governing text: docs/adr/0146-*.md D2: a customization is "exported (GET /packages/:id/export), committed, reviewed and deployed to another environment as any package is"; the Dependency range note names "an export of hotcrm.custom deployed into another environment".
What a customer sees
An administrator customizes a view on staging and moves it to production with the documented commands. The CLI prints a success message and production keeps showing the old view. Nothing says the change was dropped.
Reproduction
Project scaffolded with create-objectstack@18.3.0, one code package com.example.asset-repair, view asset_repair_ticket.open.
On the source instance, POST /api/v1/packages/com.example.asset-repair/ensure-customization, save the view into com.example.asset-repair.custom with overrides: { package, basedOn } and a new label, then publish-drafts. The instance serves the new label.
os package export -u SOURCE -o ./export. The file 01-com.example.asset-repair.custom/objectstack.json carries viewItems with the new label and the overrides block.
os package install ./export/01-com.example.asset-repair.custom/objectstack.json -r TARGET --email OWNER on a fresh os start instance that runs the same base package. It prints ✓ Package installed into the running kernel.
On the target, GET /api/v1/meta/view/asset_repair_ticket.open.
Measured
Read on the target
Result
GET /api/v1/meta/view/asset_repair_ticket.open
The base label, no overrides, package com.example.asset-repair
GET /api/v1/packages/com.example.asset-repair/customizations
Same result on the published 18.3.0 and on main63b86b385d with the same exported file. On 18.3.0 a server restart does not change it (not repeated on main).
Only view was measured. Other overridable types were not run through this path.
Expected
After the install the target serves the override, and the customizations read lists it, the same as on the source. If the install cannot apply an item it says so and does not report success.
The maintainer asked for more testing here: 「继续测试」 (2026-11-04). Measured on main987ff33b88, CLI and server built from that commit. This widens the card: the install also locks the target out of further customization.
Result by item type
Source: os dev, one .custom holding the items below, published and served there. Export: os package export. Target: a fresh os start, separate database, same base package. Install: os package install FILE -r TARGET --email OWNER, which prints ✓ Package installed into the running kernel.
Item in the exported file
On the source
On the target after install
After a target restart
Override, view
Served
Not served, base label
Not served
Override, dashboard
Served
Not served
Not served
Override, app
Served
Not served
Not served
Override, dataset
Served
Not served
Not served
New item, view under its own name
Served
Served
Served
GET /api/v1/packages/com.example.asset-repair/customizations answers overrides: 4 on the source and overrides: 0 on the target. The exported file does carry all four with their overrides block.
The install also closes the door behind it
Step on the target, after the install
Result
POST /packages/com.example.asset-repair/ensure-customization
200, created: false, writable: false
Save a view override into the pair, as Studio does
422 Cannot create view/… that package is read-only (provided by code or an installed app)
422 INSTALL_MODE_NOT_PERMITTED: the file names no installModes, so only managed is allowed
So a customer who follows the documented path ends with no change applied and no way to customize that base on that instance. The only recovery the seat found is deleting the cached file by hand from the host, and restarting.
The same install on a target whose pair already exists and is writable also reports success, and the overrides still do not apply. The seat did not read whether rows already in that pair survive or are shadowed.
Where the cached file lives
The install wrote .objectstack/installed-packages/com.example.asset-repair.custom.json under the server's working directory even though that server ran with OS_HOME set elsewhere. A later instance started from the same directory with a different OS_HOME and a fresh database picked the package up. This was found by accident, when one test contaminated the next. A container's working directory is usually not on a volume, so whether the install survives a container replacement was not measured.
Likely cause, from reading the code
Every read of an override asks sys_metadata rows: listServedOverrides in packages/metadata-protocol/src/protocol-served-overrides.ts selects where: { package_id: pair.value, state: 'active' }.
The install registers the file's items in the in-memory registry as a code-provided package and writes no such row. The server log shows [Registry] Registered view: com.example.asset-repair.custom:asset_repair_ticket.open.
That explains both halves: no row means no override served, and a registered package counts as provided by code, so it is not writable. This is a reading and was not confirmed by a fix.
Other door tried
POST /api/v1/packages does not take the exported file: 400 on the missing manifest.type, and with a type added, 400 Unrecognized key(s)… apps, dashboards, datasets, viewItems. So no other published door was found for carrying a .custom between environments.
Not measured
Other overridable types: report, translation, email_template, page, doc, book, mapping.
Object extensions (__c fields) carried in a .custom.
The Docker path, because Docker is not running on this machine.
Expected, restated
ADR-0146 D2 says the pair is "exported, committed, reviewed and deployed to another environment as any package is". After the install, the target serves the overrides, the customizations read lists them, and an administrator there can keep customizing. If an item cannot be applied, the install says so and does not print success.
Read fresh. The documented ADR-0146 D2 path (export a .custom, install it on another environment) prints success. But none of its overrides (view, dashboard, app, dataset) is served on the target, and the install leaves the target's pair read-only, so it can be neither customized nor removed. A silent failure of a documented deployment path that also locks the target, so p1.
Claim: PM loop round 1
Session: session_01Utp6CbPxYq1wQmUNWvMZkC (seat) · dev = project card thread session_01Utp6CXfNPQKEBNuyohXjfg
Account: os-bill
Branch: claude/project-thread-j915rv
Worktree: objectstack-issue-30106
Domain: domain:server
Seat: domain:server#3
File surface: packages/cli/src/commands/package/**, packages/runtime/src/domains/packages.ts (and the install door it calls), packages/metadata-protocol/src/protocol-served-overrides.ts read path only if the fix needs it, packages/cloud-connection/src/local-manifest-source.ts (cache location) — stop on breach; explain in the report. ⛔ packages/spec.
Container & model: M–L, mode:thread, model: default judgment tier (dispatch-gates --tier: no path-derived mandate; floor sonnet · default opus · ceiling fable), effort: xhigh (p1)
Clause-②: no — the fix makes the install apply what the published export already carries (ADR-0146 D2); the dev re-measures on the built entry closure and reports.
Metadata-protocol: none
Responsibility: the package install door registers a .custom file in memory as code-provided and writes no sys_metadata row (reading, not confirmed) | no platform path carries a .custom between environments today (POST /packages refuses the file, 6633535319) | any customer following the documented ADR-0146 D2 deploy path; reached on 18.3.0 and main
Thread-read: 6633829810
Premise: holds
Serial constraints cleared: #30062 (declared overrides, metadata-protocol, unclaimed in pm:queue) may intersect at metadata-protocol; the dev merges main before opening the PR. No in-flight claim on these paths.
{
"issue": 30106,
"status": "done",
"branch": "claude/project-thread-j915rv",
"pr": "https://github.com/objectstack-ai/objectstack/pull/30207",
"session": "session_01Utp6CXfNPQKEBNuyohXjfg",
"premise_still_valid": true,
"summary": "PM hypothesis measured true, and one fact is added. On main 07595c07 the managed install-local path registered the pair as code. No sys_metadata row was written, so listServedOverrides and the served read saw nothing. The pair also turned read-only (scope cloud, engine.manifests), so ensure-customization answered writable:false and the next save into it got 422 WRITABLE_PACKAGE_REQUIRED. The CLI still printed success. The fix routes a pair id (customizationBasePackageId) to installCustomizationPair: the target's ensure door, then saveMetaItem per item (mode publish, pair as package, installer as actor), in load order. Nothing is registered or ledgered. A pair that is already read-only is refused 409 with its way back; a refused save answers failure, and a pair this install created is rolled back. The CLI prints the pair, and prints an older runtime's as-code answer as an error (exit 1).",
"tests": "At 6be0aea6a: @objectstack/cloud-connection full vitest, Test Files 70 passed (70), Tests 846 passed (846). New: customization-pair planner (7 cases) and customization-pair-install (15 cases). Updated: override-gate (3 cases) and extension-field-suffix (1 case), from registered===[PAIR] to saves named. @objectstack/cli --project unit: 382/383 files and 5381/5382 tests. The one failure, package-export.test.ts (its stub answered the pair as code), was fixed and passes 6/6; new package-install-customization-pair 2/2. Dogfood package-export-reinstall-custom-pair + package-export-bundle-round-trip: 2 files, 16/16 tests. cloud-connection typecheck exit 0; cli tsc --noEmit exit 0 (its test-typecheck OOMed while two dev servers ran, so NOT MEASURED). Dev e2e on two os dev showcase runtimes, before and after the fix, with readings in the PR Verification section. After the fix the override labels are served, customizations overrides:2, ensure writable:true, a further save into the pair 200, re-install idempotent, no ledger file, rows persist across two restarts. Stale code pair: 409 naming DELETE + restart, then 409 naming restart, then success after restart. Ablation (scripts/ablation-replace.mjs; tests import src, so no dist): the pair branch was disabled ('if (pairBaseId !== null)' changed to 'if (false && pairBaseId !== null)'; anchor 1 to 0, blob 304abdb60d58 to bef2069a57a3). customization-pair-install + override-gate + extension-field-suffix went from 30 passed to 18 failed / 12 passed. Restored: blob == HEAD, git diff HEAD empty.",
"gates": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 64 commands at 6be0aea6a, each run with its exit code recorded before any pipe: 64 :: exit 0. --ran: 64 derived famil(ies) accounted for, 64 run, 0 NOT-MEASURED. On the first pass, pnpm check:durability-log-level exited 1 (the save-loop catch had no log; fixed in place by an error log in the catch) and check-plugin-teardown-shape --self-test exited 3 (shallow clone; pinned fixture commit fetched). pnpm lint exit 0. The PR's check-runs had not been read when this report was written.",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm declared. The two pair dogfood files ran (16/16); see open_questions on the Clause-② re-check",
"mcp_calls": "5 — mcp__github__issue_read x5 (reads); no MCP write tool used",
"api_writes": "2 — POST /repos/objectstack-ai/objectstack/dispatches (relay pr_create, landed #30207, body identical, assignees none); this comment via post-stamped. git push is not a REST write.",
"open_questions": [
{
"question": "Clause-② re-check (dev 实测复核). The claim's line, copied, is 'no'. Measured: a pair-id body carrying a key with no item form (code, a translations bundle, an envelope, an unclassified key), or a pair inside a multi-package artifact, is now refused, where before it was registered as code. A pair install's answer gains customizationPair / writtenCount / written and no longer carries hotLoaded / storageDir. Keep 'no'?",
"options": [
"A keep Clause-②: no — the refused bodies never installed a working pair (nothing was served), and the answer keys are additive for one id class",
"B Clause-②: yes (narrowing) — say the narrowed accept set in the PR body and the changeset; the seat edits both"
],
"recommendation": "A, because a pair registered as code served none of what it carried, so the refused shapes had no working install to narrow; the seat owns the call"
}
],
"security_findings": "none",
"out_of_scope_findings": [
"class: a · reach: DELETE /api/v1/marketplace/install-local/ID answers 200 'withdrawn from the running kernel', then POST /api/v1/packages/BASE/ensure-customization answers 201 created:true writable:false — the engine's manifests map keeps the id until a restart, so an uninstalled code package still reads read-only (measured on pre-fix and fixed builds) · evidence: package-writability.ts isWritablePackage reads engine.manifests first; engine.ts only ever sets it · dedupe words: install-local uninstall manifests writable, ensure-customization writable false after uninstall, engine.manifests never deleted",
"class: a · reach: os dev --fresh then a managed install-local writes CWD/.objectstack/installed-packages/ID.json (measured: examples/app-showcase/.objectstack/installed-packages/com.example.showcase.custom.json under a fresh OS_HOME); an entry there is rehydrated by the next --fresh boot (measured) · evidence: local-manifest-source.ts default resolve(process.cwd(), DEFAULT_INSTALLED_PACKAGES_DIR); serve.ts constructs the plugin without storageDir; dev.ts says state not keyed off OS_HOME is not covered · judged out of scope: a pair no longer writes one; moving it for other packages needs a read-old-location fallback · dedupe words: installed-packages OS_HOME, LocalManifestSource cwd, --fresh install-local cache",
"carrier: none · noted, not filed (read from code, not measured): the pair export omits emailTemplates and translation items, so those pair overrides do not round-trip; --install-mode unmanaged on a pair still takes the unmanaged copy path; overrideWriteItemsOf (install-time override gate) does not read viewItems"
]
}
ACCEPT → PR #30207 comment 6648031887 (head 6be0aea6). Contract review PASS 6647885067. Readied and auto-merge armed by the seat. Out of scope filed: #30215, #30217.
Activity
objectstack-fleet commentedon Nov 4, 2026
epic:#26676#1 · zhuangjianguo · session_cdb7a717def74e719988f089fbaa18ff
The maintainer asked for more testing here: 「继续测试」 (2026-11-04). Measured on
main987ff33b88, CLI and server built from that commit. This widens the card: the install also locks the target out of further customization.Result by item type
Source:
os dev, one.customholding the items below, published and served there. Export:os package export. Target: a freshos start, separate database, same base package. Install:os package install FILE -r TARGET --email OWNER, which prints✓ Package installed into the running kernel.viewdashboardappdatasetviewunder its own nameGET /api/v1/packages/com.example.asset-repair/customizationsanswersoverrides: 4on the source andoverrides: 0on the target. The exported file does carry all four with theiroverridesblock.The install also closes the door behind it
POST /packages/com.example.asset-repair/ensure-customizationcreated: false,writable: falseCannot create view/… that package is read-only (provided by code or an installed app)DELETE /api/v1/packages/com.example.asset-repair.customWRITABLE_PACKAGE_REQUIRED … it is read-onlyos package install FILE --install-mode unmanagedINSTALL_MODE_NOT_PERMITTED: the file names noinstallModes, so onlymanagedis allowedSo a customer who follows the documented path ends with no change applied and no way to customize that base on that instance. The only recovery the seat found is deleting the cached file by hand from the host, and restarting.
The same install on a target whose pair already exists and is writable also reports success, and the overrides still do not apply. The seat did not read whether rows already in that pair survive or are shadowed.
Where the cached file lives
The install wrote
.objectstack/installed-packages/com.example.asset-repair.custom.jsonunder the server's working directory even though that server ran withOS_HOMEset elsewhere. A later instance started from the same directory with a differentOS_HOMEand a fresh database picked the package up. This was found by accident, when one test contaminated the next. A container's working directory is usually not on a volume, so whether the install survives a container replacement was not measured.Likely cause, from reading the code
sys_metadatarows:listServedOverridesinpackages/metadata-protocol/src/protocol-served-overrides.tsselectswhere: { package_id: pair.value, state: 'active' }.[Registry] Registered view: com.example.asset-repair.custom:asset_repair_ticket.open.That explains both halves: no row means no override served, and a registered package counts as provided by code, so it is not writable. This is a reading and was not confirmed by a fix.
Other door tried
POST /api/v1/packagesdoes not take the exported file: 400 on the missingmanifest.type, and with atypeadded, 400Unrecognized key(s)… apps, dashboards, datasets, viewItems. So no other published door was found for carrying a.custombetween environments.Not measured
report,translation,email_template,page,doc,book,mapping.__cfields) carried in a.custom.Expected, restated
ADR-0146 D2 says the pair is "exported, committed, reviewed and deployed to another environment as any package is". After the install, the target serves the overrides, the customizations read lists them, and an administrator there can keep customizing. If an item cannot be applied, the install says so and does not print success.
objectstack-fleet commentedon Nov 4, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: first-touch audit · p1 ·
domain:server·pm:queue· 2026-11-04T14:53Z⛔ Not a claim.
.custom, install it on another environment) prints success. But none of its overrides (view, dashboard, app, dataset) is served on the target, and the install leaves the target's pair read-only, so it can be neither customized nor removed. A silent failure of a documented deployment path that also locks the target, so p1.os package install). Serial with Declared overrides: a mapping override publishes but is never served, doc and mapping overrides cannot be restored, and an override's label can be hidden by translation #30062 (declared overrides).Generated by Claude Code
objectstack-fleet commentedon Nov 5, 2026
domain:server#3 · os-bill · session_01Utp6CbPxYq1wQmUNWvMZkC
Claim: PM loop round 1
Session:
session_01Utp6CbPxYq1wQmUNWvMZkC(seat) · dev = project card threadsession_01Utp6CXfNPQKEBNuyohXjfgAccount:
os-billBranch:
claude/project-thread-j915rvWorktree:
objectstack-issue-30106Domain:
domain:serverSeat:
domain:server#3File surface:
packages/cli/src/commands/package/**,packages/runtime/src/domains/packages.ts(and the install door it calls),packages/metadata-protocol/src/protocol-served-overrides.tsread path only if the fix needs it,packages/cloud-connection/src/local-manifest-source.ts(cache location) — stop on breach; explain in the report. ⛔packages/spec.Container & model:
M–L,mode:thread,model: default judgment tier (dispatch-gates --tier: no path-derived mandate; floor sonnet · default opus · ceiling fable),effort: xhigh (p1)Clause-②: no — the fix makes the install apply what the published export already carries (ADR-0146 D2); the dev re-measures on the built entry closure and reports.
Metadata-protocol: none
Responsibility:
the package install door registers a .custom file in memory as code-provided and writes no sys_metadata row (reading, not confirmed) | no platform path carries a .custom between environments today (POST /packages refuses the file, 6633535319) | any customer following the documented ADR-0146 D2 deploy path; reached on 18.3.0 and mainThread-read: 6633829810
Premise: holds
Serial constraints cleared:
#30062 (declared overrides, metadata-protocol, unclaimed in pm:queue) may intersect at metadata-protocol; the dev merges main before opening the PR. No in-flight claim on these paths.objectstack-fleet commentedon Nov 5, 2026
domain:server#3 · os-bill · session_01Utp6CXfNPQKEBNuyohXjfg
os-dev-report
{ "issue": 30106, "status": "done", "branch": "claude/project-thread-j915rv", "pr": "https://github.com/objectstack-ai/objectstack/pull/30207", "session": "session_01Utp6CXfNPQKEBNuyohXjfg", "premise_still_valid": true, "summary": "PM hypothesis measured true, and one fact is added. On main 07595c07 the managed install-local path registered the pair as code. No sys_metadata row was written, so listServedOverrides and the served read saw nothing. The pair also turned read-only (scope cloud, engine.manifests), so ensure-customization answered writable:false and the next save into it got 422 WRITABLE_PACKAGE_REQUIRED. The CLI still printed success. The fix routes a pair id (customizationBasePackageId) to installCustomizationPair: the target's ensure door, then saveMetaItem per item (mode publish, pair as package, installer as actor), in load order. Nothing is registered or ledgered. A pair that is already read-only is refused 409 with its way back; a refused save answers failure, and a pair this install created is rolled back. The CLI prints the pair, and prints an older runtime's as-code answer as an error (exit 1).", "tests": "At 6be0aea6a: @objectstack/cloud-connection full vitest, Test Files 70 passed (70), Tests 846 passed (846). New: customization-pair planner (7 cases) and customization-pair-install (15 cases). Updated: override-gate (3 cases) and extension-field-suffix (1 case), from registered===[PAIR] to saves named. @objectstack/cli --project unit: 382/383 files and 5381/5382 tests. The one failure, package-export.test.ts (its stub answered the pair as code), was fixed and passes 6/6; new package-install-customization-pair 2/2. Dogfood package-export-reinstall-custom-pair + package-export-bundle-round-trip: 2 files, 16/16 tests. cloud-connection typecheck exit 0; cli tsc --noEmit exit 0 (its test-typecheck OOMed while two dev servers ran, so NOT MEASURED). Dev e2e on two os dev showcase runtimes, before and after the fix, with readings in the PR Verification section. After the fix the override labels are served, customizations overrides:2, ensure writable:true, a further save into the pair 200, re-install idempotent, no ledger file, rows persist across two restarts. Stale code pair: 409 naming DELETE + restart, then 409 naming restart, then success after restart. Ablation (scripts/ablation-replace.mjs; tests import src, so no dist): the pair branch was disabled ('if (pairBaseId !== null)' changed to 'if (false && pairBaseId !== null)'; anchor 1 to 0, blob 304abdb60d58 to bef2069a57a3). customization-pair-install + override-gate + extension-field-suffix went from 30 passed to 18 failed / 12 passed. Restored: blob == HEAD, git diff HEAD empty.", "gates": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 64 commands at 6be0aea6a, each run with its exit code recorded before any pipe: 64 :: exit 0. --ran: 64 derived famil(ies) accounted for, 64 run, 0 NOT-MEASURED. On the first pass, pnpm check:durability-log-level exited 1 (the save-loop catch had no log; fixed in place by an error log in the catch) and check-plugin-teardown-shape --self-test exited 3 (shallow clone; pinned fixture commit fetched). pnpm lint exit 0. The PR's check-runs had not been read when this report was written.", "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm declared. The two pair dogfood files ran (16/16); see open_questions on the Clause-② re-check", "mcp_calls": "5 — mcp__github__issue_read x5 (reads); no MCP write tool used", "api_writes": "2 — POST /repos/objectstack-ai/objectstack/dispatches (relay pr_create, landed #30207, body identical, assignees none); this comment via post-stamped. git push is not a REST write.", "open_questions": [ { "question": "Clause-② re-check (dev 实测复核). The claim's line, copied, is 'no'. Measured: a pair-id body carrying a key with no item form (code, a translations bundle, an envelope, an unclassified key), or a pair inside a multi-package artifact, is now refused, where before it was registered as code. A pair install's answer gains customizationPair / writtenCount / written and no longer carries hotLoaded / storageDir. Keep 'no'?", "options": [ "A keep Clause-②: no — the refused bodies never installed a working pair (nothing was served), and the answer keys are additive for one id class", "B Clause-②: yes (narrowing) — say the narrowed accept set in the PR body and the changeset; the seat edits both" ], "recommendation": "A, because a pair registered as code served none of what it carried, so the refused shapes had no working install to narrow; the seat owns the call" } ], "security_findings": "none", "out_of_scope_findings": [ "class: a · reach: DELETE /api/v1/marketplace/install-local/ID answers 200 'withdrawn from the running kernel', then POST /api/v1/packages/BASE/ensure-customization answers 201 created:true writable:false — the engine's manifests map keeps the id until a restart, so an uninstalled code package still reads read-only (measured on pre-fix and fixed builds) · evidence: package-writability.ts isWritablePackage reads engine.manifests first; engine.ts only ever sets it · dedupe words: install-local uninstall manifests writable, ensure-customization writable false after uninstall, engine.manifests never deleted", "class: a · reach: os dev --fresh then a managed install-local writes CWD/.objectstack/installed-packages/ID.json (measured: examples/app-showcase/.objectstack/installed-packages/com.example.showcase.custom.json under a fresh OS_HOME); an entry there is rehydrated by the next --fresh boot (measured) · evidence: local-manifest-source.ts default resolve(process.cwd(), DEFAULT_INSTALLED_PACKAGES_DIR); serve.ts constructs the plugin without storageDir; dev.ts says state not keyed off OS_HOME is not covered · judged out of scope: a pair no longer writes one; moving it for other packages needs a read-old-location fallback · dedupe words: installed-packages OS_HOME, LocalManifestSource cwd, --fresh install-local cache", "carrier: none · noted, not filed (read from code, not measured): the pair export omits emailTemplates and translation items, so those pair overrides do not round-trip; --install-mode unmanaged on a pair still takes the unmanaged copy path; overrideWriteItemsOf (install-time override gate) does not read viewItems" ] }Generated by Claude Code
objectstack-fleet commentedon Nov 5, 2026
domain:server#3 · os-bill · session_01Utp6CbPxYq1wQmUNWvMZkC
ACCEPT → PR #30207 comment 6648031887 (head
6be0aea6). Contract review PASS 6647885067. Readied and auto-merge armed by the seat. Out of scope filed: #30215, #30217.objectstack-fleet commentedon Nov 5, 2026
domain:server#3 · os-bill · session_01Utp6CbPxYq1wQmUNWvMZkC
Landed · 2026-11-05T02:53Z
afc761c35fa475d1a1a48cda5982be994a7f079f(merged_at 2026-11-05T02:52Z)..custominstalled on another environment now lands in its writable pair and its overrides are served.os dev --freshrehydrates a previous install #30217.pm:dispatchedremoved. Only.customexport installed on another environment reports success and the override is not applied #30106 closed in the merge window (no closing keyword misfire).