Switch the production worker route and all hardcoded URLs from
ohmyopenagent.com to omo.dev. Six legacy domains (ohmyopenagent.com,
ohmyopencode.org, ulw.dev, ultrawork.ai, ultrawork.dev,
ultrawork.engineer) are configured to permanently (301) redirect to
omo.dev via Cloudflare Page Rules set up out-of-band via flarectl
and the CF API.
- wrangler.toml: bind worker to omo.dev + www.omo.dev only
- middleware.ts: primaryHost to omo.dev, www to apex redirect retained
- layout.tsx: primarySiteUrl + gaTrackedDomain to omo.dev (GA still G-S0QJFKT46Q)
- sitemap.ts, robots.ts: BASE_URL to https://omo.dev
- npm-downloads/route.ts: usage comment URL refreshed
- web-deploy.yml: environment URL to https://omo.dev
- manifesto.md: domain reality-check line lists omo.dev as canonical
- README*.md (5 langs): npm-downloads badge endpoint to omo.dev
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 publish-main job runs npm publish which triggers prepublishOnly →
build:lsp-tools-mcp. That script needs packages/lsp-tools-mcp/ populated,
but actions/checkout@v4 doesn't init submodules by default.
Without this, publish-main failed with 'npm error code 1' on an empty
packages/lsp-tools-mcp/ directory, blocking v4.2.0 release.
Aligns with ci.yml which already uses submodules: recursive everywhere.
The dist-bundle regression tests in
src/shared/dist-bundle-bun-globals.test.ts are guarded by
`test.skipIf(!existsSync("dist/index.js"))` and dist/ is
gitignored, so they silently skipped in CI which ran tests before
the build step. Adding the build step earlier ensures the
regression guard runs and a future raw `Bun.*` leak in the bundle
fails CI.
The first build of #3860 failed at type-check because the generated
`lib/docs-content.generated.ts` is gitignored (regenerated on every
build) and CI's `type-check` step runs before `build`. Two fixes:
- web-ci.yml: explicit `Generate docs content from repo-root docs/`
step right after `bun install` so format-check, lint, and type-check
all see the file.
- web/package.json: add `prepare` lifecycle script. `bun install`
invokes it automatically, so a fresh local checkout boots into a
working state too.
Build still re-runs the generator via prebuild, so docs/ edits land in
the bundle without an explicit dev action.
Now that docs/ is the single source of truth that the marketing site
renders at build time, edits to those files must run web CI and trigger
the Cloudflare deploy. Add `docs/**` to the paths filter in both
web-ci.yml and web-deploy.yml.
A markdown-only fix in docs/ is now sufficient to redeploy
oh-my-openagent.com — no companion web/ change needed.
PRs land on `dev` (master is blocked by `block-master-pr`), but the
deploy workflow only listened to `master` pushes — so #3853's web/
dependency bumps merged to dev with no Cloudflare deployment ever
running.
Add `dev` to the push branches list. The existing `paths` filter
keeps the deploy from firing on non-web changes, and `workflow_dispatch`
is preserved as the manual fallback.
web-ci.yml — runs on push/PR to master|dev that touches web/**:
- format:check (prettier --check)
- lint (eslint flat config)
- type-check (tsc --noEmit)
- bun run build (next build, sanity)
- bunx opennextjs-cloudflare build (Cloudflare worker bundle)
web-deploy.yml — runs on push to master that touches web/** OR manual
workflow_dispatch (with optional environment input):
- bun install --frozen-lockfile
- bun run prebuild + bunx opennextjs-cloudflare build
- cloudflare/wrangler-action@v3 deploy with CLOUDFLARE_API_TOKEN +
CLOUDFLARE_ACCOUNT_ID secrets, scoped to working-directory: web
Both gated by paths-filter so plugin-only changes do not trigger them.
Concurrency group cancels in-progress CI runs but NOT in-progress deploys.
A web-production GitHub environment is referenced so deploys can be
gated behind required reviewers / wait timers if desired.
Verified locally end-to-end before push:
- bun install: 678 packages
- format:check: pass after `bun run format` reformatted 21 files
- lint: pass
- type-check: pass
- bun run build: pass (4 locales × pages built)
- bunx opennextjs-cloudflare build: pass (.open-next/worker.js generated)
Empirically the npm registry returns HTTP 201 (Created) - not 200 -
when the OIDC token exchange succeeds and a fresh publish token is
issued. The preflight gate was only accepting 200 so every
correctly-configured package was flagged as missing. Accept any
2xx status; only treat 4xx/5xx as missing trust config.
The publish workflow used to bump npm latest+1 *before* attempting
the platform publishes. When a platform package was missing its
trusted-publisher config the version was already incremented but
that platform never shipped, leaving partial-publish garbage
versions on npm (this happened with v3.17.7-v3.17.9 during the
OIDC migration).
Add a preflight-trust job that runs in parallel with test/typecheck
and verifies all 24 packages have a trusted publisher configured by
calling npm's own OIDC token exchange endpoint with the workflow's
GitHub OIDC token. publish-main now needs preflight-trust, so any
missing trust config fails the workflow before the version bump.
Failure output lists the exact npm.com URLs to configure each
missing package, plus the org/repo/workflow values to enter.
After switching to npm Trusted Publishing the publish step still
returned 'PUT 404' because actions/setup-node injects an
'//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}' line into
.npmrc. With NODE_AUTH_TOKEN unset that placeholder evaluates to
an empty string, so npm tries an empty token before reaching for
the OIDC ID token and the registry rejects it.
- Add a step that strips any _authToken line from both project-
local and $HOME/.npmrc before publishing, so npm CLI proceeds
to OIDC token exchange.
- Bump publish commands to --loglevel verbose so future failures
expose the actual auth path (provenance attestation, OIDC
exchange, etc.) in workflow logs.
NODE_AUTH_TOKEN expired (set 90 days ago, the npm token default
expiry) causing all publish runs to fail with 'PUT 404 Not Found'
since 2026-04-30.
Migrate publish.yml and publish-platform.yml to npm Trusted
Publishing (OIDC) so we no longer depend on long-lived secrets:
- Bump actions/setup-node v4 -> v6 (improves OIDC compatibility)
- Add 'npm install -g npm@latest' to guarantee npm CLI >= 11.5.1
(the minimum required for trusted publishing).
- Drop NODE_AUTH_TOKEN env from every publish step. The npm CLI
picks up the GitHub Actions OIDC token automatically.
- Keep --provenance / NPM_CONFIG_PROVENANCE=true (real-world
reports indicate provenance is not auto-emitted yet).
Per-package trusted publisher must still be configured on
npmjs.com (Settings -> Trusted Publisher) for all 24 packages
(oh-my-opencode + oh-my-openagent main + 11 platform packages
each, dual-published) before the next publish run.
Bun-compiled binaries contain a malformed LC_CODE_SIGNATURE load
command that prevents codesign from directly replacing it. Remove
the existing signature first, then apply a fresh ad-hoc signature.
Bun on github macos-latest runners does not emit linker-signed
signatures by default. Sign explicitly with 'codesign --sign -'
without preserve-metadata since the binary has no prior signature.
The previous ad-hoc codesign step failed with 'invalid or unsupported
format for signature' because it tried to preserve the 'linker-signed'
flag which cannot be re-signed. The native macOS build already produces
a valid ad-hoc signature via Bun's linker, so we only need to verify
the signature exists rather than re-sign it.
v3.16.0 binaries had 'adhoc,linker-signed' signatures because newer
Bun versions no longer emit linker-signed signatures when cross-compiling
darwin targets from Linux. Current releases have 'code object is not
signed at all', causing macOS Gatekeeper to reject them immediately.
Verified empirically:
- v3.16.0 darwin-arm64: Signature=adhoc, flags=0x20002(adhoc,linker-signed)
- v3.17.0 darwin-arm64: 'code object is not signed at all'
- Local bun build on macos: produces linker-signed signature (matches v3.16.0)
Changes:
- Route darwin-* platforms to macos-latest runner (native compile)
- Add explicit ad-hoc codesign step as belt-and-suspenders safety net
- Pin bun-version to 1.3.10 across all CI workflows to avoid
mock.module() barrel export regression introduced in 1.3.11
- Remove test:ci script from package.json (use bun test directly)
- Update publish-workflow.test.ts to expect "bun test" instead
🤖 GENERATED WITH ASSISTANCE OF OhMyOpenCode
Three test files were mocking the entire '../../shared' barrel, which
corrupted exports for subsequent test files in the same batch run.
Narrow mocks to specific submodules (logger, connected-providers-cache).
Also reverts Bun version pin since the root cause was mock scope, not Bun.
Bun 1.3.11 has a regression where mock.module() leaks across test files
in isolated batch execution, causing barrel re-exports to fail with
'Export named X not found' errors. Pin to 1.3.10 until upstream fix.
Running Linux CI in one Bun process still leaks mock.module registrations across files, so the workflows now use a CI-specific test runner that isolates mock-heavy targets before executing the remaining suite together.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
- Add afterAll(() => { mock.restore() }) to 52 test files missing cleanup
- Rewrite create-tool-guard-hooks.test.ts to use spyOn instead of barrel mock
- Fix skill-mcp-manager OAuth tests with missing mockTokens/mockLogin definitions
- Fix start-work hook: show worktree active block on resume with existing worktree_path
- Extract createWorktreeActiveBlock to worktree-block.ts to avoid circular import
- Replace 80-line isolated test runner CI config with single `bun test` command
- Add providerModelsCache/fetchAvailableModels mocks to 20 utils.test.ts
tests that broke when createBuiltinAgents started reading the cache
- Isolate ALL src/plugin and src/features/background-agent test files in CI
(mock.module pollution crosses between files in the same bun process)
- Mirror CI isolation changes in publish.yml
25 failures → 0 in CI (all mock-pollution tests run individually)
- completedTaskSummaries now includes status and error info
- notifyParentSession: noReply=false for failed tasks so parent reacts
- Batch notification distinguishes successful vs failed/cancelled tasks
- notification-template updated to show task errors
- task-poller: session-gone tests (85 new lines)
- CI: add Bun shim to PATH for legacy plugin migration tests
Apply the same mock.module() isolation fixes to publish.yml:
- Move shared and session-recovery mock-heavy tests to isolated section
- Use dynamic find + exclusion for remaining src/shared tests
- Include session-recovery tests in remaining batch
Ensures publish workflow has the same test config as main CI run.