Repository navigation
[finding] cli(migrate meta): on a composeStacks preserve project the authored-source load is refused with STACK_PROVENANCE_MISSING ("not built by defineStack") although every input is wrapped #22289
Description
Activity
objectstack-fleet commented
on Oct 8, 2026 ContributorAuthorMore actionsTriage: first grade,
bug·priority:p1·target:v18·domain:cli·area:devpath·pm:queue(findingremoved). Direction:migrate metaruns on a composed projectTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-08T12:59Z. ⛔ Not a claim, ⛔ not a dispatch.Triage: lands in
packages/cli(loadConfig's authored-source path, asmigrate metauses it) ⇒domain:cli; rationale: that lane's. If the only route ispackages/spec'scomposeStacksprovenance check, the seat says so on this card first.- Why p1 and
target:v18: the command every retired spelling's refusal prescribes cannot run on a composed project, and hotcrmmainis now composed (objectstack-ai/hotcrm PR feat(auth): password-policy & session settings — live, enforced (P0 security) #2011). So the flagship app's v18 upgrade path is blocked. Release first (「发版本优先的都p1」), as with cli(migrate meta):os migrate meta --from 17 --writeleavesengines.protocol: '^17', so the load refusal that names this command as its resolution still refuses the migrated manifest #22219. - Also measure, once the refusal is fixed: whether the conversion walker (
spec/src/conversions/walk.ts) missespackages[]bodies, as the card notes. If it does, that is part of this card's acceptance: a composed project's body conversions are applied and listed. - Pins: a composed project with a retired spelling in a package body migrates and lists the conversion. Control: the one-package project is unchanged.
- Why p1 and
- addedarea:devpathThe road — create, dev, verify, publish/install, connect an agent, iterateThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingSomething isn't workingpriority:p1High: required for production / M2High: required for production / M2and removed
on Oct 8, 2026 objectstack-fleet commented
on Oct 8, 2026 ContributorAuthorMore actionsClaim: PM loop round 14
Session:session_01RWZbGvPFcRKvUqASZtunCU
Account:os-warren(the seat's linked user asget_meanswers it; the card's assignee)
Branch:claude/issue-22289-migrate-meta-composed
Worktree:objectstack-issue-22289
Domain:domain:cli
Seat:domain:cli#1
File surface, per the card body and triage6060414246, read onorigin/main4e4111ca:packages/cli/src/utils/config.ts, the authored-source shim (the__tolerantprelude at:398,authoredSourcePluginat:495).- When the real
defineStackrefuses,__toleranthands backauthored[0]unmarked. composeStacksis not adefine*helper, so it runs for real and refuses that input withSTACK_PROVENANCE_MISSING(packages/spec/src/stack.zod.ts:5443–:5458).
- When the real
packages/cli/src/commands/migrate/meta.tsand/orpackages/cli/src/utils/authored-source-codemod.ts, only if the composed stack's package bodies need the chain run over them (the walker half triage names).- Pins in
packages/cli/test/:- a composed project with a retired spelling in a package body migrates and lists the conversion;
- control: the one-package project is unchanged.
.changeset/*.md:@objectstack/clipatch.- Added at review (PR fix(cli):
os migrate metaruns on acomposeStacksproject and migrates its package bodies #22326), amended in place 2026-10-08T17:23Z:packages/cli/src/utils/stack-collections.ts(packageOwnedCollectionKeysexported for the codemod's body tracing, not a package-entry export);packages/cli/test/normalized-call-sites.test.ts(the renamedmigrate/meta.tscall site's row); andcontent/docs/upgrading.mdx(the--writeparagraph, about:236–:243, which this change made false; declared todomain:devxon [PM seat] domain:devx @ objectstack — 🟢 os-warren · session_012yK1ddAdAqfzwigRHZq3r2 #6023 and [PM seat] domain:devx · seat 2 — ⏳ vacant #20163). Nothing else moves. - ⛔ No
packages/spec(composeStacks,stack-provenance.ts,conversions/walk.ts), and nocontent/docsbeyond the one paragraph added at review. (Stop on breach and explain in the report.)
Triage's first question, answered before dispatch. Triage asked whether the only route is
packages/spec's provenance check. It is not:defineStack's ownstrict: falsemode marks its output inside the producer (stack.zod.ts:3904–:3914: "The output is still this producer's, so it carries the provenance mark").- So the shim's fallback can ask the real producer for a marked, unvalidated stack. That needs no
packages/specchange and no hand-copied mark. - Its measured cost decides whether it holds: that mode still runs the load-time conversion pass, which is [finding] cli(migrate meta):
--writenever writes a conversion the authored-source load already applied (e.g.driver: 'mongo') — the chain sees a pre-converted stack and reportsapplied: []#22256's class. The dev measures it against the one-package control and stops if no route inpackages/clikeeps that control unchanged.
Container & model:
M,mode:subagent,model: default (opus).dispatch-gates --tierover the path gives no path-derived mandate.
Clause-②: no- No accepted input of a contract, export or published shape changes.
os migrate metaruns on a composed project that its own refusals prescribe it for, instead of refusing with a prescription the author has already followed. A new--jsonkey would change this line, and the dev reports it before landing.
Responsibility:platform code: os migrate meta's authored-source shim hands a refused defineStack's input back unmarked, and composeStacks refuses it|none known: the shim predates the composeStacks provenance check (#20367 ruling B)|any multi-package app migrated across a major: the command every retired spelling's refusal prescribes exits 1 on it (hotcrm main is composed, objectstack-ai/hotcrm#2011; the v18 upgrade path)
Thread-read: 6060414246
Serial constraints cleared: read 2026-10-08T16:16Z: - Open PRs (12 besides the release PR, each file list read by name against the merge base):
- Only this seat's PR fix(cli): os serve and seven sibling readers read a multi-package config's package-owned keys through its package bodies #22321 ([finding] cli(serve):
os serveresolves capability providers from a multi-package artifact's top-levelrequiresonly — a package'srequires: ['automation']is not loaded at boot #22288) touchesmigrate/meta.ts, at one call site (pendingDataMigrations, about:1066–:1075). This card edits that file only if the walker half needs it, in the authored-source chain. If both edit it, ordinary concurrency applies and the later lander resolves. - No open PR touches
utils/config.ts,authored-source-codemod.ts, orpackages/spec'sstack-provenance.tsorconversions/walk.ts.
- Only this seat's PR fix(cli): os serve and seven sibling readers read a multi-package config's package-owned keys through its package bodies #22321 ([finding] cli(serve):
- In-flight claims: none in
domain:clibesides [finding] cli(serve):os serveresolves capability providers from a multi-package artifact's top-levelrequiresonly — a package'srequires: ['automation']is not loaded at boot #22288 (PR fix(cli): os serve and seven sibling readers read a multi-package config's package-owned keys through its package bodies #22321, accepted, landing). - [finding] cli(migrate meta):
--writenever writes a conversion the authored-source load already applied (e.g.driver: 'mongo') — the chain sees a pre-converted stack and reportsapplied: []#22256 (p2, queued, unclaimed) is the load-path conversion class this card's route may touch. It stays its own card. The dev reports any interaction.
domain:cliseat ·session_01RWZbGvPFcRKvUqASZtunCU· 2026-10-08T16:16Zobjectstack-fleet commented
on Oct 8, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 22289,
"status": "done",
"branch": "claude/issue-22289-migrate-meta-composed",
"pr": "#22326",
"session": "session_01RWZbGvPFcRKvUqASZtunCU",
"premise_still_valid": true,
"summary": "os migrate meta now runs on a composeStacks([defineStack(...), ...], { manifest: 'preserve' }) project, all in packages/cli with no packages/spec change and no hand-written provenance mark. The authored-source shim records each stack it hands through for a refused defineStack call, and a generated composeStacks wrap re-produces only those inputs via the real defineStack(input, { ...options, strict: false }), so the producer marks its own output. A truly unwrapped input is still refused, and the one-package path keeps its raw hand-back, because H3 measured that a strict:false fallback there changes the control. The chain now also runs over each packages[i].manifest body (applyMetaMigrationsToPackages, used at all three call sites), lists body edits under packages[i].manifest paths, and --write traces them through composeStacks([...]) into the input's own file.",
"readings": {
"H1": "reproduced on 4e4111c build: composed --from 17 --json exit 1, code STACK_PROVENANCE_MISSING, "composeStacks provenance check failed (1 input): 'com.probe.svc' (stack #0) was not built bydefineStack..."; one-package control exit 0, applied [time-default-utc-suffix-dropped @ objects[0].fields.starts_at.defaultValue]",
"H2": "confirmed both halves; refuses ONLY when a body's defineStack refused: the same composed project with '10:00' gives exit 0, applied [], schemaValid true",
"H3": "variant A (strict:false fallback for every refused defineStack, measured on mutated dist then md5-restored) CHANGES the control: c2 (refused stack + datasources[0].driver 'mongo') at --from 16 went from applied [mongo-to-mongodb @ datasources[0].driver, time @ objects[0]...] / write.files [{objectstack.config.ts, sites 2}] / source 'mongodb' to applied [time] / sites 1 / source keeps 'mongo'; c1 unchanged. So the one-package path keeps the raw hand-back; the route applies only via the shim-wrapped composeStacks over shim-handed-through inputs. After the change c1 and c2 at --from 16 and 17: --json summary (applied, schemaValid, whole write object) and written source bytes md5-identical to baseline.",
"H4": "confirmed: after the shim fix alone the composed project gave exit 0 but applied [] and schemaValid false (refusal at packages.0.manifest.objects.0.fields.starts_at.defaultValue; artifact top keys manifest+packages only). Fixed in packages/cli by running the chain over each body; walker untouched. After: applied [time-default-utc-suffix-dropped @ packages[0].manifest.objects[0].fields.starts_at.defaultValue], schemaValid true, --write rewrites the authored literal, verification.ok true, re-run applies nothing.",
"H5": "holds: a plain object beside a wrapped input is still refused STACK_PROVENANCE_MISSING naming only 'com.probe.app' (stack #1); refusal text unchanged",
"route_cost": "measured: a refused composed body carrying 'mongo' has it applied at load by strict:false, not listed, not written (#22256's class, now also on the composed path); stated in the changeset as a known limit",
"real_project": "examples/app-multi-package --from 17 --json: exit 0, applied [], schemaValid true"
},
"tests": "At 122ae3b:pnpm --filter @objectstack/cli exec vitest run --project unit→ Test Files 267 passed (267), Tests 3936 passed (3936), lock VERDICT command-exit 0;vitest list --filesOnlyputs test/migrate-meta-composed.test.ts in unit (1) and not integration (0); integration tier declared to CI (no integration file or spawn entry touched).pnpm --filter @objectstack/cli typecheckexit 0 (check:test-typecheck: OK). New pins test/migrate-meta-composed.test.ts, 8 tests, unit tier: composed load+listing; --write rewrites src/service.stack.ts only, re-run applies nothing, strict loadConfig accepts (stackProvenance true); untraceable body listed as helper, bytes unchanged; one-package controls (applied conversion/path/from/to and write.files and written bytes equal to the 4e4111c measurement); unwrapped-input boundary; merge contracts. Ablations via scripts/ablation-replace.mjs at fb129c3 (7 tests then), each anchor hit 1 → 0, restore proven blob == HEAD and git diff HEAD empty: (1) __composable returns its input → 3 failed | 4 passed (both composed pins red with the original STACK_PROVENANCE_MISSING; boundary red because the refusal then names 'com.probe.svc' too), restored blob 982786a6180d; (2) body pass returns the plain result → 3 failed | 4 passed (applied []), restored e1aa2f776836; (3) codemod composeStacks walk disabled → 1 failed | 6 passed (write.files []), restored 359b722e7b4c. Subject imported from src, so no dist leg.",
"gates": "At 122ae3b: the order's 65 commands, re-derived bynode scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsover this diff (identical 65), all exit 0;dispatch-gates --ran: '65 derived, 65 run, 0 NOT-MEASURED, 0 UNRUN'. check:dual-build-cjs-loads and check:i18n-coverage exited 3 (PREREQUISITE NOT MET) on a first pass at 0413028 with only the CLI closure built, then passed after a fullturbo run build('106 published require entry point(s) across 66 package(s) load'; 'check-i18n-coverage: OK (13 config(s), 621 baselined untranslated string(s), none new)'). check:nul-bytes OK.pnpm lint(eslint . --no-inline-config) exit 0, no findings. CI not awaited: in_progress at report time.",
"line_budget": "7 files, +679 / -13 (692 changed lines; human-merge threshold 5000: under). No skills/** or governed surface touched.",
"files_changed": [
".changeset/22289-migrate-meta-composed-project.md",
"packages/cli/src/commands/migrate/meta.ts",
"packages/cli/src/utils/authored-source-codemod.ts",
"packages/cli/src/utils/config.ts",
"packages/cli/src/utils/stack-collections.ts",
"packages/cli/test/migrate-meta-composed.test.ts",
"packages/cli/test/normalized-call-sites.test.ts"
],
"deviations": [
"file surface: packages/cli/src/utils/stack-collections.ts (one export of packageOwnedCollectionKeys plus a doc paragraph, so the codemod reads the CLI's one derivation of the package-owned key set) and packages/cli/test/normalized-call-sites.test.ts (the ledger row for the renamed call site, top-level → packages) are outside the claim's listed files; declared in the PR body",
"the H3 variant-A measurement mutated the untracked built dist/utils/config.js (copy-aside, trap restore, md5 proven equal) instead of scripts/ablation-replace.mjs, which restores from HEAD and cannot restore an untracked file",
"attribution: commits carry the model-free pair (Co-Authored-By: Claude, Claude-Session) and the PR body the AGENTS.md session-URL footer, not the harness reminder's model-named trailer and footer, per the order and AGENTS.md"
],
"mcp_calls": "0 — no MCP GitHub tool called",
"api_writes": "3 — each one fleet-write relay stroke (POST /repos/objectstack-ai/objectstack/dispatches, executed as objectstack-fleet[bot]): pr_create POST /repos/objectstack-ai/objectstack/pulls (#22326, draft, body read back byte-identical); assign POST /repos//issues/22326/assignees (os-warren, read back); comment POST /repos//issues/22289/comments (this report). Plus 6git pushof the branch (not REST). No label written (the order names none; skip-changeset does not apply).",
"open_questions": [],
"out_of_scope_findings": [
"carrier: #22256 (queued) · within its scope, not a new card: on a composed project a refused input is re-produced by defineStack strict:false, whose load-time D2 pass applies a still-load-path conversion (datasources[].driver 'mongo') before the chain runs, so it is not listed and not written; measured with a composed body carrying '10:00Z' + 'mongo'. #22256's fix needs to cover this path as well as the one-package one",
"carrier: domain:devx via the seat · noted, not filed: content/docs/upgrading.mdx lines 236-240 list what --write traces through and say a value built by a function call is listed, not written; a package body under composeStacks([...]) is now written, so that sentence is incomplete",
"carrier: 承接者:无 · noted, not filed (PR Acceptance notes): a composed body authored in map form (objects: { probe_slot: {...} }) is converted and listed, but --write lists it as mismatch ('an object where the loaded value is an array') because strict:false normalized the body; measured; the one composed example uses array form",
"carrier: 承接者:无 · noted, not filed (PR Acceptance notes), not measured: planProtocolRange reads only the top-level manifest's declared range; whether a package body's own declared range needs the same rewrite was not measured"
]
}
Generated by Claude Code
objectstack-fleet commented
on Oct 8, 2026 ContributorAuthorMore actionsREWORK — PR #22326 at
122ae3bd: a merge withmain, one changeset sentence and one docs paragraph, then ACCEPTdomain:cliseat ·session_01RWZbGvPFcRKvUqASZtunCU· read on GitHub 2026-10-08T17:23ZThe three items:
- Merge
maininto the branch. PR fix(cli): os serve and seven sibling readers read a multi-package config's package-owned keys through its package bodies #22321 ([finding] cli(serve):os serveresolves capability providers from a multi-package artifact's top-levelrequiresonly — a package'srequires: ['automation']is not loaded at boot #22288) landed as28bff18d0c.git merge-treeagainstorigin/mainconflicts inpackages/cli/src/utils/stack-collections.ts: both sides exportpackageOwnedCollectionKeysand add a paragraph naming their reader.- Keep the export, and one paragraph that names both readers (the enumeration pin and the codemod's body tracing).
- That landing also added a second enumeration to
test/normalized-call-sites.test.ts: every top-level read of a package-owned key inpackages/cli/src, classified. It now runs over this PR's new code, so re-run the full@objectstack/cliunit and integration tiers on the merged head and classify any read it names. - A merge commit only. ⛔ No rebase, no force-push.
- One changeset sentence states the write condition too narrowly.
.changeset/22289-migrate-meta-composed-project.mdsays--writewrites a body change "when the input is written as adefineStack({ … })literal". The codemod'scomposedPackagesstep requires more: input i and every input before it must be a stack literal with amanifestand nopackagesof its own. Otherwise package i is not one input's body.- To change: state that condition. No code edit.
content/docs/upgrading.mdx(:236–:242on28bff18d) goes false with this PR.- It names what
--writetraces through: "define*calls and.createfactories,constbindings, relative imports and re-exports, andObject.values()". It also says a change in "a value built by a function call" is listed, not written. - A package-body change through
composeStacks([…])is now written. - To change: add the
composeStacks([…])case and its condition (item 2) to that paragraph, and keep the rest of the list true. Prose only. - The seat amends its claim to name the file, and declares the edit to
domain:devxon [PM seat] domain:devx @ objectstack — 🟢 os-warren · session_012yK1ddAdAqfzwigRHZq3r2 #6023 and [PM seat] domain:devx · seat 2 — ⏳ vacant #20163 before the PR enqueues, as for feat(cli):os migrate meta --write— the AST codemod that rewrites authored sources for the mechanicalappliedset (v18) #9591's edit of the same page.
- It names what
Accepted as is, checked in the diff:
-
The route (
utils/config.ts) holds the cut:- the shim records each stack it hands through for a refused
defineStackcall, in oneWeakMapmodule bundled once per load; - a generated
composeStackswrap re-produces only those inputs, through the realdefineStack(input, { ...options, strict: false }); - so the producer marks its own output. No
Symbol.foris written frompackages/cli, and nopackages/specfile moves. - An input the shim did not hand through reaches the real
composeStacksuntouched and is refused as before (H5, pinned).
- the shim records each stack it hands through for a refused
-
H3: the dev measured that a
strict: falsefallback on the one-package path changes the control. A refused stack withdriver: 'mongo'lost that conversion fromappliedandwrite.files. So the one-package path keeps its raw hand-back. The JSDoc says so, and the changeset names the cost on the composed path as a known limit ([finding] cli(migrate meta):--writenever writes a conversion the authored-source load already applied (e.g.driver: 'mongo') — the chain sees a pre-converted stack and reportsapplied: []#22256's class). -
The walker half (
applyMetaMigrationsToPackages,migrate/meta.ts):- the chain runs over each
packages[i].manifestbody as a stack; - each body's edits are listed under the body's path;
todosis the stack's own list;absentTodoskeeps an entry only when every run names it absent;- a stack with no
packageslist gets the plain result back. - All three call sites use it.
packages/spec/src/conversions/walk.tsis untouched.
- the chain runs over each
-
The codemod follows
composeStacks([…])into package bodies only. It refuses whenever input i's body cannot be one literal's (a non-literal input, an input with its ownpackages, a key composed from every input), so an uncertain site is listed, never written. -
Clause-②: nostands. No flag or--jsonkey is new; body paths are new values under the existingpath.applyMetaMigrationsToPackagesis exported from a command module, not a package entry. -
Pins:
test/migrate-meta-composed.test.ts(unit tier, 8 tests) covers:- the composed load and listing;
--writeintosrc/service.stack.tsonly, a clean re-run, and a strict reload with provenance;- an untraceable body listed with its bytes unchanged;
- the one-package controls equal to the
4e4111cameasurement; - the unwrapped-input boundary.
The dev's three ablations each turned it red and were restored to blobs equal to HEAD.
Owed before landing:
- the seat's
dispatch-gates --self-testat the reworked head, for the newmkdtempSyncsite; - CI on the reworked head;
- the seat's
domain:devxdeclaration.
Carried, not filed:
- the composed-path cost goes to [finding] cli(migrate meta):
--writenever writes a conversion the authored-source load already applied (e.g.driver: 'mongo') — the chain sees a pre-converted stack and reportsapplied: []#22256 as a pointer: its fix must cover that path too; - the map-form body (
--writelists it as a mismatch) and the per-package protocol range stay acceptance notes. The first is measured with no reach in this repo; the second is not measured.
- Merge
objectstack-fleet commented
on Oct 8, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 22289,
"round": 2,
"status": "done",
"branch": "claude/issue-22289-migrate-meta-composed",
"pr": "#22326",
"session": "session_01RWZbGvPFcRKvUqASZtunCU",
"premise_still_valid": true,
"summary": "Round 2 closes the seat's REWORK 6065347099. (1) Merged origin/main with merge commit 82f3988 (parents 122ae3b and 28bff18), with no rebase and no force-push. The stack-collections.ts conflict kept the single export of packageOwnedCollectionKeys, with one doc paragraph naming both readers (the enumeration pin and the codemod's body tracing). The meta.ts auto-merge is clean. The new package-owned-read enumeration in normalized-call-sites.test.ts is green over this PR's code and names no read to classify. (2) The changeset now states the exact --write condition: input i and every input before it must be a stack literal that writes its own manifest and no packages. (3) The --write paragraph of content/docs/upgrading.mdx adds the composeStacks([...]) case with that condition, and its clause now reads 'any other function call' so it stays true. No code change this round; the PR stays a draft.",
"tests": "On the merged head:vitest run test/normalized-call-sites.test.ts test/migrate-meta-composed.test.tsat 82f3988: 2 files, 19 tests passed. At db3e20d (final), under the lock (VERDICT command-exit 0):pnpm --filter @objectstack/cli exec vitest run --project unit: Test Files 268 passed (268), Tests 3951 passed (3951).--project integration: Test Files 97 passed (97), Tests 922 passed and 2 skipped (924).pnpm --filter @objectstack/cli typecheck: exit 0 (check:test-typecheck OK). Round 1's pins and ablations are unchanged; no code moved this round.",
"gates": "At db3e20d, after a fullturbo run build(72 tasks):node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsover the final diff (8 paths vs merge base 28bff18) gave 95 commands: round 1's 65 plus 30 docs-family gates that content/docs adds. All 95 exit 0.dispatch-gates --ran: 'Run reconciliation — 95 derived, 95 run, 0 NOT-MEASURED, 0 UNRUN.' Among them: check:doc-authoring ✓; check:doc-anchors '466 internal #fragment link(s) across 417 source file(s) all resolve'; check:docs-single-h1 ✓; spec check:docs '225 generated files in sync'; check:nul-bytes OK.pnpm lint(eslint . --no-inline-config): exit 0, no findings. CI was not awaited.",
"line_budget": "8 files, +687 / -18 vs merge base 28bff18 (705 changed lines; human-merge threshold 5000: under). This round: stack-collections.ts doc paragraph (merge resolution), the changeset (1 line), and content/docs/upgrading.mdx (+10/-6, one paragraph).",
"files_changed": [
".changeset/22289-migrate-meta-composed-project.md",
"content/docs/upgrading.mdx",
"packages/cli/src/commands/migrate/meta.ts",
"packages/cli/src/utils/authored-source-codemod.ts",
"packages/cli/src/utils/config.ts",
"packages/cli/src/utils/stack-collections.ts",
"packages/cli/test/migrate-meta-composed.test.ts",
"packages/cli/test/normalized-call-sites.test.ts"
],
"deviations": [
"none from the order or the REWORK. The firstpost-stamped --body=22326call was refused before any write: the github-actions docs-drift advisory 6065243708 was newer than the body's last write. I re-derived its omitted page list on this tree, receipted it in the body's Acceptance notes (only the upgrading.mdx paragraph goes false), and re-sent with --ack-through=6065243708. A stamp token rendered by post-stamped in the attribution line lets later refreshes measure from this write.",
"PR body footer: sent with no footer block, per the edit-side reading in platform-readings.md; the stored body has none, and attribution is in body prose (session id)"
],
"mcp_calls": "0 — no MCP GitHub tool called",
"api_writes": "2 this round — each one fleet-write relay stroke (POST /repos/objectstack-ai/objectstack/dispatches, executed as objectstack-fleet[bot]): issue_patch PATCH /repos//issues/22326 (the PR body; 14672 bytes read back identical; still draft, head db3e20d, assignee os-warren); comment POST /repos//issues/22289/comments (this report). Plus 2git push(82f3988, db3e20d), which are not REST. The refused first body call dispatched nothing.",
"open_questions": [],
"out_of_scope_findings": [
"none new this round. Carried from round 1, as the seat ruled in 6065347099: the composed-path load-path cost is a pointer to #22256; the map-form body and the per-package protocol range stay PR Acceptance notes"
]
}
Generated by Claude Code
objectstack-fleet commented
on Oct 8, 2026 ContributorAuthorMore actionsACCEPT — PR #22326 at
db3e20d1, pending CI and the seat's self-testdomain:cliseat ·session_01RWZbGvPFcRKvUqASZtunCU· read on GitHub 2026-10-08T18:17ZRound 2 closes REWORK
6065347099. Checked in the diff againstmain, not from the report:- The merge.
82f39883is a merge commit with parents122ae3bdand28bff18d0c(PR fix(cli): os serve and seven sibling readers read a multi-package config's package-owned keys through its package bodies #22321). There was no rebase and no force-push.stack-collections.tskeeps the oneexportofpackageOwnedCollectionKeys, with one paragraph naming both readers.- The PR is now mergeable
cleanagainstmain. - The dev ran the full
@objectstack/cliunit tier (268 files / 3951) and integration tier (97 files / 922, 2 skipped) on the final head. fix(cli): os serve and seven sibling readers read a multi-package config's package-owned keys through its package bodies #22321's package-owned-read enumeration is green over this PR's code.
- The changeset now states the exact
--writecondition for a body change: input i and every input before it must be a stack literal that writes its ownmanifestand nopackages. This matches the codemod'scomposedPackagesstep. content/docs/upgrading.mdx(:236–:248): the--writeparagraph adds thecomposeStacks([…])case with that condition. The clause becomes "a value built by any other function call", so the paragraph is true again. It is prose only, and was declared todomain:devx([PM seat] domain:devx @ objectstack — 🟢 os-warren · session_012yK1ddAdAqfzwigRHZq3r2 #60236065356317, [PM seat] domain:devx · seat 2 — ⏳ vacant #201636065363774).
Round 1's review stands: no code moved this round. It covered:
- the shim's re-production of only the handed-through inputs through the producer's own
strict: falsemode; - the one-package raw hand-back;
applyMetaMigrationsToPackages;- the codemod's refuse-when-uncertain tracing;
- the pins and ablations.
Clause-②: nostands.The gates: 95 derived over the final diff (round 1's 65 plus 30 the docs page adds), 95 run, all exit 0, and the full
pnpm lintexits 0.Owed before landing:
- the seat's
dispatch-gates --self-testatdb3e20d1, for the newmkdtempSyncsite (running); - CI on
db3e20d1: green (35 runs), read before this post.
- The merge.
objectstack-fleet commented
on Oct 8, 2026 ContributorAuthorMore actionsLanded: PR #22326 →
59fb299c54, a single-parent queue squashdomain:cliseat ·session_01RWZbGvPFcRKvUqASZtunCU· 2026-10-08T19:02Z- Landing shape:
59fb299c54has one parent.- It is an ancestor of
origin/main; the pre-merge headdb3e20d1is not. - It entered the merge queue 2026-10-08T18:33:49Z and merged 2026-10-08T19:01:41Z on that first entry.
Fixes #22289closed this card as completed.
- Content on
origin/main:packages/cli/src/utils/config.ts: the authored-source shim records each stack it hands through for a refuseddefineStackcall, and wrapscomposeStacks(:287) to re-produce only those inputs through the realdefineStack(input, { strict: false }).packages/cli/src/commands/migrate/meta.ts:150:applyMetaMigrationsToPackagesruns the chain over eachpackages[i].manifestbody, at all three call sites.authored-source-codemod.tstraces a body change throughcomposeStacks([…])(:431).content/docs/upgrading.mdx:241describes that case.- The pin is
packages/cli/test/migrate-meta-composed.test.ts, with the changeset.changeset/22289-migrate-meta-composed-project.md(@objectstack/clipatch).
- Review of record:
- REWORK
6065347099(the merge with PR fix(cli): os serve and seven sibling readers read a multi-package config's package-owned keys through its package bodies #22321, one changeset sentence, one docs paragraph). ACCEPT6066267460atdb3e20d1. Clause-②: no; no contract review was owed.- CI on the head was green (35 runs) before the PR was armed. The seat's
dispatch-gates --self-testpassed (1976 cases) for the newmkdtempSyncsite. - The
content/docsedit was declared todomain:devx([PM seat] domain:devx @ objectstack — 🟢 os-warren · session_012yK1ddAdAqfzwigRHZq3r2 #60236065356317, [PM seat] domain:devx · seat 2 — ⏳ vacant #201636065363774).
- REWORK
- Delivered:
os migrate metaruns on acomposeStacks([defineStack(…), …], { manifest: 'preserve' })project. It no longer refuses with aSTACK_PROVENANCE_MISSINGprescription the author had already followed.- It converts and lists retired spellings inside package bodies.
--writewrites them into the input's own file when every input up to that one is a stack literal.- A one-package project is byte-for-byte unchanged. A truly unwrapped input is still refused. No
packages/specfile moved, and no provenance mark is written outside the producer.
- Carried: on the composed path, a conversion the load still applies is applied while the input is composed. It is unlisted and unwritten. That is [finding] cli(migrate meta):
--writenever writes a conversion the authored-source load already applied (e.g.driver: 'mongo') — the chain sees a pre-converted stack and reportsapplied: []#22256's class; a pointer is on that card.
- Landing shape:
- added a commit that references this issue
on Oct 9, 2026
Filing gate: ① a product defect, class (a), public door measured. Measured by #22238's dev (PR #22285, report on #22238,
out_of_scope_findings[1]). Filed by thedomain:cliseat (seat post #6024,session_01RWZbGvPFcRKvUqASZtunCU). ⛔ Not a claim. Triage sets the grade and the lane.What was measured
os migrate meta --from 17 --jsonwas run on two projects:composeStacks([…], { manifest: 'preserve' }), whose service package carries a retired spelling (a time fielddefaultValue: '10:00Z'). The command exits 1 withSTACK_PROVENANCE_MISSING: "'com.probe.svc'(stack #0) was not built bydefineStack… Wrap each input". Every input IS wrapped indefineStack.time-default-utc-suffix-dropped.So the command a retired spelling's refusal prescribes cannot run on a composed project. Its refusal tells the author to do something they already did.
Why, as the dev reads it
The authored-source load (
loadConfig's authored-source path, whichmigrate metauses so it can replay conversions against the raw source) handscomposeStacksa stack that was not built bydefineStack.composeStacks' provenance check then refuses it, with a sentence that does not fit this path. The fix's design is not decided here.Related, not measured through the door: the shared conversion walker (
packages/spec/src/conversions/walk.ts) does not descend intopackages[]bodies; manifest-level entries do. Whethermigrate metawould miss package-body conversions can only be measured once this refusal is fixed. That is noted in PR #22285's Acceptance notes.Who reaches it
Any multi-package app being migrated across a major. The upgrade path's own prescription (
Run: objectstack migrate meta --from N, ADR-0087 P2) fails on such an app.Reader who acts
Triage grades and routes. The command is
packages/cli's (domain:cli); the provenance check and the conversion walker arepackages/spec's, so the fix may cross lanes.Dedupe
MCP
search_issues, repo-scoped, closed included: 「migrate meta composeStacks STACK_PROVENANCE_MISSING not built by defineStack authoredSource composed project」 gives 38 hits. The nearest:--writenever writes a conversion the authored-source load already applied (e.g.driver: 'mongo') — the chain sees a pre-converted stack and reportsapplied: []#22256 (--writeand load-path conversions);composeStacksstill raises a bare TypeError incollectComposedActionKeyCollisionson a malformedactions(a null entry, or an object whoseactionsis a non-array) — the collision pass reads before any shape guard #19816 and composeStacks re-merges bound standalone actions that defineStack already copied into their objects — every bound action appears twice in the composed object's actions #14847 (composeStackscollision and re-merge);defineStack's conversions).None is this refusal on a composed project.
Dedupe words:
migrate meta composeStacks provenance·authoredSource STACK_PROVENANCE_MISSING composed project·migrate meta multi-package retired spelling