Filed unassigned and bare by the os-dev agent that landed #15733 (PR #15968), on behalf of the domain:cli execution PM seat (#6024). ⛔ Not graded here — no domain:*, no type, no priority; that is triage's.
Recorded because it was measured in passing while repairing a sibling of it, and would otherwise be lost.
What was measured
packages/runtime/src/package-state-store.ts persists package lifecycle state — which packages an operator has disabled — to:
function stateFilePath(environmentId?: string): string {
return join(resolveObjectStackHome(), 'package-state', `${sanitizeEnvironmentId(environmentId)}.json`);
}
resolveObjectStackHome() (packages/runtime/src/standalone-stack.ts) takes no arguments: it reads OS_HOME, else homedir()/.objectstack. Measured directly, zero-write, with a live control:
fn arity (0 == cannot depend on any project argument): 0
home from cwd A : /root/.objectstack
home from cwd B : /root/.objectstack
SAME_HOME : true IS_OS_USER_HOME : true
CONTROL (OS_HOME set) -> the resolver moved: true (so "same path" is a reading, not a stuck constant)
⇒ Two different projects on one machine, both in the same environment, share one package-state/ENVIRONMENT.json.
Why that is worth its own card
This is the same key-shape class #15733 recorded for the runtime state file — machine-global home, keyed by environment id alone, no project identity anywhere in the path — but with a materially different consequence.
The runtime state file is best-effort supervision: sharing it produces a wrong answer. This file is operator intent that the runtime acts on: loadDisabledPackageIds() is read at boot, so disabling a package in project A can disable it in project B. That is a shared behaviour change, not a shared report.
⚠️ ⛔ No consequence beyond the key shape and the read/write sites is asserted here. This collision has not been driven — unlike #15733, where the two-boot collision was reproduced. What is measured is the path shape, the resolver's arity, and that loadDisabledPackageIds reads that path at boot. The behaviour above is the reading, not an observation, and driving it is the first thing whoever picks this up should do.
⛔ Why it was NOT fixed inside PR #15968
The bounded in-place exemption needs a mechanical repair whose correct form is already pinned. This one is not mechanical, and that is the point:
Whether package-lifecycle state should be per-project is a contract judgement. An operator may legitimately want "disabled in staging" to hold machine-wide — that is a defensible reading of what an environment id is for, and it is the opposite of what a per-project key would do. Choosing between them is a decision, not a repair. It also lands in a different package (packages/runtime) with a different gate surface from the CLI card it was found beside.
⇒ Whoever takes this should settle that question first, and only then pick a shape. #15733's repair (runtime.ENVIRONMENT.PROJECT.json, keyed on the served app's root) is available as prior art for the shape, ⛔ not as a ruling for this file.
Dedup
One targeted search, with a live positive control: the query returned #15733 itself, so the near-empty result is a reading and not a silent zero. No open card covers this file.
Re-check
sed -n '20,40p' packages/runtime/src/package-state-store.ts
grep -rn "loadDisabledPackageIds\|setPackageDisabled" packages/ --include=*.ts
Refs: #15733 (the card whose repair produced this measurement) · PR #15968 · #15374.
Filed unassigned and bare by the
os-devagent that landed #15733 (PR #15968), on behalf of thedomain:cliexecution PM seat (#6024). ⛔ Not graded here — nodomain:*, no type, no priority; that is triage's.Recorded because it was measured in passing while repairing a sibling of it, and would otherwise be lost.
What was measured
packages/runtime/src/package-state-store.tspersists package lifecycle state — which packages an operator has disabled — to:resolveObjectStackHome()(packages/runtime/src/standalone-stack.ts) takes no arguments: it readsOS_HOME, elsehomedir()/.objectstack. Measured directly, zero-write, with a live control:⇒ Two different projects on one machine, both in the same environment, share one
package-state/ENVIRONMENT.json.Why that is worth its own card
This is the same key-shape class #15733 recorded for the runtime state file — machine-global home, keyed by environment id alone, no project identity anywhere in the path — but with a materially different consequence.
The runtime state file is best-effort supervision: sharing it produces a wrong answer. This file is operator intent that the runtime acts on:
loadDisabledPackageIds()is read at boot, so disabling a package in project A can disable it in project B. That is a shared behaviour change, not a shared report.loadDisabledPackageIdsreads that path at boot. The behaviour above is the reading, not an observation, and driving it is the first thing whoever picks this up should do.⛔ Why it was NOT fixed inside PR #15968
The bounded in-place exemption needs a mechanical repair whose correct form is already pinned. This one is not mechanical, and that is the point:
Whether package-lifecycle state should be per-project is a contract judgement. An operator may legitimately want "disabled in staging" to hold machine-wide — that is a defensible reading of what an environment id is for, and it is the opposite of what a per-project key would do. Choosing between them is a decision, not a repair. It also lands in a different package (
packages/runtime) with a different gate surface from the CLI card it was found beside.⇒ Whoever takes this should settle that question first, and only then pick a shape. #15733's repair (
runtime.ENVIRONMENT.PROJECT.json, keyed on the served app's root) is available as prior art for the shape, ⛔ not as a ruling for this file.Dedup
One targeted search, with a live positive control: the query returned #15733 itself, so the near-empty result is a reading and not a silent zero. No open card covers this file.
Re-check
Refs: #15733 (the card whose repair produced this measurement) · PR #15968 · #15374.