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
cli build: the legacy runtime bundle hash changes on every identical rebuild, because the temp entry path (pid + Date.now()) is embedded in the bundle and its inline sourcemap #26478
Filing gate: ① a product defect with a deterministic reproduction. This is the repro #7651 was closed for lacking ("UNCONFIRMED … needs a deterministic-rebuild repro").
Business reason: os build names the legacy runtime bundle by content hash (objectstack-runtime.HASH.mjs) so that identical input gives an identical artifact. Today every rebuild of an unchanged app emits a new hash and a new runtimeModule ref in dist/objectstack.json. Builds are not reproducible, any cache or CDN keyed on the name is busted on every build, and a deploy diff always shows the artifact as changed.
Reader: packages/cli (src/utils/build-runtime.ts).
Dedupe (open AND closed): "objectstack-runtime bundle hash not deterministic rebuild content hash filename changes every build" → 2 hits. #7651 is this defect, closed not_planned for want of a repro. #20560 is unrelated.
reach: CLI, measured at 756220c4 on a scratch copy of the blank scaffold. Seen across 4+ consecutive builds in two fixtures.
Checklist item priority: P1
type: Bug
QA-source: #26476 · cli.hook-body-extraction-gates · observed beside the clauses
Reproduction:
In a scaffold, author one hook whose handler cannot be lowered to a body (for example one that calls a module-scope helper), so the build bundles it.
Run os build, then copy dist/objectstack-runtime.*.mjs aside.
Run os build again with nothing changed.
The new file has a different hash in its name, and runtimeModule in dist/objectstack.json changes with it. diff of the two .mjs files differs only in the // .objectstack-runtime.entry.PID.TIMESTAMP.mjs comment and in the inline sourcemap line.
Mechanism (traced):packages/cli/src/utils/build-runtime.ts names the temporary esbuild entry `.${baseName}.entry.${process.pid}.${Date.now()}.mjs` (around line 201). esbuild writes that path into the bundle as a comment, and into the sourcemap: 'inline' map (around line 227). The file name hash is sha256(code) over that output (around line 243), so it can never repeat.
Expected: a byte-identical rebuild produces a byte-identical bundle and the same name. For example, use a stable entry name (in a per-process temp dir if collisions matter), or hash the code with the entry path normalised out.
Claim: PM loop round 9 · card thread · the reproducible legacy runtime bundle
Session: session_01R1q2xdtYgU6FKrZ7LgjPCC (the seat); the card thread is session_01FEkQ5ozQ2e4NBxHuYv9Wph
Account: os-project-manager (the seat's linked user; the card's assignee)
Branch: claude/project-thread-k5tue6 (the card thread's harness-pinned branch; it names no issue, so this claim is the identity record)
Worktree: the card thread's own container checkout
Domain: domain:server
Seat: domain:server#1
Ruling-ref: triage 6434175591: two builds of an unchanged app give a byte-identical bundle, name and runtimeModule ref; a stable entry path, not a hash over stripped code. Intake split with domain:server#2 for the 18.2.0 wave-2 cards (#25807).
File surface: packages/cli/src/utils/build-runtime.ts, its tests and a patch changeset. ⛔ No packages/spec/** (lane red line).
Container & model: S, mode:thread, default model and effort (set at thread open)
Clause-②: no — the dev measures it on the diff
Metadata-protocol: none
Responsibility: every rebuild of an unchanged app ships a new artifact name, so caches and deploy diffs never settle
Thread-read: 6434175591
Premise: holds (read 2026-10-27T06:52Z at origin/mainc7d6ca8ee3: card open, pm:queue, no live claim)
Serial constraints cleared: none known on these paths; the dev re-measures open PRs on the files it touches before pr_create.
os-dev-report
{
"issue": 26478,
"status": "done",
"branch": "claude/project-thread-k5tue6",
"pr": "#26547",
"session": "session_01FEkQ5ozQ2e4NBxHuYv9Wph",
"premise_still_valid": true,
"summary": "Premise held at origin/main c7d6ca8: build-runtime.ts wrote the esbuild entry as .objectstack-runtime.entry.PID.TIMESTAMP.mjs, and esbuild printed that path (cwd-relative) into the bundle comment and inline sourcemap, so sha256(code) and the file name changed every build. buildRuntimeBundle now hands the generated entry to esbuild as stdin under the fixed name .objectstack-runtime.entry.mjs (resolveDir = the config dir, nothing written beside the config, so concurrent builds share no file) and sets absWorkingDir to the config dir. The cwd-relative path was the one other per-run value found, same mechanism, fixed in this PR: the same app built from two cwds now gives one name (objectstack-runtime.29956dd5d3b128f6.mjs both times). The order's example route (fixed name in a per-build mkdtemp dir) was not taken, because the random dir name would itself be printed into the same comment and sourcemap. Patch changeset on @objectstack/cli; no packages/spec change.",
"tests": "New packages/cli/test/build-runtime-reproducible.test.ts (unit tier, in-process, no CLI spawn): (1) two builds give same outputFileName, hash and bytes, one file in dist; (2) sourcemap sources are exactly the three config-relative names and the mkdtemp dir name is absent; (3) nothing left beside the config, and the imported module serves and runs the hook. Red first on base c7d6ca8 (test commit c1c07c8 alone): 'Tests 2 failed | 1 passed (3)', name objectstack-runtime.0d8a62ba362af40a.mjs vs objectstack-runtime.0509e52d02fdce77.mjs, sources '../../../../../tmp/os-build-runtime-reproducible-fADw6M/app/.objectstack-runtime.entry.1505.1793084124288.mjs'; lock VERDICT command-exit 1. Fix 37a263c: 'Tests 3 passed (3)', VERDICT command-exit 0. Ablation via scripts/ablation-replace.mjs of the absWorkingDir line (anchor 1 -> 0, blob 36fb893d -> d6c7a478): case 2 red with cwd-relative sources, cases 1 and 3 green; restored blob 36fb893d == HEAD, git diff HEAD empty (test imports ../src, no dist between edit and run). Whole cli unit tier at c914e2e: 336/338 files passed, the 2 others (published-subpath-console.pin, published-subpath-hook-body.pin) failed only on 'packages/cli is not built'; after pnpm --filter @objectstack/cli build they pass 29/29. pnpm --filter @objectstack/cli typecheck exit 0. eslint --no-inline-config on the 2 touched files exit 0. Integration tier declared to CI (no spawn entry or integration-tier file touched).",
"gates": "Local at c914e2e: dispatch-gates --commands --repo objectstack-ai/objectstack derived 61 families; --ran reconciles '61 derived, 60 run, 1 NOT-MEASURED, 0 UNRUN'. NOT MEASURED: pnpm check:dual-build-cjs-loads (exit 3 PREREQUISITE NOT MET, needs every package's dist; only the cli closure was built). check-plugin-teardown-shape --self-test, check:i18n, check:i18n-coverage, check:i18n-walk-parity first exited 3 (shallow clone, cli not yet built) and were re-run green after git fetch --unshallow and the cli build. All other 56 families exit 0. CI check-runs on PR #26547: in_progress at report time.",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"mcp_calls": "5 — mcp__github__issue_read x4 (get #26478, get_comments #26478 x2, get #7651), mcp__github__search_pull_requests x1; no MCP write tool",
"api_writes": "2 — fleet-write relay: POST repos/objectstack-ai/objectstack/dispatches for pr_create (run 40467732114, created #26547 with assignee os-project-manager, body read back 8771/8771 bytes identical); post-stamped os-dev-report comment on #26478. Plus git push (not a REST write). Write budget spent: 3 of 3 (push, pr_create, report).",
"open_questions": [],
"out_of_scope_findings": []
}
Activity
objectstack-fleet commentedon Oct 27, 2026
Triage: first grade —
bug·priority:p2·domain:server·area:devpath·pm:queue· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-27T05:01Z⛔ Not a claim, ⛔ not a dispatch.
os build's content-hashed legacy runtime bundle changes on every identical rebuild, because the temp entry path (pid +Date.now()) is embedded in the bundle and in its sourcemap. Make the entry path stable (or strip it), and pin with two identical builds giving one hash. This is the repro [finding] UNCONFIRMED: runtime bundle filename hash differs across byte-identical rebuilds — needs a deterministic-rebuild repro #7651 lacked. Found by the 18.2.0 wave-2 sweep ([sweep] v18.2.0 release test sweep #25807).Generated by Claude Code
objectstack-fleet commentedon Oct 27, 2026
Claim: PM loop round 9 · card thread · the reproducible legacy runtime bundle
Session:
session_01R1q2xdtYgU6FKrZ7LgjPCC(the seat); the card thread issession_01FEkQ5ozQ2e4NBxHuYv9WphAccount:
os-project-manager(the seat's linked user; the card's assignee)Branch:
claude/project-thread-k5tue6(the card thread's harness-pinned branch; it names no issue, so this claim is the identity record)Worktree: the card thread's own container checkout
Domain:
domain:serverSeat:
domain:server#1Ruling-ref: triage
6434175591: two builds of an unchanged app give a byte-identical bundle, name andruntimeModuleref; a stable entry path, not a hash over stripped code. Intake split withdomain:server#2for the 18.2.0 wave-2 cards (#25807).File surface:
packages/cli/src/utils/build-runtime.ts, its tests and apatchchangeset. ⛔ Nopackages/spec/**(lane red line).Container & model:
S,mode:thread, default model and effort (set at thread open)Clause-②: no — the dev measures it on the diff
Metadata-protocol: none
Responsibility: every rebuild of an unchanged app ships a new artifact name, so caches and deploy diffs never settle
Thread-read: 6434175591
Premise: holds (read 2026-10-27T06:52Z at
origin/mainc7d6ca8ee3: card open,pm:queue, no live claim)Serial constraints cleared: none known on these paths; the dev re-measures open PRs on the files it touches before
pr_create.objectstack-fleet commentedon Oct 27, 2026
os-dev-report
{
"issue": 26478,
"status": "done",
"branch": "claude/project-thread-k5tue6",
"pr": "#26547",
"session": "session_01FEkQ5ozQ2e4NBxHuYv9Wph",
"premise_still_valid": true,
"summary": "Premise held at origin/main c7d6ca8: build-runtime.ts wrote the esbuild entry as .objectstack-runtime.entry.PID.TIMESTAMP.mjs, and esbuild printed that path (cwd-relative) into the bundle comment and inline sourcemap, so sha256(code) and the file name changed every build. buildRuntimeBundle now hands the generated entry to esbuild as stdin under the fixed name .objectstack-runtime.entry.mjs (resolveDir = the config dir, nothing written beside the config, so concurrent builds share no file) and sets absWorkingDir to the config dir. The cwd-relative path was the one other per-run value found, same mechanism, fixed in this PR: the same app built from two cwds now gives one name (objectstack-runtime.29956dd5d3b128f6.mjs both times). The order's example route (fixed name in a per-build mkdtemp dir) was not taken, because the random dir name would itself be printed into the same comment and sourcemap. Patch changeset on @objectstack/cli; no packages/spec change.",
"tests": "New packages/cli/test/build-runtime-reproducible.test.ts (unit tier, in-process, no CLI spawn): (1) two builds give same outputFileName, hash and bytes, one file in dist; (2) sourcemap sources are exactly the three config-relative names and the mkdtemp dir name is absent; (3) nothing left beside the config, and the imported module serves and runs the hook. Red first on base c7d6ca8 (test commit c1c07c8 alone): 'Tests 2 failed | 1 passed (3)', name objectstack-runtime.0d8a62ba362af40a.mjs vs objectstack-runtime.0509e52d02fdce77.mjs, sources '../../../../../tmp/os-build-runtime-reproducible-fADw6M/app/.objectstack-runtime.entry.1505.1793084124288.mjs'; lock VERDICT command-exit 1. Fix 37a263c: 'Tests 3 passed (3)', VERDICT command-exit 0. Ablation via scripts/ablation-replace.mjs of the absWorkingDir line (anchor 1 -> 0, blob 36fb893d -> d6c7a478): case 2 red with cwd-relative sources, cases 1 and 3 green; restored blob 36fb893d == HEAD, git diff HEAD empty (test imports ../src, no dist between edit and run). Whole cli unit tier at c914e2e: 336/338 files passed, the 2 others (published-subpath-console.pin, published-subpath-hook-body.pin) failed only on 'packages/cli is not built'; after pnpm --filter @objectstack/cli build they pass 29/29. pnpm --filter @objectstack/cli typecheck exit 0. eslint --no-inline-config on the 2 touched files exit 0. Integration tier declared to CI (no spawn entry or integration-tier file touched).",
"gates": "Local at c914e2e: dispatch-gates --commands --repo objectstack-ai/objectstack derived 61 families; --ran reconciles '61 derived, 60 run, 1 NOT-MEASURED, 0 UNRUN'. NOT MEASURED: pnpm check:dual-build-cjs-loads (exit 3 PREREQUISITE NOT MET, needs every package's dist; only the cli closure was built). check-plugin-teardown-shape --self-test, check:i18n, check:i18n-coverage, check:i18n-walk-parity first exited 3 (shallow clone, cli not yet built) and were re-run green after git fetch --unshallow and the cli build. All other 56 families exit 0. CI check-runs on PR #26547: in_progress at report time.",
"dogfood_battery": "n/a — no
!in the PR title and no (narrowing) arm","mcp_calls": "5 — mcp__github__issue_read x4 (get #26478, get_comments #26478 x2, get #7651), mcp__github__search_pull_requests x1; no MCP write tool",
"api_writes": "2 — fleet-write relay: POST repos/objectstack-ai/objectstack/dispatches for pr_create (run 40467732114, created #26547 with assignee os-project-manager, body read back 8771/8771 bytes identical); post-stamped os-dev-report comment on #26478. Plus git push (not a REST write). Write budget spent: 3 of 3 (push, pr_create, report).",
"open_questions": [],
"out_of_scope_findings": []
}
Generated by Claude Code
objectstack-fleet commentedon Oct 27, 2026
Landed
PR #26547 merged at 2026-10-27T08:03Z by the merge queue as
ab3c776a95onmain(Fixes #26478; ACCEPT6436514018).git ls-remote origin 'refs/heads/gh-readonly-queue/main/pr-26547-*'origin/mainby contentgit cat-file -e origin/main:packages/cli/test/build-runtime-reproducible.test.tsgit merge-base --is-ancestor ab3c776a95 origin/mainState: this card closed by
Fixes(completed);pm:dispatchedremoved.Generated by Claude Code