fix(example-showcase): the nightly health sweep takes its engine off the job handler's argument - #14459

Merged
os-musk merged 4 commits into
mainfrom
claude/issue-14257-showcase-job-context
Sep 2, 2026
Merged

fix(example-showcase): the nightly health sweep takes its engine off the job handler's argument#14459
os-musk merged 4 commits into
mainfrom
claude/issue-14257-showcase-job-context

Conversation

@os-musk

Copy link
Copy Markdown
Collaborator

Fixes#14257

What was wrong

The showcase's nightly showcase_health_sweep handler held its engine in a module-scope let host, filled by an exported bindShowcaseJobRuntime(ctx) that objectstack.config.ts called from onEnable. With host unset the handler logged no engine handle bound yet — skipping this run and returned.

That binding does not exist on the artifact path: objectstack build emits functions into a sibling runtime module exporting only { functions, meta }, the artifact JSON carries no onEnable, and mergeRuntimeModule merges only functions. So on an artifact-served boot the sweep fired on schedule, recomputed nothing, and was reported as a clean run. This is the repo's only shipped defineJob, i.e. what an author copies.

What changed

  • src/automation/jobs/sweep-project-health.ts — the handler destructures { jobId, ql, logger } from its JobHandlerContext argument (A defineJob handler is invoked with { jobId, data, bundle } and no data reach, so the platform's only scheduled-work metadata shape cannot read or write a record #14094, type imported from @objectstack/runtime). Deleted: the module-scope host, the local JobHostContext / JobHostEngine interfaces, bindShowcaseJobRuntime, and the no engine handle bound yet early return. logger is now the platform Logger the context carries, so the optional-call spelling goes with it.
  • src/automation/jobs/index.ts — drops the bindShowcaseJobRuntime re-export.
  • objectstack.config.ts — drops the import and the onEnable call.
  • test/inert-wirings.test.ts — a fake CONTEXT instead of a fake host, plus the artifact-boot case this card is about.

effect: 'writes' on the functions entry is unchanged, per the card's triage. That declaration is about who counts the writes — a job has no downstream declarative node to count them, so undeclared a run reports having written nothing rather than "cannot say", which is indistinguishable from the broken sweep #4354 exists to detect. It never said anything about where the handle came from.

Two comment regions edited beyond the lines the dispatch named

Both are inside the three files already on the surface, but outside the named lines. Declared here because leaving them would have kept the reference app teaching the superseded shape in prose while its code no longer used it.

  1. objectstack.config.ts, the functions map docblock. It read "it writes over an engine handle captured at onEnable" — a sentence this PR makes false about the very entry it sits above. Evidence for the replacement wording: JobHandlerContext's own docblock in @objectstack/runtime, and content/docs/automation/jobs.mdx, which A defineJob handler is invoked with { jobId, data, bundle } and no data reach, so the platform's only scheduled-work metadata shape cannot read or write a record #14094 already updated to teach the argument (that page is correct as it stands and is untouched here).
  2. sweep-project-health.ts, healthFor's docblock. It pointed readers at test/job-health-sweep.test.ts. That file does not exist anywhere in the tree — a repo-wide grep finds this one mention and no file. Repointed at test/inert-wirings.test.ts, where those unit tests actually live.

Tests

test/inert-wirings.test.ts now builds the argument AppPlugin really passes. ql is declared satisfies the contract's own member types rather than a local interface, so a drift in IDataEngine.find / .update reds in this file instead of being absorbed by a hand-written approximation; the cast that follows widens only to the engine members this handler never touches. pnpm check:engine-double-contract is green with no new baseline row.

Three cases added, one of them the card's:

  • artifact-shaped boot — reach the handler through its functions entry, the one thing objectstack build emits and mergeRuntimeModule merges, with onEnable called nowhere in the file, and assert it reads both objects and writes the recomputed health.
  • the jobs module exports no bindShowcaseJobRuntime (the seam is gone from the export surface, not merely unused).
  • no authored source under src/orobjectstack.config.ts carries the seam or its skip branch, judged on comment-stripped text so documentation stays free to explain why it went.

Ablation (direction predicted before the run: RED)

Reverted the handler to a module-scope handle in the worktree, on top of the committed implementation. Mutation proved on disk by anchored counts before measuring — injected no engine handle bound yet 1, injected let host: JobHostContext 1, deleted { jobId, ql, logger }: JobHandlerContext 0, blob hash cd757ba moved to a9f19b9.

Tests 3 failed | 33 passed (36)
× recomputes when `functions` is all that was merged and `onEnable` never ran
AssertionError: expected [] to deeply equal [ 'showcase_project', 'showcase_task' ]
× sweeps only in-play projects and writes only what changed
× no authored source re-introduces the module-scope handle

Restored with git checkout HEAD -- ABSOLUTE_PATH; git diff HEAD empty and the blob hash back to cd757ba, byte-identical.

No dist/ leg applies to this ablation, and that is a measured property rather than an assumption: sweep-project-health.ts has exactly one import and it is import type, so the handler carries no runtime dependency to build, and the test resolves it from source. The source-only mutation flipping the suite red is itself the proof that no build artifact stands between them.

One prediction missed, and it is worth reading. I expected four failures; three came. is a no-op when nothing changed stayed GREEN under the ablation, because it asserts writes is empty and the broken handler writes nothing at all. That assertion passes vacuously against exactly the defect this card is about — the same shape as the production symptom, where a sweep that recomputed nothing was recorded as a clean run.

Gates

Run on final HEAD 7988daded (quoted from that same run), after git merge origin/main and a full install --frozen-lockfile plus turbo run build of the packages closure. Exit codes captured after redirect, never through a pipe.

  • pnpm --filter @objectstack/example-showcase typecheck — green. The app's include covers test/**, measured rather than assumed: before the test was rewritten this same command printed three errors, all of them in test/inert-wirings.test.ts.
  • pnpm --filter @objectstack/example-showcase exec vitest run --maxWorkers=2Test Files 26 passed (26), Tests 367 passed (367).
  • pnpm lint — repo-wide eslint . --no-inline-config, exit 0. Not narrowed.
  • The 22 families node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands derives from this diff: all green, plus the always-runs pnpm check:error-status-conformance.
  • One exception, recorded rather than counted as a pass: node scripts/check-test-completeness.mjs exits 3 with PREREQUISITE NOT MET — this gate grades a saved 'turbo run test' log, and no log was named, and its own text says "the local reading for this gate is NOT MEASURED. It is not a red, and there is nothing here to fix." CI passes it the teed log.

check:cross-package-test-inputs reds an intermediate commit here and the fix is worth knowing: it is a source scan, so a repo path spelled in a test comment is read as one of that test's real inputs. Naming mergeRuntimeModule's file by path made the gate demand a turbo inputs declaration for a file the test never reads.

Changeset

None, and skip-changeset applied. @objectstack/example-showcase is "private": true and publishes nothing; the changeset-check job in pr-automation.yml counts added .changeset/*.md unless that label is live-read on the PR, which is the exemption for a PR that declares no release of its own. Recent showcase-only fixes landed the same way.


🤖 Generated with Claude Code

https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68

Generated by Claude Code


Generated by Claude Code

…ext argument
The nightly `showcase_health_sweep` handler held its engine in a module-scope
`let host` that `onEnable` filled via an exported `bindShowcaseJobRuntime`.
That binding does not exist on the artifact path: `objectstack build` emits
`functions` into a sibling runtime module exporting only `{ functions, meta }`,
the artifact JSON carries no `onEnable`, and `mergeRuntimeModule` merges only
`functions` -- so on an artifact-served boot the handle stayed `undefined` and
the sweep recomputed nothing while reporting a clean run.
Take `jobId` / `ql` / `logger` off the handler's `JobHandlerContext` argument
(#14094) and delete the binding seam entirely: the module-scope `host`, the
`JobHostContext` / `JobHostEngine` local interfaces, `bindShowcaseJobRuntime`,
its re-export and its `onEnable` call. `effect: 'writes'` on the `functions`
entry is unchanged -- that declaration is about who counts the writes, not
about where the handle comes from.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
Swap the handler test's fake HOST for a fake CONTEXT: `jobRun()` builds the
`JobHandlerContext` `AppPlugin` passes, with `ql` declared `satisfies` the
contract's own member types so a drift in `IDataEngine.find`/`.update` reds
here rather than being absorbed by a hand-written approximation.
Adds the case this card is about: reach the handler through its `functions`
entry -- the only thing `objectstack build` emits and `mergeRuntimeModule`
merges -- with no `onEnable` called anywhere in the file, and assert it still
reads and recomputes. Plus two guards that the seam cannot return: the jobs
module exports no `bindShowcaseJobRuntime`, and no authored source (comments
stripped) carries the binding seam or its "no engine handle bound yet" branch.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
…t comment
`check:cross-package-test-inputs` is a SOURCE SCAN: a path literal anywhere in
a test file is read as one of that test's real inputs, comment or not. Naming
`mergeRuntimeModule`'s file by repo path made the gate demand a turbo `inputs`
declaration for a file this test never reads. Describe the module instead, and
say so in the comment so the next author does not put the path back.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
@os-muskClaude

Copy link
Copy Markdown
CollaboratorAuthor

Landing provenance — engine execution seat (session session_0112hMx9hjJ9BgB28X97DS68).

ACCEPT on the card: comment 5506367294 (#14257). Flip pre-checks on head 7988daded: every one of the 39 check runs completed with conclusion success or skipped (Lint & Repo Gates completed 08:12:56Z; Check Changeset skipped under the live-read skip-changeset label — @objectstack/example-showcase is private); governed-surface test on the PR's 4 paths: NOT governed — ordinary queue landing applies; closing-keyword two-read done at ACCEPT (Fixes #14257, correct). Clause-② self-reading no (example app; no contract member moves), so no contract-review carrier applied.

Action: draft: false then auto-merge (squash) — the merge queue takes it from here.


Generated by Claude Code

@os-musk
os-musk enabled auto-merge September 2, 2026 08:14
@os-musk
os-musk added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 253da34Sep 2, 2026
41 checks passed
@os-musk
os-musk deleted the claude/issue-14257-showcase-job-context branch September 2, 2026 08:50
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

app-showcase's nightly health sweep reaches its engine through a module-scope global, so it silently does nothing on an artifact-served boot

2 participants

@os-musk@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

fix(example-showcase): the nightly health sweep takes its engine off the job handler's argument - #14459

Merged
os-musk merged 4 commits into
mainfrom
claude/issue-14257-showcase-job-context
Sep 2, 2026
Merged

fix(example-showcase): the nightly health sweep takes its engine off the job handler's argument#14459
os-musk merged 4 commits into
mainfrom
claude/issue-14257-showcase-job-context

Conversation

@os-musk

Copy link
Copy Markdown
Collaborator

Fixes#14257

What was wrong

The showcase's nightly showcase_health_sweep handler held its engine in a module-scope let host, filled by an exported bindShowcaseJobRuntime(ctx) that objectstack.config.ts called from onEnable. With host unset the handler logged no engine handle bound yet — skipping this run and returned.

That binding does not exist on the artifact path: objectstack build emits functions into a sibling runtime module exporting only { functions, meta }, the artifact JSON carries no onEnable, and mergeRuntimeModule merges only functions. So on an artifact-served boot the sweep fired on schedule, recomputed nothing, and was reported as a clean run. This is the repo's only shipped defineJob, i.e. what an author copies.

What changed

  • src/automation/jobs/sweep-project-health.ts — the handler destructures { jobId, ql, logger } from its JobHandlerContext argument (A defineJob handler is invoked with { jobId, data, bundle } and no data reach, so the platform's only scheduled-work metadata shape cannot read or write a record #14094, type imported from @objectstack/runtime). Deleted: the module-scope host, the local JobHostContext / JobHostEngine interfaces, bindShowcaseJobRuntime, and the no engine handle bound yet early return. logger is now the platform Logger the context carries, so the optional-call spelling goes with it.
  • src/automation/jobs/index.ts — drops the bindShowcaseJobRuntime re-export.
  • objectstack.config.ts — drops the import and the onEnable call.
  • test/inert-wirings.test.ts — a fake CONTEXT instead of a fake host, plus the artifact-boot case this card is about.

effect: 'writes' on the functions entry is unchanged, per the card's triage. That declaration is about who counts the writes — a job has no downstream declarative node to count them, so undeclared a run reports having written nothing rather than "cannot say", which is indistinguishable from the broken sweep #4354 exists to detect. It never said anything about where the handle came from.

Two comment regions edited beyond the lines the dispatch named

Both are inside the three files already on the surface, but outside the named lines. Declared here because leaving them would have kept the reference app teaching the superseded shape in prose while its code no longer used it.

  1. objectstack.config.ts, the functions map docblock. It read "it writes over an engine handle captured at onEnable" — a sentence this PR makes false about the very entry it sits above. Evidence for the replacement wording: JobHandlerContext's own docblock in @objectstack/runtime, and content/docs/automation/jobs.mdx, which A defineJob handler is invoked with { jobId, data, bundle } and no data reach, so the platform's only scheduled-work metadata shape cannot read or write a record #14094 already updated to teach the argument (that page is correct as it stands and is untouched here).
  2. sweep-project-health.ts, healthFor's docblock. It pointed readers at test/job-health-sweep.test.ts. That file does not exist anywhere in the tree — a repo-wide grep finds this one mention and no file. Repointed at test/inert-wirings.test.ts, where those unit tests actually live.

Tests

test/inert-wirings.test.ts now builds the argument AppPlugin really passes. ql is declared satisfies the contract's own member types rather than a local interface, so a drift in IDataEngine.find / .update reds in this file instead of being absorbed by a hand-written approximation; the cast that follows widens only to the engine members this handler never touches. pnpm check:engine-double-contract is green with no new baseline row.

Three cases added, one of them the card's:

  • artifact-shaped boot — reach the handler through its functions entry, the one thing objectstack build emits and mergeRuntimeModule merges, with onEnable called nowhere in the file, and assert it reads both objects and writes the recomputed health.
  • the jobs module exports no bindShowcaseJobRuntime (the seam is gone from the export surface, not merely unused).
  • no authored source under src/orobjectstack.config.ts carries the seam or its skip branch, judged on comment-stripped text so documentation stays free to explain why it went.

Ablation (direction predicted before the run: RED)

Reverted the handler to a module-scope handle in the worktree, on top of the committed implementation. Mutation proved on disk by anchored counts before measuring — injected no engine handle bound yet 1, injected let host: JobHostContext 1, deleted { jobId, ql, logger }: JobHandlerContext 0, blob hash cd757ba moved to a9f19b9.

Tests 3 failed | 33 passed (36)
× recomputes when `functions` is all that was merged and `onEnable` never ran
AssertionError: expected [] to deeply equal [ 'showcase_project', 'showcase_task' ]
× sweeps only in-play projects and writes only what changed
× no authored source re-introduces the module-scope handle

Restored with git checkout HEAD -- ABSOLUTE_PATH; git diff HEAD empty and the blob hash back to cd757ba, byte-identical.

No dist/ leg applies to this ablation, and that is a measured property rather than an assumption: sweep-project-health.ts has exactly one import and it is import type, so the handler carries no runtime dependency to build, and the test resolves it from source. The source-only mutation flipping the suite red is itself the proof that no build artifact stands between them.

One prediction missed, and it is worth reading. I expected four failures; three came. is a no-op when nothing changed stayed GREEN under the ablation, because it asserts writes is empty and the broken handler writes nothing at all. That assertion passes vacuously against exactly the defect this card is about — the same shape as the production symptom, where a sweep that recomputed nothing was recorded as a clean run.

Gates

Run on final HEAD 7988daded (quoted from that same run), after git merge origin/main and a full install --frozen-lockfile plus turbo run build of the packages closure. Exit codes captured after redirect, never through a pipe.

  • pnpm --filter @objectstack/example-showcase typecheck — green. The app's include covers test/**, measured rather than assumed: before the test was rewritten this same command printed three errors, all of them in test/inert-wirings.test.ts.
  • pnpm --filter @objectstack/example-showcase exec vitest run --maxWorkers=2Test Files 26 passed (26), Tests 367 passed (367).
  • pnpm lint — repo-wide eslint . --no-inline-config, exit 0. Not narrowed.
  • The 22 families node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands derives from this diff: all green, plus the always-runs pnpm check:error-status-conformance.
  • One exception, recorded rather than counted as a pass: node scripts/check-test-completeness.mjs exits 3 with PREREQUISITE NOT MET — this gate grades a saved 'turbo run test' log, and no log was named, and its own text says "the local reading for this gate is NOT MEASURED. It is not a red, and there is nothing here to fix." CI passes it the teed log.

check:cross-package-test-inputs reds an intermediate commit here and the fix is worth knowing: it is a source scan, so a repo path spelled in a test comment is read as one of that test's real inputs. Naming mergeRuntimeModule's file by path made the gate demand a turbo inputs declaration for a file the test never reads.

Changeset

None, and skip-changeset applied. @objectstack/example-showcase is "private": true and publishes nothing; the changeset-check job in pr-automation.yml counts added .changeset/*.md unless that label is live-read on the PR, which is the exemption for a PR that declares no release of its own. Recent showcase-only fixes landed the same way.


🤖 Generated with Claude Code

https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68

Generated by Claude Code


Generated by Claude Code

…ext argument
The nightly `showcase_health_sweep` handler held its engine in a module-scope
`let host` that `onEnable` filled via an exported `bindShowcaseJobRuntime`.
That binding does not exist on the artifact path: `objectstack build` emits
`functions` into a sibling runtime module exporting only `{ functions, meta }`,
the artifact JSON carries no `onEnable`, and `mergeRuntimeModule` merges only
`functions` -- so on an artifact-served boot the handle stayed `undefined` and
the sweep recomputed nothing while reporting a clean run.
Take `jobId` / `ql` / `logger` off the handler's `JobHandlerContext` argument
(#14094) and delete the binding seam entirely: the module-scope `host`, the
`JobHostContext` / `JobHostEngine` local interfaces, `bindShowcaseJobRuntime`,
its re-export and its `onEnable` call. `effect: 'writes'` on the `functions`
entry is unchanged -- that declaration is about who counts the writes, not
about where the handle comes from.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
Swap the handler test's fake HOST for a fake CONTEXT: `jobRun()` builds the
`JobHandlerContext` `AppPlugin` passes, with `ql` declared `satisfies` the
contract's own member types so a drift in `IDataEngine.find`/`.update` reds
here rather than being absorbed by a hand-written approximation.
Adds the case this card is about: reach the handler through its `functions`
entry -- the only thing `objectstack build` emits and `mergeRuntimeModule`
merges -- with no `onEnable` called anywhere in the file, and assert it still
reads and recomputes. Plus two guards that the seam cannot return: the jobs
module exports no `bindShowcaseJobRuntime`, and no authored source (comments
stripped) carries the binding seam or its "no engine handle bound yet" branch.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
…t comment
`check:cross-package-test-inputs` is a SOURCE SCAN: a path literal anywhere in
a test file is read as one of that test's real inputs, comment or not. Naming
`mergeRuntimeModule`'s file by repo path made the gate demand a turbo `inputs`
declaration for a file this test never reads. Describe the module instead, and
say so in the comment so the next author does not put the path back.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
@os-muskClaude

Copy link
Copy Markdown
CollaboratorAuthor

Landing provenance — engine execution seat (session session_0112hMx9hjJ9BgB28X97DS68).

ACCEPT on the card: comment 5506367294 (#14257). Flip pre-checks on head 7988daded: every one of the 39 check runs completed with conclusion success or skipped (Lint & Repo Gates completed 08:12:56Z; Check Changeset skipped under the live-read skip-changeset label — @objectstack/example-showcase is private); governed-surface test on the PR's 4 paths: NOT governed — ordinary queue landing applies; closing-keyword two-read done at ACCEPT (Fixes #14257, correct). Clause-② self-reading no (example app; no contract member moves), so no contract-review carrier applied.

Action: draft: false then auto-merge (squash) — the merge queue takes it from here.


Generated by Claude Code

@os-musk
os-musk enabled auto-merge September 2, 2026 08:14
@os-musk
os-musk added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 253da34Sep 2, 2026
41 checks passed
@os-musk
os-musk deleted the claude/issue-14257-showcase-job-context branch September 2, 2026 08:50
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

app-showcase's nightly health sweep reaches its engine through a module-scope global, so it silently does nothing on an artifact-served boot

2 participants

@os-musk@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(example-showcase): the nightly health sweep takes its engine off the job handler's argument - #14459

Merged
os-musk merged 4 commits into
mainfrom
claude/issue-14257-showcase-job-context
Sep 2, 2026
Merged

fix(example-showcase): the nightly health sweep takes its engine off the job handler's argument#14459
os-musk merged 4 commits into
mainfrom
claude/issue-14257-showcase-job-context

Conversation

@os-musk

Copy link
Copy Markdown
Collaborator

Fixes#14257

What was wrong

The showcase's nightly showcase_health_sweep handler held its engine in a module-scope let host, filled by an exported bindShowcaseJobRuntime(ctx) that objectstack.config.ts called from onEnable. With host unset the handler logged no engine handle bound yet — skipping this run and returned.

That binding does not exist on the artifact path: objectstack build emits functions into a sibling runtime module exporting only { functions, meta }, the artifact JSON carries no onEnable, and mergeRuntimeModule merges only functions. So on an artifact-served boot the sweep fired on schedule, recomputed nothing, and was reported as a clean run. This is the repo's only shipped defineJob, i.e. what an author copies.

What changed

  • src/automation/jobs/sweep-project-health.ts — the handler destructures { jobId, ql, logger } from its JobHandlerContext argument (A defineJob handler is invoked with { jobId, data, bundle } and no data reach, so the platform's only scheduled-work metadata shape cannot read or write a record #14094, type imported from @objectstack/runtime). Deleted: the module-scope host, the local JobHostContext / JobHostEngine interfaces, bindShowcaseJobRuntime, and the no engine handle bound yet early return. logger is now the platform Logger the context carries, so the optional-call spelling goes with it.
  • src/automation/jobs/index.ts — drops the bindShowcaseJobRuntime re-export.
  • objectstack.config.ts — drops the import and the onEnable call.
  • test/inert-wirings.test.ts — a fake CONTEXT instead of a fake host, plus the artifact-boot case this card is about.

effect: 'writes' on the functions entry is unchanged, per the card's triage. That declaration is about who counts the writes — a job has no downstream declarative node to count them, so undeclared a run reports having written nothing rather than "cannot say", which is indistinguishable from the broken sweep #4354 exists to detect. It never said anything about where the handle came from.

Two comment regions edited beyond the lines the dispatch named

Both are inside the three files already on the surface, but outside the named lines. Declared here because leaving them would have kept the reference app teaching the superseded shape in prose while its code no longer used it.

  1. objectstack.config.ts, the functions map docblock. It read "it writes over an engine handle captured at onEnable" — a sentence this PR makes false about the very entry it sits above. Evidence for the replacement wording: JobHandlerContext's own docblock in @objectstack/runtime, and content/docs/automation/jobs.mdx, which A defineJob handler is invoked with { jobId, data, bundle } and no data reach, so the platform's only scheduled-work metadata shape cannot read or write a record #14094 already updated to teach the argument (that page is correct as it stands and is untouched here).
  2. sweep-project-health.ts, healthFor's docblock. It pointed readers at test/job-health-sweep.test.ts. That file does not exist anywhere in the tree — a repo-wide grep finds this one mention and no file. Repointed at test/inert-wirings.test.ts, where those unit tests actually live.

Tests

test/inert-wirings.test.ts now builds the argument AppPlugin really passes. ql is declared satisfies the contract's own member types rather than a local interface, so a drift in IDataEngine.find / .update reds in this file instead of being absorbed by a hand-written approximation; the cast that follows widens only to the engine members this handler never touches. pnpm check:engine-double-contract is green with no new baseline row.

Three cases added, one of them the card's:

  • artifact-shaped boot — reach the handler through its functions entry, the one thing objectstack build emits and mergeRuntimeModule merges, with onEnable called nowhere in the file, and assert it reads both objects and writes the recomputed health.
  • the jobs module exports no bindShowcaseJobRuntime (the seam is gone from the export surface, not merely unused).
  • no authored source under src/orobjectstack.config.ts carries the seam or its skip branch, judged on comment-stripped text so documentation stays free to explain why it went.

Ablation (direction predicted before the run: RED)

Reverted the handler to a module-scope handle in the worktree, on top of the committed implementation. Mutation proved on disk by anchored counts before measuring — injected no engine handle bound yet 1, injected let host: JobHostContext 1, deleted { jobId, ql, logger }: JobHandlerContext 0, blob hash cd757ba moved to a9f19b9.

Tests 3 failed | 33 passed (36)
× recomputes when `functions` is all that was merged and `onEnable` never ran
AssertionError: expected [] to deeply equal [ 'showcase_project', 'showcase_task' ]
× sweeps only in-play projects and writes only what changed
× no authored source re-introduces the module-scope handle

Restored with git checkout HEAD -- ABSOLUTE_PATH; git diff HEAD empty and the blob hash back to cd757ba, byte-identical.

No dist/ leg applies to this ablation, and that is a measured property rather than an assumption: sweep-project-health.ts has exactly one import and it is import type, so the handler carries no runtime dependency to build, and the test resolves it from source. The source-only mutation flipping the suite red is itself the proof that no build artifact stands between them.

One prediction missed, and it is worth reading. I expected four failures; three came. is a no-op when nothing changed stayed GREEN under the ablation, because it asserts writes is empty and the broken handler writes nothing at all. That assertion passes vacuously against exactly the defect this card is about — the same shape as the production symptom, where a sweep that recomputed nothing was recorded as a clean run.

Gates

Run on final HEAD 7988daded (quoted from that same run), after git merge origin/main and a full install --frozen-lockfile plus turbo run build of the packages closure. Exit codes captured after redirect, never through a pipe.

  • pnpm --filter @objectstack/example-showcase typecheck — green. The app's include covers test/**, measured rather than assumed: before the test was rewritten this same command printed three errors, all of them in test/inert-wirings.test.ts.
  • pnpm --filter @objectstack/example-showcase exec vitest run --maxWorkers=2Test Files 26 passed (26), Tests 367 passed (367).
  • pnpm lint — repo-wide eslint . --no-inline-config, exit 0. Not narrowed.
  • The 22 families node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands derives from this diff: all green, plus the always-runs pnpm check:error-status-conformance.
  • One exception, recorded rather than counted as a pass: node scripts/check-test-completeness.mjs exits 3 with PREREQUISITE NOT MET — this gate grades a saved 'turbo run test' log, and no log was named, and its own text says "the local reading for this gate is NOT MEASURED. It is not a red, and there is nothing here to fix." CI passes it the teed log.

check:cross-package-test-inputs reds an intermediate commit here and the fix is worth knowing: it is a source scan, so a repo path spelled in a test comment is read as one of that test's real inputs. Naming mergeRuntimeModule's file by path made the gate demand a turbo inputs declaration for a file the test never reads.

Changeset

None, and skip-changeset applied. @objectstack/example-showcase is "private": true and publishes nothing; the changeset-check job in pr-automation.yml counts added .changeset/*.md unless that label is live-read on the PR, which is the exemption for a PR that declares no release of its own. Recent showcase-only fixes landed the same way.


🤖 Generated with Claude Code

https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68

Generated by Claude Code


Generated by Claude Code

…ext argument
The nightly `showcase_health_sweep` handler held its engine in a module-scope
`let host` that `onEnable` filled via an exported `bindShowcaseJobRuntime`.
That binding does not exist on the artifact path: `objectstack build` emits
`functions` into a sibling runtime module exporting only `{ functions, meta }`,
the artifact JSON carries no `onEnable`, and `mergeRuntimeModule` merges only
`functions` -- so on an artifact-served boot the handle stayed `undefined` and
the sweep recomputed nothing while reporting a clean run.
Take `jobId` / `ql` / `logger` off the handler's `JobHandlerContext` argument
(#14094) and delete the binding seam entirely: the module-scope `host`, the
`JobHostContext` / `JobHostEngine` local interfaces, `bindShowcaseJobRuntime`,
its re-export and its `onEnable` call. `effect: 'writes'` on the `functions`
entry is unchanged -- that declaration is about who counts the writes, not
about where the handle comes from.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
Swap the handler test's fake HOST for a fake CONTEXT: `jobRun()` builds the
`JobHandlerContext` `AppPlugin` passes, with `ql` declared `satisfies` the
contract's own member types so a drift in `IDataEngine.find`/`.update` reds
here rather than being absorbed by a hand-written approximation.
Adds the case this card is about: reach the handler through its `functions`
entry -- the only thing `objectstack build` emits and `mergeRuntimeModule`
merges -- with no `onEnable` called anywhere in the file, and assert it still
reads and recomputes. Plus two guards that the seam cannot return: the jobs
module exports no `bindShowcaseJobRuntime`, and no authored source (comments
stripped) carries the binding seam or its "no engine handle bound yet" branch.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
…t comment
`check:cross-package-test-inputs` is a SOURCE SCAN: a path literal anywhere in
a test file is read as one of that test's real inputs, comment or not. Naming
`mergeRuntimeModule`'s file by repo path made the gate demand a turbo `inputs`
declaration for a file this test never reads. Describe the module instead, and
say so in the comment so the next author does not put the path back.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
@os-muskClaude

Copy link
Copy Markdown
CollaboratorAuthor

Landing provenance — engine execution seat (session session_0112hMx9hjJ9BgB28X97DS68).

ACCEPT on the card: comment 5506367294 (#14257). Flip pre-checks on head 7988daded: every one of the 39 check runs completed with conclusion success or skipped (Lint & Repo Gates completed 08:12:56Z; Check Changeset skipped under the live-read skip-changeset label — @objectstack/example-showcase is private); governed-surface test on the PR's 4 paths: NOT governed — ordinary queue landing applies; closing-keyword two-read done at ACCEPT (Fixes #14257, correct). Clause-② self-reading no (example app; no contract member moves), so no contract-review carrier applied.

Action: draft: false then auto-merge (squash) — the merge queue takes it from here.


Generated by Claude Code

@os-musk
os-musk enabled auto-merge September 2, 2026 08:14
@os-musk
os-musk added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 253da34Sep 2, 2026
41 checks passed
@os-musk
os-musk deleted the claude/issue-14257-showcase-job-context branch September 2, 2026 08:50
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

app-showcase's nightly health sweep reaches its engine through a module-scope global, so it silently does nothing on an artifact-served boot

2 participants

@os-musk@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(example-showcase): the nightly health sweep takes its engine off the job handler's argument - #14459

Merged
os-musk merged 4 commits into
mainfrom
claude/issue-14257-showcase-job-context
Sep 2, 2026
Merged

fix(example-showcase): the nightly health sweep takes its engine off the job handler's argument#14459
os-musk merged 4 commits into
mainfrom
claude/issue-14257-showcase-job-context

Conversation

@os-musk

Copy link
Copy Markdown
Collaborator

Fixes#14257

What was wrong

The showcase's nightly showcase_health_sweep handler held its engine in a module-scope let host, filled by an exported bindShowcaseJobRuntime(ctx) that objectstack.config.ts called from onEnable. With host unset the handler logged no engine handle bound yet — skipping this run and returned.

That binding does not exist on the artifact path: objectstack build emits functions into a sibling runtime module exporting only { functions, meta }, the artifact JSON carries no onEnable, and mergeRuntimeModule merges only functions. So on an artifact-served boot the sweep fired on schedule, recomputed nothing, and was reported as a clean run. This is the repo's only shipped defineJob, i.e. what an author copies.

What changed

  • src/automation/jobs/sweep-project-health.ts — the handler destructures { jobId, ql, logger } from its JobHandlerContext argument (A defineJob handler is invoked with { jobId, data, bundle } and no data reach, so the platform's only scheduled-work metadata shape cannot read or write a record #14094, type imported from @objectstack/runtime). Deleted: the module-scope host, the local JobHostContext / JobHostEngine interfaces, bindShowcaseJobRuntime, and the no engine handle bound yet early return. logger is now the platform Logger the context carries, so the optional-call spelling goes with it.
  • src/automation/jobs/index.ts — drops the bindShowcaseJobRuntime re-export.
  • objectstack.config.ts — drops the import and the onEnable call.
  • test/inert-wirings.test.ts — a fake CONTEXT instead of a fake host, plus the artifact-boot case this card is about.

effect: 'writes' on the functions entry is unchanged, per the card's triage. That declaration is about who counts the writes — a job has no downstream declarative node to count them, so undeclared a run reports having written nothing rather than "cannot say", which is indistinguishable from the broken sweep #4354 exists to detect. It never said anything about where the handle came from.

Two comment regions edited beyond the lines the dispatch named

Both are inside the three files already on the surface, but outside the named lines. Declared here because leaving them would have kept the reference app teaching the superseded shape in prose while its code no longer used it.

  1. objectstack.config.ts, the functions map docblock. It read "it writes over an engine handle captured at onEnable" — a sentence this PR makes false about the very entry it sits above. Evidence for the replacement wording: JobHandlerContext's own docblock in @objectstack/runtime, and content/docs/automation/jobs.mdx, which A defineJob handler is invoked with { jobId, data, bundle } and no data reach, so the platform's only scheduled-work metadata shape cannot read or write a record #14094 already updated to teach the argument (that page is correct as it stands and is untouched here).
  2. sweep-project-health.ts, healthFor's docblock. It pointed readers at test/job-health-sweep.test.ts. That file does not exist anywhere in the tree — a repo-wide grep finds this one mention and no file. Repointed at test/inert-wirings.test.ts, where those unit tests actually live.

Tests

test/inert-wirings.test.ts now builds the argument AppPlugin really passes. ql is declared satisfies the contract's own member types rather than a local interface, so a drift in IDataEngine.find / .update reds in this file instead of being absorbed by a hand-written approximation; the cast that follows widens only to the engine members this handler never touches. pnpm check:engine-double-contract is green with no new baseline row.

Three cases added, one of them the card's:

  • artifact-shaped boot — reach the handler through its functions entry, the one thing objectstack build emits and mergeRuntimeModule merges, with onEnable called nowhere in the file, and assert it reads both objects and writes the recomputed health.
  • the jobs module exports no bindShowcaseJobRuntime (the seam is gone from the export surface, not merely unused).
  • no authored source under src/orobjectstack.config.ts carries the seam or its skip branch, judged on comment-stripped text so documentation stays free to explain why it went.

Ablation (direction predicted before the run: RED)

Reverted the handler to a module-scope handle in the worktree, on top of the committed implementation. Mutation proved on disk by anchored counts before measuring — injected no engine handle bound yet 1, injected let host: JobHostContext 1, deleted { jobId, ql, logger }: JobHandlerContext 0, blob hash cd757ba moved to a9f19b9.

Tests 3 failed | 33 passed (36)
× recomputes when `functions` is all that was merged and `onEnable` never ran
AssertionError: expected [] to deeply equal [ 'showcase_project', 'showcase_task' ]
× sweeps only in-play projects and writes only what changed
× no authored source re-introduces the module-scope handle

Restored with git checkout HEAD -- ABSOLUTE_PATH; git diff HEAD empty and the blob hash back to cd757ba, byte-identical.

No dist/ leg applies to this ablation, and that is a measured property rather than an assumption: sweep-project-health.ts has exactly one import and it is import type, so the handler carries no runtime dependency to build, and the test resolves it from source. The source-only mutation flipping the suite red is itself the proof that no build artifact stands between them.

One prediction missed, and it is worth reading. I expected four failures; three came. is a no-op when nothing changed stayed GREEN under the ablation, because it asserts writes is empty and the broken handler writes nothing at all. That assertion passes vacuously against exactly the defect this card is about — the same shape as the production symptom, where a sweep that recomputed nothing was recorded as a clean run.

Gates

Run on final HEAD 7988daded (quoted from that same run), after git merge origin/main and a full install --frozen-lockfile plus turbo run build of the packages closure. Exit codes captured after redirect, never through a pipe.

  • pnpm --filter @objectstack/example-showcase typecheck — green. The app's include covers test/**, measured rather than assumed: before the test was rewritten this same command printed three errors, all of them in test/inert-wirings.test.ts.
  • pnpm --filter @objectstack/example-showcase exec vitest run --maxWorkers=2Test Files 26 passed (26), Tests 367 passed (367).
  • pnpm lint — repo-wide eslint . --no-inline-config, exit 0. Not narrowed.
  • The 22 families node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands derives from this diff: all green, plus the always-runs pnpm check:error-status-conformance.
  • One exception, recorded rather than counted as a pass: node scripts/check-test-completeness.mjs exits 3 with PREREQUISITE NOT MET — this gate grades a saved 'turbo run test' log, and no log was named, and its own text says "the local reading for this gate is NOT MEASURED. It is not a red, and there is nothing here to fix." CI passes it the teed log.

check:cross-package-test-inputs reds an intermediate commit here and the fix is worth knowing: it is a source scan, so a repo path spelled in a test comment is read as one of that test's real inputs. Naming mergeRuntimeModule's file by path made the gate demand a turbo inputs declaration for a file the test never reads.

Changeset

None, and skip-changeset applied. @objectstack/example-showcase is "private": true and publishes nothing; the changeset-check job in pr-automation.yml counts added .changeset/*.md unless that label is live-read on the PR, which is the exemption for a PR that declares no release of its own. Recent showcase-only fixes landed the same way.


🤖 Generated with Claude Code

https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68

Generated by Claude Code


Generated by Claude Code

…ext argument
The nightly `showcase_health_sweep` handler held its engine in a module-scope
`let host` that `onEnable` filled via an exported `bindShowcaseJobRuntime`.
That binding does not exist on the artifact path: `objectstack build` emits
`functions` into a sibling runtime module exporting only `{ functions, meta }`,
the artifact JSON carries no `onEnable`, and `mergeRuntimeModule` merges only
`functions` -- so on an artifact-served boot the handle stayed `undefined` and
the sweep recomputed nothing while reporting a clean run.
Take `jobId` / `ql` / `logger` off the handler's `JobHandlerContext` argument
(#14094) and delete the binding seam entirely: the module-scope `host`, the
`JobHostContext` / `JobHostEngine` local interfaces, `bindShowcaseJobRuntime`,
its re-export and its `onEnable` call. `effect: 'writes'` on the `functions`
entry is unchanged -- that declaration is about who counts the writes, not
about where the handle comes from.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
Swap the handler test's fake HOST for a fake CONTEXT: `jobRun()` builds the
`JobHandlerContext` `AppPlugin` passes, with `ql` declared `satisfies` the
contract's own member types so a drift in `IDataEngine.find`/`.update` reds
here rather than being absorbed by a hand-written approximation.
Adds the case this card is about: reach the handler through its `functions`
entry -- the only thing `objectstack build` emits and `mergeRuntimeModule`
merges -- with no `onEnable` called anywhere in the file, and assert it still
reads and recomputes. Plus two guards that the seam cannot return: the jobs
module exports no `bindShowcaseJobRuntime`, and no authored source (comments
stripped) carries the binding seam or its "no engine handle bound yet" branch.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
…t comment
`check:cross-package-test-inputs` is a SOURCE SCAN: a path literal anywhere in
a test file is read as one of that test's real inputs, comment or not. Naming
`mergeRuntimeModule`'s file by repo path made the gate demand a turbo `inputs`
declaration for a file this test never reads. Describe the module instead, and
say so in the comment so the next author does not put the path back.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
@os-muskClaude

Copy link
Copy Markdown
CollaboratorAuthor

Landing provenance — engine execution seat (session session_0112hMx9hjJ9BgB28X97DS68).

ACCEPT on the card: comment 5506367294 (#14257). Flip pre-checks on head 7988daded: every one of the 39 check runs completed with conclusion success or skipped (Lint & Repo Gates completed 08:12:56Z; Check Changeset skipped under the live-read skip-changeset label — @objectstack/example-showcase is private); governed-surface test on the PR's 4 paths: NOT governed — ordinary queue landing applies; closing-keyword two-read done at ACCEPT (Fixes #14257, correct). Clause-② self-reading no (example app; no contract member moves), so no contract-review carrier applied.

Action: draft: false then auto-merge (squash) — the merge queue takes it from here.


Generated by Claude Code

@os-musk
os-musk enabled auto-merge September 2, 2026 08:14
@os-musk
os-musk added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 253da34Sep 2, 2026
41 checks passed
@os-musk
os-musk deleted the claude/issue-14257-showcase-job-context branch September 2, 2026 08:50
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

app-showcase's nightly health sweep reaches its engine through a module-scope global, so it silently does nothing on an artifact-served boot

2 participants

@os-musk@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

fix(example-showcase): the nightly health sweep takes its engine off the job handler's argument - #14459

Merged
os-musk merged 4 commits into
mainfrom
claude/issue-14257-showcase-job-context
Sep 2, 2026
Merged

fix(example-showcase): the nightly health sweep takes its engine off the job handler's argument#14459
os-musk merged 4 commits into
mainfrom
claude/issue-14257-showcase-job-context

Conversation

@os-musk

Copy link
Copy Markdown
Collaborator

Fixes#14257

What was wrong

The showcase's nightly showcase_health_sweep handler held its engine in a module-scope let host, filled by an exported bindShowcaseJobRuntime(ctx) that objectstack.config.ts called from onEnable. With host unset the handler logged no engine handle bound yet — skipping this run and returned.

That binding does not exist on the artifact path: objectstack build emits functions into a sibling runtime module exporting only { functions, meta }, the artifact JSON carries no onEnable, and mergeRuntimeModule merges only functions. So on an artifact-served boot the sweep fired on schedule, recomputed nothing, and was reported as a clean run. This is the repo's only shipped defineJob, i.e. what an author copies.

What changed

  • src/automation/jobs/sweep-project-health.ts — the handler destructures { jobId, ql, logger } from its JobHandlerContext argument (A defineJob handler is invoked with { jobId, data, bundle } and no data reach, so the platform's only scheduled-work metadata shape cannot read or write a record #14094, type imported from @objectstack/runtime). Deleted: the module-scope host, the local JobHostContext / JobHostEngine interfaces, bindShowcaseJobRuntime, and the no engine handle bound yet early return. logger is now the platform Logger the context carries, so the optional-call spelling goes with it.
  • src/automation/jobs/index.ts — drops the bindShowcaseJobRuntime re-export.
  • objectstack.config.ts — drops the import and the onEnable call.
  • test/inert-wirings.test.ts — a fake CONTEXT instead of a fake host, plus the artifact-boot case this card is about.

effect: 'writes' on the functions entry is unchanged, per the card's triage. That declaration is about who counts the writes — a job has no downstream declarative node to count them, so undeclared a run reports having written nothing rather than "cannot say", which is indistinguishable from the broken sweep #4354 exists to detect. It never said anything about where the handle came from.

Two comment regions edited beyond the lines the dispatch named

Both are inside the three files already on the surface, but outside the named lines. Declared here because leaving them would have kept the reference app teaching the superseded shape in prose while its code no longer used it.

  1. objectstack.config.ts, the functions map docblock. It read "it writes over an engine handle captured at onEnable" — a sentence this PR makes false about the very entry it sits above. Evidence for the replacement wording: JobHandlerContext's own docblock in @objectstack/runtime, and content/docs/automation/jobs.mdx, which A defineJob handler is invoked with { jobId, data, bundle } and no data reach, so the platform's only scheduled-work metadata shape cannot read or write a record #14094 already updated to teach the argument (that page is correct as it stands and is untouched here).
  2. sweep-project-health.ts, healthFor's docblock. It pointed readers at test/job-health-sweep.test.ts. That file does not exist anywhere in the tree — a repo-wide grep finds this one mention and no file. Repointed at test/inert-wirings.test.ts, where those unit tests actually live.

Tests

test/inert-wirings.test.ts now builds the argument AppPlugin really passes. ql is declared satisfies the contract's own member types rather than a local interface, so a drift in IDataEngine.find / .update reds in this file instead of being absorbed by a hand-written approximation; the cast that follows widens only to the engine members this handler never touches. pnpm check:engine-double-contract is green with no new baseline row.

Three cases added, one of them the card's:

  • artifact-shaped boot — reach the handler through its functions entry, the one thing objectstack build emits and mergeRuntimeModule merges, with onEnable called nowhere in the file, and assert it reads both objects and writes the recomputed health.
  • the jobs module exports no bindShowcaseJobRuntime (the seam is gone from the export surface, not merely unused).
  • no authored source under src/orobjectstack.config.ts carries the seam or its skip branch, judged on comment-stripped text so documentation stays free to explain why it went.

Ablation (direction predicted before the run: RED)

Reverted the handler to a module-scope handle in the worktree, on top of the committed implementation. Mutation proved on disk by anchored counts before measuring — injected no engine handle bound yet 1, injected let host: JobHostContext 1, deleted { jobId, ql, logger }: JobHandlerContext 0, blob hash cd757ba moved to a9f19b9.

Tests 3 failed | 33 passed (36)
× recomputes when `functions` is all that was merged and `onEnable` never ran
AssertionError: expected [] to deeply equal [ 'showcase_project', 'showcase_task' ]
× sweeps only in-play projects and writes only what changed
× no authored source re-introduces the module-scope handle

Restored with git checkout HEAD -- ABSOLUTE_PATH; git diff HEAD empty and the blob hash back to cd757ba, byte-identical.

No dist/ leg applies to this ablation, and that is a measured property rather than an assumption: sweep-project-health.ts has exactly one import and it is import type, so the handler carries no runtime dependency to build, and the test resolves it from source. The source-only mutation flipping the suite red is itself the proof that no build artifact stands between them.

One prediction missed, and it is worth reading. I expected four failures; three came. is a no-op when nothing changed stayed GREEN under the ablation, because it asserts writes is empty and the broken handler writes nothing at all. That assertion passes vacuously against exactly the defect this card is about — the same shape as the production symptom, where a sweep that recomputed nothing was recorded as a clean run.

Gates

Run on final HEAD 7988daded (quoted from that same run), after git merge origin/main and a full install --frozen-lockfile plus turbo run build of the packages closure. Exit codes captured after redirect, never through a pipe.

  • pnpm --filter @objectstack/example-showcase typecheck — green. The app's include covers test/**, measured rather than assumed: before the test was rewritten this same command printed three errors, all of them in test/inert-wirings.test.ts.
  • pnpm --filter @objectstack/example-showcase exec vitest run --maxWorkers=2Test Files 26 passed (26), Tests 367 passed (367).
  • pnpm lint — repo-wide eslint . --no-inline-config, exit 0. Not narrowed.
  • The 22 families node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands derives from this diff: all green, plus the always-runs pnpm check:error-status-conformance.
  • One exception, recorded rather than counted as a pass: node scripts/check-test-completeness.mjs exits 3 with PREREQUISITE NOT MET — this gate grades a saved 'turbo run test' log, and no log was named, and its own text says "the local reading for this gate is NOT MEASURED. It is not a red, and there is nothing here to fix." CI passes it the teed log.

check:cross-package-test-inputs reds an intermediate commit here and the fix is worth knowing: it is a source scan, so a repo path spelled in a test comment is read as one of that test's real inputs. Naming mergeRuntimeModule's file by path made the gate demand a turbo inputs declaration for a file the test never reads.

Changeset

None, and skip-changeset applied. @objectstack/example-showcase is "private": true and publishes nothing; the changeset-check job in pr-automation.yml counts added .changeset/*.md unless that label is live-read on the PR, which is the exemption for a PR that declares no release of its own. Recent showcase-only fixes landed the same way.


🤖 Generated with Claude Code

https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68

Generated by Claude Code


Generated by Claude Code

…ext argument
The nightly `showcase_health_sweep` handler held its engine in a module-scope
`let host` that `onEnable` filled via an exported `bindShowcaseJobRuntime`.
That binding does not exist on the artifact path: `objectstack build` emits
`functions` into a sibling runtime module exporting only `{ functions, meta }`,
the artifact JSON carries no `onEnable`, and `mergeRuntimeModule` merges only
`functions` -- so on an artifact-served boot the handle stayed `undefined` and
the sweep recomputed nothing while reporting a clean run.
Take `jobId` / `ql` / `logger` off the handler's `JobHandlerContext` argument
(#14094) and delete the binding seam entirely: the module-scope `host`, the
`JobHostContext` / `JobHostEngine` local interfaces, `bindShowcaseJobRuntime`,
its re-export and its `onEnable` call. `effect: 'writes'` on the `functions`
entry is unchanged -- that declaration is about who counts the writes, not
about where the handle comes from.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
Swap the handler test's fake HOST for a fake CONTEXT: `jobRun()` builds the
`JobHandlerContext` `AppPlugin` passes, with `ql` declared `satisfies` the
contract's own member types so a drift in `IDataEngine.find`/`.update` reds
here rather than being absorbed by a hand-written approximation.
Adds the case this card is about: reach the handler through its `functions`
entry -- the only thing `objectstack build` emits and `mergeRuntimeModule`
merges -- with no `onEnable` called anywhere in the file, and assert it still
reads and recomputes. Plus two guards that the seam cannot return: the jobs
module exports no `bindShowcaseJobRuntime`, and no authored source (comments
stripped) carries the binding seam or its "no engine handle bound yet" branch.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
…t comment
`check:cross-package-test-inputs` is a SOURCE SCAN: a path literal anywhere in
a test file is read as one of that test's real inputs, comment or not. Naming
`mergeRuntimeModule`'s file by repo path made the gate demand a turbo `inputs`
declaration for a file this test never reads. Describe the module instead, and
say so in the comment so the next author does not put the path back.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
@os-muskClaude

Copy link
Copy Markdown
CollaboratorAuthor

Landing provenance — engine execution seat (session session_0112hMx9hjJ9BgB28X97DS68).

ACCEPT on the card: comment 5506367294 (#14257). Flip pre-checks on head 7988daded: every one of the 39 check runs completed with conclusion success or skipped (Lint & Repo Gates completed 08:12:56Z; Check Changeset skipped under the live-read skip-changeset label — @objectstack/example-showcase is private); governed-surface test on the PR's 4 paths: NOT governed — ordinary queue landing applies; closing-keyword two-read done at ACCEPT (Fixes #14257, correct). Clause-② self-reading no (example app; no contract member moves), so no contract-review carrier applied.

Action: draft: false then auto-merge (squash) — the merge queue takes it from here.


Generated by Claude Code

@os-musk
os-musk enabled auto-merge September 2, 2026 08:14
@os-musk
os-musk added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 253da34Sep 2, 2026
41 checks passed
@os-musk
os-musk deleted the claude/issue-14257-showcase-job-context branch September 2, 2026 08:50
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

app-showcase's nightly health sweep reaches its engine through a module-scope global, so it silently does nothing on an artifact-served boot

2 participants

@os-musk@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(example-showcase): the nightly health sweep takes its engine off the job handler's argument - #14459

Merged
os-musk merged 4 commits into
mainfrom
claude/issue-14257-showcase-job-context
Sep 2, 2026
Merged

fix(example-showcase): the nightly health sweep takes its engine off the job handler's argument#14459
os-musk merged 4 commits into
mainfrom
claude/issue-14257-showcase-job-context

Conversation

@os-musk

Copy link
Copy Markdown
Collaborator

Fixes#14257

What was wrong

The showcase's nightly showcase_health_sweep handler held its engine in a module-scope let host, filled by an exported bindShowcaseJobRuntime(ctx) that objectstack.config.ts called from onEnable. With host unset the handler logged no engine handle bound yet — skipping this run and returned.

That binding does not exist on the artifact path: objectstack build emits functions into a sibling runtime module exporting only { functions, meta }, the artifact JSON carries no onEnable, and mergeRuntimeModule merges only functions. So on an artifact-served boot the sweep fired on schedule, recomputed nothing, and was reported as a clean run. This is the repo's only shipped defineJob, i.e. what an author copies.

What changed

  • src/automation/jobs/sweep-project-health.ts — the handler destructures { jobId, ql, logger } from its JobHandlerContext argument (A defineJob handler is invoked with { jobId, data, bundle } and no data reach, so the platform's only scheduled-work metadata shape cannot read or write a record #14094, type imported from @objectstack/runtime). Deleted: the module-scope host, the local JobHostContext / JobHostEngine interfaces, bindShowcaseJobRuntime, and the no engine handle bound yet early return. logger is now the platform Logger the context carries, so the optional-call spelling goes with it.
  • src/automation/jobs/index.ts — drops the bindShowcaseJobRuntime re-export.
  • objectstack.config.ts — drops the import and the onEnable call.
  • test/inert-wirings.test.ts — a fake CONTEXT instead of a fake host, plus the artifact-boot case this card is about.

effect: 'writes' on the functions entry is unchanged, per the card's triage. That declaration is about who counts the writes — a job has no downstream declarative node to count them, so undeclared a run reports having written nothing rather than "cannot say", which is indistinguishable from the broken sweep #4354 exists to detect. It never said anything about where the handle came from.

Two comment regions edited beyond the lines the dispatch named

Both are inside the three files already on the surface, but outside the named lines. Declared here because leaving them would have kept the reference app teaching the superseded shape in prose while its code no longer used it.

  1. objectstack.config.ts, the functions map docblock. It read "it writes over an engine handle captured at onEnable" — a sentence this PR makes false about the very entry it sits above. Evidence for the replacement wording: JobHandlerContext's own docblock in @objectstack/runtime, and content/docs/automation/jobs.mdx, which A defineJob handler is invoked with { jobId, data, bundle } and no data reach, so the platform's only scheduled-work metadata shape cannot read or write a record #14094 already updated to teach the argument (that page is correct as it stands and is untouched here).
  2. sweep-project-health.ts, healthFor's docblock. It pointed readers at test/job-health-sweep.test.ts. That file does not exist anywhere in the tree — a repo-wide grep finds this one mention and no file. Repointed at test/inert-wirings.test.ts, where those unit tests actually live.

Tests

test/inert-wirings.test.ts now builds the argument AppPlugin really passes. ql is declared satisfies the contract's own member types rather than a local interface, so a drift in IDataEngine.find / .update reds in this file instead of being absorbed by a hand-written approximation; the cast that follows widens only to the engine members this handler never touches. pnpm check:engine-double-contract is green with no new baseline row.

Three cases added, one of them the card's:

  • artifact-shaped boot — reach the handler through its functions entry, the one thing objectstack build emits and mergeRuntimeModule merges, with onEnable called nowhere in the file, and assert it reads both objects and writes the recomputed health.
  • the jobs module exports no bindShowcaseJobRuntime (the seam is gone from the export surface, not merely unused).
  • no authored source under src/orobjectstack.config.ts carries the seam or its skip branch, judged on comment-stripped text so documentation stays free to explain why it went.

Ablation (direction predicted before the run: RED)

Reverted the handler to a module-scope handle in the worktree, on top of the committed implementation. Mutation proved on disk by anchored counts before measuring — injected no engine handle bound yet 1, injected let host: JobHostContext 1, deleted { jobId, ql, logger }: JobHandlerContext 0, blob hash cd757ba moved to a9f19b9.

Tests 3 failed | 33 passed (36)
× recomputes when `functions` is all that was merged and `onEnable` never ran
AssertionError: expected [] to deeply equal [ 'showcase_project', 'showcase_task' ]
× sweeps only in-play projects and writes only what changed
× no authored source re-introduces the module-scope handle

Restored with git checkout HEAD -- ABSOLUTE_PATH; git diff HEAD empty and the blob hash back to cd757ba, byte-identical.

No dist/ leg applies to this ablation, and that is a measured property rather than an assumption: sweep-project-health.ts has exactly one import and it is import type, so the handler carries no runtime dependency to build, and the test resolves it from source. The source-only mutation flipping the suite red is itself the proof that no build artifact stands between them.

One prediction missed, and it is worth reading. I expected four failures; three came. is a no-op when nothing changed stayed GREEN under the ablation, because it asserts writes is empty and the broken handler writes nothing at all. That assertion passes vacuously against exactly the defect this card is about — the same shape as the production symptom, where a sweep that recomputed nothing was recorded as a clean run.

Gates

Run on final HEAD 7988daded (quoted from that same run), after git merge origin/main and a full install --frozen-lockfile plus turbo run build of the packages closure. Exit codes captured after redirect, never through a pipe.

  • pnpm --filter @objectstack/example-showcase typecheck — green. The app's include covers test/**, measured rather than assumed: before the test was rewritten this same command printed three errors, all of them in test/inert-wirings.test.ts.
  • pnpm --filter @objectstack/example-showcase exec vitest run --maxWorkers=2Test Files 26 passed (26), Tests 367 passed (367).
  • pnpm lint — repo-wide eslint . --no-inline-config, exit 0. Not narrowed.
  • The 22 families node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands derives from this diff: all green, plus the always-runs pnpm check:error-status-conformance.
  • One exception, recorded rather than counted as a pass: node scripts/check-test-completeness.mjs exits 3 with PREREQUISITE NOT MET — this gate grades a saved 'turbo run test' log, and no log was named, and its own text says "the local reading for this gate is NOT MEASURED. It is not a red, and there is nothing here to fix." CI passes it the teed log.

check:cross-package-test-inputs reds an intermediate commit here and the fix is worth knowing: it is a source scan, so a repo path spelled in a test comment is read as one of that test's real inputs. Naming mergeRuntimeModule's file by path made the gate demand a turbo inputs declaration for a file the test never reads.

Changeset

None, and skip-changeset applied. @objectstack/example-showcase is "private": true and publishes nothing; the changeset-check job in pr-automation.yml counts added .changeset/*.md unless that label is live-read on the PR, which is the exemption for a PR that declares no release of its own. Recent showcase-only fixes landed the same way.


🤖 Generated with Claude Code

https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68

Generated by Claude Code


Generated by Claude Code

…ext argument
The nightly `showcase_health_sweep` handler held its engine in a module-scope
`let host` that `onEnable` filled via an exported `bindShowcaseJobRuntime`.
That binding does not exist on the artifact path: `objectstack build` emits
`functions` into a sibling runtime module exporting only `{ functions, meta }`,
the artifact JSON carries no `onEnable`, and `mergeRuntimeModule` merges only
`functions` -- so on an artifact-served boot the handle stayed `undefined` and
the sweep recomputed nothing while reporting a clean run.
Take `jobId` / `ql` / `logger` off the handler's `JobHandlerContext` argument
(#14094) and delete the binding seam entirely: the module-scope `host`, the
`JobHostContext` / `JobHostEngine` local interfaces, `bindShowcaseJobRuntime`,
its re-export and its `onEnable` call. `effect: 'writes'` on the `functions`
entry is unchanged -- that declaration is about who counts the writes, not
about where the handle comes from.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
Swap the handler test's fake HOST for a fake CONTEXT: `jobRun()` builds the
`JobHandlerContext` `AppPlugin` passes, with `ql` declared `satisfies` the
contract's own member types so a drift in `IDataEngine.find`/`.update` reds
here rather than being absorbed by a hand-written approximation.
Adds the case this card is about: reach the handler through its `functions`
entry -- the only thing `objectstack build` emits and `mergeRuntimeModule`
merges -- with no `onEnable` called anywhere in the file, and assert it still
reads and recomputes. Plus two guards that the seam cannot return: the jobs
module exports no `bindShowcaseJobRuntime`, and no authored source (comments
stripped) carries the binding seam or its "no engine handle bound yet" branch.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
…t comment
`check:cross-package-test-inputs` is a SOURCE SCAN: a path literal anywhere in
a test file is read as one of that test's real inputs, comment or not. Naming
`mergeRuntimeModule`'s file by repo path made the gate demand a turbo `inputs`
declaration for a file this test never reads. Describe the module instead, and
say so in the comment so the next author does not put the path back.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
@os-muskClaude

Copy link
Copy Markdown
CollaboratorAuthor

Landing provenance — engine execution seat (session session_0112hMx9hjJ9BgB28X97DS68).

ACCEPT on the card: comment 5506367294 (#14257). Flip pre-checks on head 7988daded: every one of the 39 check runs completed with conclusion success or skipped (Lint & Repo Gates completed 08:12:56Z; Check Changeset skipped under the live-read skip-changeset label — @objectstack/example-showcase is private); governed-surface test on the PR's 4 paths: NOT governed — ordinary queue landing applies; closing-keyword two-read done at ACCEPT (Fixes #14257, correct). Clause-② self-reading no (example app; no contract member moves), so no contract-review carrier applied.

Action: draft: false then auto-merge (squash) — the merge queue takes it from here.


Generated by Claude Code

@os-musk
os-musk enabled auto-merge September 2, 2026 08:14
@os-musk
os-musk added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 253da34Sep 2, 2026
41 checks passed
@os-musk
os-musk deleted the claude/issue-14257-showcase-job-context branch September 2, 2026 08:50
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

app-showcase's nightly health sweep reaches its engine through a module-scope global, so it silently does nothing on an artifact-served boot

2 participants

@os-musk@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(example-showcase): the nightly health sweep takes its engine off the job handler's argument - #14459

Merged
os-musk merged 4 commits into
mainfrom
claude/issue-14257-showcase-job-context
Sep 2, 2026
Merged

fix(example-showcase): the nightly health sweep takes its engine off the job handler's argument#14459
os-musk merged 4 commits into
mainfrom
claude/issue-14257-showcase-job-context

Conversation

@os-musk

Copy link
Copy Markdown
Collaborator

Fixes#14257

What was wrong

The showcase's nightly showcase_health_sweep handler held its engine in a module-scope let host, filled by an exported bindShowcaseJobRuntime(ctx) that objectstack.config.ts called from onEnable. With host unset the handler logged no engine handle bound yet — skipping this run and returned.

That binding does not exist on the artifact path: objectstack build emits functions into a sibling runtime module exporting only { functions, meta }, the artifact JSON carries no onEnable, and mergeRuntimeModule merges only functions. So on an artifact-served boot the sweep fired on schedule, recomputed nothing, and was reported as a clean run. This is the repo's only shipped defineJob, i.e. what an author copies.

What changed

  • src/automation/jobs/sweep-project-health.ts — the handler destructures { jobId, ql, logger } from its JobHandlerContext argument (A defineJob handler is invoked with { jobId, data, bundle } and no data reach, so the platform's only scheduled-work metadata shape cannot read or write a record #14094, type imported from @objectstack/runtime). Deleted: the module-scope host, the local JobHostContext / JobHostEngine interfaces, bindShowcaseJobRuntime, and the no engine handle bound yet early return. logger is now the platform Logger the context carries, so the optional-call spelling goes with it.
  • src/automation/jobs/index.ts — drops the bindShowcaseJobRuntime re-export.
  • objectstack.config.ts — drops the import and the onEnable call.
  • test/inert-wirings.test.ts — a fake CONTEXT instead of a fake host, plus the artifact-boot case this card is about.

effect: 'writes' on the functions entry is unchanged, per the card's triage. That declaration is about who counts the writes — a job has no downstream declarative node to count them, so undeclared a run reports having written nothing rather than "cannot say", which is indistinguishable from the broken sweep #4354 exists to detect. It never said anything about where the handle came from.

Two comment regions edited beyond the lines the dispatch named

Both are inside the three files already on the surface, but outside the named lines. Declared here because leaving them would have kept the reference app teaching the superseded shape in prose while its code no longer used it.

  1. objectstack.config.ts, the functions map docblock. It read "it writes over an engine handle captured at onEnable" — a sentence this PR makes false about the very entry it sits above. Evidence for the replacement wording: JobHandlerContext's own docblock in @objectstack/runtime, and content/docs/automation/jobs.mdx, which A defineJob handler is invoked with { jobId, data, bundle } and no data reach, so the platform's only scheduled-work metadata shape cannot read or write a record #14094 already updated to teach the argument (that page is correct as it stands and is untouched here).
  2. sweep-project-health.ts, healthFor's docblock. It pointed readers at test/job-health-sweep.test.ts. That file does not exist anywhere in the tree — a repo-wide grep finds this one mention and no file. Repointed at test/inert-wirings.test.ts, where those unit tests actually live.

Tests

test/inert-wirings.test.ts now builds the argument AppPlugin really passes. ql is declared satisfies the contract's own member types rather than a local interface, so a drift in IDataEngine.find / .update reds in this file instead of being absorbed by a hand-written approximation; the cast that follows widens only to the engine members this handler never touches. pnpm check:engine-double-contract is green with no new baseline row.

Three cases added, one of them the card's:

  • artifact-shaped boot — reach the handler through its functions entry, the one thing objectstack build emits and mergeRuntimeModule merges, with onEnable called nowhere in the file, and assert it reads both objects and writes the recomputed health.
  • the jobs module exports no bindShowcaseJobRuntime (the seam is gone from the export surface, not merely unused).
  • no authored source under src/orobjectstack.config.ts carries the seam or its skip branch, judged on comment-stripped text so documentation stays free to explain why it went.

Ablation (direction predicted before the run: RED)

Reverted the handler to a module-scope handle in the worktree, on top of the committed implementation. Mutation proved on disk by anchored counts before measuring — injected no engine handle bound yet 1, injected let host: JobHostContext 1, deleted { jobId, ql, logger }: JobHandlerContext 0, blob hash cd757ba moved to a9f19b9.

Tests 3 failed | 33 passed (36)
× recomputes when `functions` is all that was merged and `onEnable` never ran
AssertionError: expected [] to deeply equal [ 'showcase_project', 'showcase_task' ]
× sweeps only in-play projects and writes only what changed
× no authored source re-introduces the module-scope handle

Restored with git checkout HEAD -- ABSOLUTE_PATH; git diff HEAD empty and the blob hash back to cd757ba, byte-identical.

No dist/ leg applies to this ablation, and that is a measured property rather than an assumption: sweep-project-health.ts has exactly one import and it is import type, so the handler carries no runtime dependency to build, and the test resolves it from source. The source-only mutation flipping the suite red is itself the proof that no build artifact stands between them.

One prediction missed, and it is worth reading. I expected four failures; three came. is a no-op when nothing changed stayed GREEN under the ablation, because it asserts writes is empty and the broken handler writes nothing at all. That assertion passes vacuously against exactly the defect this card is about — the same shape as the production symptom, where a sweep that recomputed nothing was recorded as a clean run.

Gates

Run on final HEAD 7988daded (quoted from that same run), after git merge origin/main and a full install --frozen-lockfile plus turbo run build of the packages closure. Exit codes captured after redirect, never through a pipe.

  • pnpm --filter @objectstack/example-showcase typecheck — green. The app's include covers test/**, measured rather than assumed: before the test was rewritten this same command printed three errors, all of them in test/inert-wirings.test.ts.
  • pnpm --filter @objectstack/example-showcase exec vitest run --maxWorkers=2Test Files 26 passed (26), Tests 367 passed (367).
  • pnpm lint — repo-wide eslint . --no-inline-config, exit 0. Not narrowed.
  • The 22 families node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands derives from this diff: all green, plus the always-runs pnpm check:error-status-conformance.
  • One exception, recorded rather than counted as a pass: node scripts/check-test-completeness.mjs exits 3 with PREREQUISITE NOT MET — this gate grades a saved 'turbo run test' log, and no log was named, and its own text says "the local reading for this gate is NOT MEASURED. It is not a red, and there is nothing here to fix." CI passes it the teed log.

check:cross-package-test-inputs reds an intermediate commit here and the fix is worth knowing: it is a source scan, so a repo path spelled in a test comment is read as one of that test's real inputs. Naming mergeRuntimeModule's file by path made the gate demand a turbo inputs declaration for a file the test never reads.

Changeset

None, and skip-changeset applied. @objectstack/example-showcase is "private": true and publishes nothing; the changeset-check job in pr-automation.yml counts added .changeset/*.md unless that label is live-read on the PR, which is the exemption for a PR that declares no release of its own. Recent showcase-only fixes landed the same way.


🤖 Generated with Claude Code

https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68

Generated by Claude Code


Generated by Claude Code

…ext argument
The nightly `showcase_health_sweep` handler held its engine in a module-scope
`let host` that `onEnable` filled via an exported `bindShowcaseJobRuntime`.
That binding does not exist on the artifact path: `objectstack build` emits
`functions` into a sibling runtime module exporting only `{ functions, meta }`,
the artifact JSON carries no `onEnable`, and `mergeRuntimeModule` merges only
`functions` -- so on an artifact-served boot the handle stayed `undefined` and
the sweep recomputed nothing while reporting a clean run.
Take `jobId` / `ql` / `logger` off the handler's `JobHandlerContext` argument
(#14094) and delete the binding seam entirely: the module-scope `host`, the
`JobHostContext` / `JobHostEngine` local interfaces, `bindShowcaseJobRuntime`,
its re-export and its `onEnable` call. `effect: 'writes'` on the `functions`
entry is unchanged -- that declaration is about who counts the writes, not
about where the handle comes from.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
Swap the handler test's fake HOST for a fake CONTEXT: `jobRun()` builds the
`JobHandlerContext` `AppPlugin` passes, with `ql` declared `satisfies` the
contract's own member types so a drift in `IDataEngine.find`/`.update` reds
here rather than being absorbed by a hand-written approximation.
Adds the case this card is about: reach the handler through its `functions`
entry -- the only thing `objectstack build` emits and `mergeRuntimeModule`
merges -- with no `onEnable` called anywhere in the file, and assert it still
reads and recomputes. Plus two guards that the seam cannot return: the jobs
module exports no `bindShowcaseJobRuntime`, and no authored source (comments
stripped) carries the binding seam or its "no engine handle bound yet" branch.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
…t comment
`check:cross-package-test-inputs` is a SOURCE SCAN: a path literal anywhere in
a test file is read as one of that test's real inputs, comment or not. Naming
`mergeRuntimeModule`'s file by repo path made the gate demand a turbo `inputs`
declaration for a file this test never reads. Describe the module instead, and
say so in the comment so the next author does not put the path back.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
@os-muskClaude

Copy link
Copy Markdown
CollaboratorAuthor

Landing provenance — engine execution seat (session session_0112hMx9hjJ9BgB28X97DS68).

ACCEPT on the card: comment 5506367294 (#14257). Flip pre-checks on head 7988daded: every one of the 39 check runs completed with conclusion success or skipped (Lint & Repo Gates completed 08:12:56Z; Check Changeset skipped under the live-read skip-changeset label — @objectstack/example-showcase is private); governed-surface test on the PR's 4 paths: NOT governed — ordinary queue landing applies; closing-keyword two-read done at ACCEPT (Fixes #14257, correct). Clause-② self-reading no (example app; no contract member moves), so no contract-review carrier applied.

Action: draft: false then auto-merge (squash) — the merge queue takes it from here.


Generated by Claude Code

@os-musk
os-musk enabled auto-merge September 2, 2026 08:14
@os-musk
os-musk added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 253da34Sep 2, 2026
41 checks passed
@os-musk
os-musk deleted the claude/issue-14257-showcase-job-context branch September 2, 2026 08:50
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

app-showcase's nightly health sweep reaches its engine through a module-scope global, so it silently does nothing on an artifact-served boot

2 participants

@os-musk@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

fix(example-showcase): the nightly health sweep takes its engine off the job handler's argument - #14459

Merged
os-musk merged 4 commits into
mainfrom
claude/issue-14257-showcase-job-context
Sep 2, 2026
Merged

fix(example-showcase): the nightly health sweep takes its engine off the job handler's argument#14459
os-musk merged 4 commits into
mainfrom
claude/issue-14257-showcase-job-context

Conversation

@os-musk

Copy link
Copy Markdown
Collaborator

Fixes#14257

What was wrong

The showcase's nightly showcase_health_sweep handler held its engine in a module-scope let host, filled by an exported bindShowcaseJobRuntime(ctx) that objectstack.config.ts called from onEnable. With host unset the handler logged no engine handle bound yet — skipping this run and returned.

That binding does not exist on the artifact path: objectstack build emits functions into a sibling runtime module exporting only { functions, meta }, the artifact JSON carries no onEnable, and mergeRuntimeModule merges only functions. So on an artifact-served boot the sweep fired on schedule, recomputed nothing, and was reported as a clean run. This is the repo's only shipped defineJob, i.e. what an author copies.

What changed

  • src/automation/jobs/sweep-project-health.ts — the handler destructures { jobId, ql, logger } from its JobHandlerContext argument (A defineJob handler is invoked with { jobId, data, bundle } and no data reach, so the platform's only scheduled-work metadata shape cannot read or write a record #14094, type imported from @objectstack/runtime). Deleted: the module-scope host, the local JobHostContext / JobHostEngine interfaces, bindShowcaseJobRuntime, and the no engine handle bound yet early return. logger is now the platform Logger the context carries, so the optional-call spelling goes with it.
  • src/automation/jobs/index.ts — drops the bindShowcaseJobRuntime re-export.
  • objectstack.config.ts — drops the import and the onEnable call.
  • test/inert-wirings.test.ts — a fake CONTEXT instead of a fake host, plus the artifact-boot case this card is about.

effect: 'writes' on the functions entry is unchanged, per the card's triage. That declaration is about who counts the writes — a job has no downstream declarative node to count them, so undeclared a run reports having written nothing rather than "cannot say", which is indistinguishable from the broken sweep #4354 exists to detect. It never said anything about where the handle came from.

Two comment regions edited beyond the lines the dispatch named

Both are inside the three files already on the surface, but outside the named lines. Declared here because leaving them would have kept the reference app teaching the superseded shape in prose while its code no longer used it.

  1. objectstack.config.ts, the functions map docblock. It read "it writes over an engine handle captured at onEnable" — a sentence this PR makes false about the very entry it sits above. Evidence for the replacement wording: JobHandlerContext's own docblock in @objectstack/runtime, and content/docs/automation/jobs.mdx, which A defineJob handler is invoked with { jobId, data, bundle } and no data reach, so the platform's only scheduled-work metadata shape cannot read or write a record #14094 already updated to teach the argument (that page is correct as it stands and is untouched here).
  2. sweep-project-health.ts, healthFor's docblock. It pointed readers at test/job-health-sweep.test.ts. That file does not exist anywhere in the tree — a repo-wide grep finds this one mention and no file. Repointed at test/inert-wirings.test.ts, where those unit tests actually live.

Tests

test/inert-wirings.test.ts now builds the argument AppPlugin really passes. ql is declared satisfies the contract's own member types rather than a local interface, so a drift in IDataEngine.find / .update reds in this file instead of being absorbed by a hand-written approximation; the cast that follows widens only to the engine members this handler never touches. pnpm check:engine-double-contract is green with no new baseline row.

Three cases added, one of them the card's:

  • artifact-shaped boot — reach the handler through its functions entry, the one thing objectstack build emits and mergeRuntimeModule merges, with onEnable called nowhere in the file, and assert it reads both objects and writes the recomputed health.
  • the jobs module exports no bindShowcaseJobRuntime (the seam is gone from the export surface, not merely unused).
  • no authored source under src/orobjectstack.config.ts carries the seam or its skip branch, judged on comment-stripped text so documentation stays free to explain why it went.

Ablation (direction predicted before the run: RED)

Reverted the handler to a module-scope handle in the worktree, on top of the committed implementation. Mutation proved on disk by anchored counts before measuring — injected no engine handle bound yet 1, injected let host: JobHostContext 1, deleted { jobId, ql, logger }: JobHandlerContext 0, blob hash cd757ba moved to a9f19b9.

Tests 3 failed | 33 passed (36)
× recomputes when `functions` is all that was merged and `onEnable` never ran
AssertionError: expected [] to deeply equal [ 'showcase_project', 'showcase_task' ]
× sweeps only in-play projects and writes only what changed
× no authored source re-introduces the module-scope handle

Restored with git checkout HEAD -- ABSOLUTE_PATH; git diff HEAD empty and the blob hash back to cd757ba, byte-identical.

No dist/ leg applies to this ablation, and that is a measured property rather than an assumption: sweep-project-health.ts has exactly one import and it is import type, so the handler carries no runtime dependency to build, and the test resolves it from source. The source-only mutation flipping the suite red is itself the proof that no build artifact stands between them.

One prediction missed, and it is worth reading. I expected four failures; three came. is a no-op when nothing changed stayed GREEN under the ablation, because it asserts writes is empty and the broken handler writes nothing at all. That assertion passes vacuously against exactly the defect this card is about — the same shape as the production symptom, where a sweep that recomputed nothing was recorded as a clean run.

Gates

Run on final HEAD 7988daded (quoted from that same run), after git merge origin/main and a full install --frozen-lockfile plus turbo run build of the packages closure. Exit codes captured after redirect, never through a pipe.

  • pnpm --filter @objectstack/example-showcase typecheck — green. The app's include covers test/**, measured rather than assumed: before the test was rewritten this same command printed three errors, all of them in test/inert-wirings.test.ts.
  • pnpm --filter @objectstack/example-showcase exec vitest run --maxWorkers=2Test Files 26 passed (26), Tests 367 passed (367).
  • pnpm lint — repo-wide eslint . --no-inline-config, exit 0. Not narrowed.
  • The 22 families node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands derives from this diff: all green, plus the always-runs pnpm check:error-status-conformance.
  • One exception, recorded rather than counted as a pass: node scripts/check-test-completeness.mjs exits 3 with PREREQUISITE NOT MET — this gate grades a saved 'turbo run test' log, and no log was named, and its own text says "the local reading for this gate is NOT MEASURED. It is not a red, and there is nothing here to fix." CI passes it the teed log.

check:cross-package-test-inputs reds an intermediate commit here and the fix is worth knowing: it is a source scan, so a repo path spelled in a test comment is read as one of that test's real inputs. Naming mergeRuntimeModule's file by path made the gate demand a turbo inputs declaration for a file the test never reads.

Changeset

None, and skip-changeset applied. @objectstack/example-showcase is "private": true and publishes nothing; the changeset-check job in pr-automation.yml counts added .changeset/*.md unless that label is live-read on the PR, which is the exemption for a PR that declares no release of its own. Recent showcase-only fixes landed the same way.


🤖 Generated with Claude Code

https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68

Generated by Claude Code


Generated by Claude Code

…ext argument
The nightly `showcase_health_sweep` handler held its engine in a module-scope
`let host` that `onEnable` filled via an exported `bindShowcaseJobRuntime`.
That binding does not exist on the artifact path: `objectstack build` emits
`functions` into a sibling runtime module exporting only `{ functions, meta }`,
the artifact JSON carries no `onEnable`, and `mergeRuntimeModule` merges only
`functions` -- so on an artifact-served boot the handle stayed `undefined` and
the sweep recomputed nothing while reporting a clean run.
Take `jobId` / `ql` / `logger` off the handler's `JobHandlerContext` argument
(#14094) and delete the binding seam entirely: the module-scope `host`, the
`JobHostContext` / `JobHostEngine` local interfaces, `bindShowcaseJobRuntime`,
its re-export and its `onEnable` call. `effect: 'writes'` on the `functions`
entry is unchanged -- that declaration is about who counts the writes, not
about where the handle comes from.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
Swap the handler test's fake HOST for a fake CONTEXT: `jobRun()` builds the
`JobHandlerContext` `AppPlugin` passes, with `ql` declared `satisfies` the
contract's own member types so a drift in `IDataEngine.find`/`.update` reds
here rather than being absorbed by a hand-written approximation.
Adds the case this card is about: reach the handler through its `functions`
entry -- the only thing `objectstack build` emits and `mergeRuntimeModule`
merges -- with no `onEnable` called anywhere in the file, and assert it still
reads and recomputes. Plus two guards that the seam cannot return: the jobs
module exports no `bindShowcaseJobRuntime`, and no authored source (comments
stripped) carries the binding seam or its "no engine handle bound yet" branch.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
…t comment
`check:cross-package-test-inputs` is a SOURCE SCAN: a path literal anywhere in
a test file is read as one of that test's real inputs, comment or not. Naming
`mergeRuntimeModule`'s file by repo path made the gate demand a turbo `inputs`
declaration for a file this test never reads. Describe the module instead, and
say so in the comment so the next author does not put the path back.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
@os-muskClaude

Copy link
Copy Markdown
CollaboratorAuthor

Landing provenance — engine execution seat (session session_0112hMx9hjJ9BgB28X97DS68).

ACCEPT on the card: comment 5506367294 (#14257). Flip pre-checks on head 7988daded: every one of the 39 check runs completed with conclusion success or skipped (Lint & Repo Gates completed 08:12:56Z; Check Changeset skipped under the live-read skip-changeset label — @objectstack/example-showcase is private); governed-surface test on the PR's 4 paths: NOT governed — ordinary queue landing applies; closing-keyword two-read done at ACCEPT (Fixes #14257, correct). Clause-② self-reading no (example app; no contract member moves), so no contract-review carrier applied.

Action: draft: false then auto-merge (squash) — the merge queue takes it from here.


Generated by Claude Code

@os-musk
os-musk enabled auto-merge September 2, 2026 08:14
@os-musk
os-musk added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 253da34Sep 2, 2026
41 checks passed
@os-musk
os-musk deleted the claude/issue-14257-showcase-job-context branch September 2, 2026 08:50
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

app-showcase's nightly health sweep reaches its engine through a module-scope global, so it silently does nothing on an artifact-served boot

2 participants

@os-musk@claude