Validator finding #12 from the publish-debate-vortex hyperultradebate flagged that internal-only skill and command assets could leak into the npm payload once the dot asset roots are included.
Bun 1.3.x ignores a root .npmignore for directories listed in package.json#files, so the exclusion rules live in nested .npmignore files co-located with each published command and skill directory.
RED before nested ignores: bun test script/package-layout-exclusion.test.ts failed with expect(received).toEqual(expected), receiving .opencode/skills/__internal-fake-do-not-ship-test-artifact/SKILL.md, .agents/skills/__internal-fake-do-not-ship-test-artifact/SKILL.md, .opencode/command/__internal-fake-do-not-ship-test-artifact.md, and .agents/command/__internal-fake-do-not-ship-test-artifact.md instead of [].
GREEN after nested ignores: bun test script/package-layout-exclusion.test.ts reported 2 pass, 0 fail, 5 expect() calls.
This is the exclusion companion to script/package-layout.test.ts, the inclusion test arriving through the dev merge.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
After the prompts-core migration the TypeScript prompt sources were
deleted; the only mechanism delivering markdown prompts to npm users
is bun build inlining via bunfig.toml [loader] ".md" = "text"
and import attributes. bun test runs from src/index.ts, not from
dist/index.js, so a future Bun upgrade that silently regresses
markdown inlining would pass source tests green while the published
bundle is broken with Cannot find module ../prompts/atlas/default.md
at first agent load.
Add a smoke test that scans the built dist/index.js for unique
signature strings from each migrated prompt file (15 signatures:
3 ultrawork + 5 atlas + 3 prometheus + 4 mode prompts). Skips
gracefully if dist/index.js does not exist (local bun test before
build). Wire into the existing CI Verify dist bundle tests step in
.github/workflows/ci.yml so the regression catches in CI build.
Closes pre-publish blocker V1 and V33.
The double-fire race fix (#4256) had handlePendingVerification return
early when verification_attempt_id was set but verification_session_id
was not, since the oracle dispatch is still in flight. That guard
introduced a permanent-stall failure mode: if tool-execute-after never
runs (oracle session hangs, crashes, OOM-killed, or tmux killed
externally), verification_session_id stays undefined forever and the
ralph-loop never escapes the pending-verification state.
Track verification_attempt_started_at as a state field, clear it on
restart/clear/setVerificationSessionID, and fall through to
handleFailedVerification when the attempt has been pending past
STUCK_VERIFICATION_TIMEOUT_MS (30 minutes). Legacy persisted states
without the timestamp continue to defer (no timeout to evaluate),
matching pre-fix behavior for that edge case.
Closes pre-publish blocker V25.
shouldDeferParentWakeForSessionHistory previously had only one escape
path from the defer state: stale pending tool call. If the assistant
had unfinished text but no pending tool call (session crashed
mid-stream, model errored after partial text, network died), the
escape never fired and parent-wake deferred forever. Background-agent
completions never woke the parent.
Add a second escape: when the assistant text blocks but no tool wait
is pending, dispatch the wake after toolCallDeferMaxMs anyway. The
prompt-async-gate still defends if the assistant text turns out to be
live; we just stop deferring indefinitely.
Closes pre-publish blocker V11.
extractRetryableSignal returns the raw isRetryable hint from up to 5
nested AI SDK error paths. isRetryableError previously trusted any
true result blindly, which would burn every configured fallback model
in an infinite loop if a provider mis-tagged a 401, 403, or other
non-transient 4xx as retryable.
Honor the signal only when the status code is absent, in the configured
retry_on_errors list, in 5xx, or in {408, 425, 429}. Reject the signal
when the status code is a non-transient 4xx and log the rejection so
operators can debug provider mis-classifications.
Closes pre-publish blocker V8.