CodeNomad/scripts
Pascal André 4ced2d18da
fix(missions): give mission roots OpenCode session identifiers (#1133)
## Problem

Missions on OpenCode Zen's free models (for example
`opencode/deepseek-v4.1-flash-free`) fail at the coordinator's very
first model request with **"Free usage limit reached. Connect a provider
or subscribe to OpenCode Go…"**, while ordinary conversations on the
same model and network keep working.

## Cause

Missions created its coordinators, recurring passage coordinators and
independent task roots with `ses_` + 26 hex characters of a SHA-256.
OpenCode passes that ID to the provider as the session identity
(`x-opencode-session-id`, `x-opencode-session`, `X-Session-Id`,
`x-session-affinity`; `core/src/session/model-request.ts`), and native
children send their **root's** ID as affinity
(`core/src/session/affinity.ts`), so one such root blocks the whole
mission family.

Isolated probes against the real free tier (keyless OpenCode 2.1.4,
OpenCode-generated control IDs accepted throughout) characterized two
checks:

| Check | Requirement | Otherwise |
|---|---|---|
| Shape | `ses_` + 12 lowercase hex + 14 alphanumerics (any case/charset
for the 14) | 403 `FreeTierError` |
| Time | the 12 hex decode, as OpenCode's descending identifier, to a
date between ~86–90 days before and 24–30 h after the request | 429
`FreeUsageLimitError` |

A hash prefix decodes to an arbitrary date over the ~795-day cycle, so
most mission roots failed the time check. A real mission A/B (UI-created
vs. the same mission attached to an OpenCode-created root) reproduced
it: derived coordinator refused, native coordinator completed; a child
with an ordinary ID under a hash-ID parent was refused too.

## Change

- `missions/session-identity.ts`: mission roots take OpenCode's
descending identifier for their **real creation time** followed by 14
hex characters derived from the mission or task identity. Ownership
stays provable from the ID alone.
- Creation: one-time coordinators (`control.ts`), independent task roots
(`control.ts`) and recurring passage coordinators
(`recurrence-store.ts`, passage `createdAt`). The time comes from the
real clock (`options.now ?? Date.now()`), not the journal's monotonic
timestamp, which may run ahead of it.
- Ownership checks match the derived suffix and also accept the original
26-hex derivation held by existing journals: managed-root creation
(`mission-root-creation.ts`, `ensureActorSession`), cleanup targets
(`session-cleanup.ts`), recurring passage parsing/archive/current reads,
and the creation readback (`mission-creation-pipeline.ts`, which no
longer needs the exact coordinator ID in advance; the hold's `sessionID`
is optional).
- `dev-docs/MISSIONS.md` documents the identity rule.

Task roots and recurring coordinators record their ID before creating
the session, so retries still reuse the exact root. A one-time
coordinator takes the clock at creation.

## Compatibility

Existing missions keep their coordinator IDs (and remain refused on free
models); new missions are accepted. Like any OpenCode session, a mission
root older than about three months is refused by the free tier. No UI,
API or journal schema change; no user-facing help change.

## Validation

- `session-identity.test.ts`: time prefix against IDs OpenCode 2.1.4
generated at known milliseconds, descending order, suffix derivation,
legacy acceptance, rejection of other missions/tasks/shapes.
- Server typecheck; all Missions server tests (`src/missions`, mission
routes, plugin, `src/opencode/missions`): 1140 pass, 1 pre-existing
environment skip.
- Native scripts against an isolated OpenCode 2.1.4:
`test-missions-native`, `-trajectory`, `-family-control`, `-contract`
pass.
- Real free tier: a mission created through the real CodeNomad routes
and plugin had its coordinator's first request accepted with the new
identifier. The remaining real checks (native subagent child,
independent task root, recurring coordinator) are pending: the probing
exhausted the network's free allowance (an OpenCode-generated control is
now refused too) and will be rerun after it resets.
2026-10-25 02:10:47 +02:00
..
fixtures chore(opencode): retire adaptations for runtimes and events OpenCode V2 no longer produces (#1034) 2026-10-20 19:19:47 +02:00
missions-child-environment chore(opencode): retire adaptations for runtimes and events OpenCode V2 no longer produces (#1034) 2026-10-20 19:19:47 +02:00
recurring-simple-native feat(missions): coordinator hand-offs, task interrupts and native decision evidence (#1013) 2026-10-19 00:34:27 +02:00
winget build: ship the Linux deb from Electron and the Windows installer without a ZIP (#955) 2026-10-14 16:45:49 +02:00
benchmark-session-history.mjs fix(history): fill search pages and remove redundant counting (#839) 2026-10-03 11:36:04 +02:00
build-help.mjs docs(help): multilingual help site with in-app Help menu and palette entry (#859) 2026-10-14 22:44:56 +02:00
bump-version.js Fix bumpVersion script for both npm and tauri 2026-03-31 20:15:16 +01:00
compare-user-html-rendering.mjs fix(chat): display user HTML as literal source (#777) 2026-09-25 09:52:18 +02:00
desktop-server-resources.cjs feat(tauri): signed cross-platform updates with stable and preview feeds (#786) 2026-10-14 12:18:36 +02:00
desktop-server-resources.test.cjs feat(tauri): signed cross-platform updates with stable and preview feeds (#786) 2026-10-14 12:18:36 +02:00
generate-icons.mjs feat(brand): adopt the hexagon CN logo, black or white by palette (#1114) 2026-10-23 19:18:38 +02:00
native-fixture-diagnostics.mjs fix(ci): stabilize Windows native tests and artifact comments (#828) 2026-10-02 11:24:27 +02:00
native-fixture-diagnostics.test.mjs fix(ci): stabilize Windows native tests and artifact comments (#828) 2026-10-02 11:24:27 +02:00
native-fixture-guards.mjs feat(missions): native project coordination, briefings and tracking (#866) 2026-10-11 14:55:49 +02:00
native-fixture-guards.test.mjs feat(missions): native project coordination, briefings and tracking (#866) 2026-10-11 14:55:49 +02:00
native-product-fixture.mjs feat(plugins): native package check and update (6/8) (#794) 2026-10-15 02:54:19 +02:00
prepare-node-runtime.cjs feat(opencode): enforce stable runtime support and add managed setup 2026-09-20 16:09:36 +02:00
prepare-node-runtime.test.cjs feat(opencode): enforce stable runtime support and add managed setup 2026-09-20 16:09:36 +02:00
preview-git-history.mjs feat(files): unify Workspace, Changes and Commits with central previews (#797) 2026-10-01 11:10:50 +02:00
profile-outline-projection.mjs perf(ui): skip redundant outline and superseded Markdown work (#852) 2026-10-05 22:32:03 +02:00
profile-outline-responsiveness.mts fix: reduce compaction and cross-session responsiveness stalls 2026-10-02 00:40:45 +02:00
profile-streaming-responsiveness.mjs perf(ui): skip redundant outline and superseded Markdown work (#852) 2026-10-05 22:32:03 +02:00
profile-ui-motion.mjs fix(status): keep connected MCP indicators static at rest (#806) 2026-09-30 14:03:19 +02:00
run-session-pruning-native.mjs fix(ci): stabilize Windows native tests and artifact comments (#828) 2026-10-02 11:24:27 +02:00
smoke-packaged-resources.cjs fix(notifications): show Windows system notifications and keep their permission (#1109) 2026-10-23 04:03:26 +02:00
test-attachment-picker-desktop.mjs feat(composer): unify native device attachments and project references (#729) 2026-09-24 23:12:44 +02:00
test-automation-native.mjs chore(opencode): retire adaptations for runtimes and events OpenCode V2 no longer produces (#1034) 2026-10-20 19:19:47 +02:00
test-blank-session-cleanup-native.mjs fix(sessions): preserve populated sessions during automatic cleanup (#755) 2026-09-23 11:53:01 +02:00
test-codemode-jobs-native.mjs fix(opencode): qualify and require 2.1.2 for correct Code Mode execution (#1078) 2026-10-21 14:36:51 +02:00
test-compaction-isolation-native.mjs chore(opencode): retire adaptations for runtimes and events OpenCode V2 no longer produces (#1034) 2026-10-20 19:19:47 +02:00
test-electron-owner-close.mjs fix(electron): avoid destroyed window access on close (#785) 2026-09-28 13:12:07 +02:00
test-git-degraded-native.mjs feat(missions): native project coordination, briefings and tracking (#866) 2026-10-11 14:55:49 +02:00
test-git-init-native.mjs feat(files): initialize Git from the Files panel for plain folders (#933) 2026-10-13 03:11:00 +02:00
test-help-browser.mjs docs(help): multilingual help site with in-app Help menu and palette entry (#859) 2026-10-14 22:44:56 +02:00
test-help.mjs docs(help): list Remote Control before direct access (#990) 2026-10-17 13:27:43 +02:00
test-missions-native-contract.mjs chore(opencode): retire adaptations for runtimes and events OpenCode V2 no longer produces (#1034) 2026-10-20 19:19:47 +02:00
test-missions-native-family-control.mjs feat(missions): native project coordination, briefings and tracking (#866) 2026-10-11 14:55:49 +02:00
test-missions-native-trajectory.mjs feat(missions): add a "Compare two models" Mission template (#1026) 2026-10-20 13:55:12 +02:00
test-missions-native.mjs fix(missions): give mission roots OpenCode session identifiers (#1133) 2026-10-25 02:10:47 +02:00
test-native-event-relay.mjs fix: reduce compaction and cross-session responsiveness stalls 2026-10-02 00:40:45 +02:00
test-native-worktree-management.mjs fix(events): prevent relay timeout on worktree discovery waits (#837) 2026-10-03 04:04:03 +02:00
test-opencode-history-migration.mjs chore(opencode): qualify 2.1.0 and adopt its native contracts (#1029) 2026-10-20 16:46:38 +02:00
test-opencode-install-native.mjs fix(opencode): share host plugin runtime and require 2.0.27 (#920) 2026-10-12 16:42:07 +02:00
test-opencode-legacy-replacement-native.mjs fix(opencode-setup): offer OpenCode 2 when an old or foreign OpenCode blocks setup (#982) 2026-10-16 15:44:17 +02:00
test-opencode-location-native.mjs chore(opencode): retire adaptations for runtimes and events OpenCode V2 no longer produces (#1034) 2026-10-20 19:19:47 +02:00
test-opencode-proxy-native.mjs fix(opencode): qualify 2.0.22 and fence parent session creation (#830) 2026-10-02 15:47:14 +02:00
test-opencode-setup-desktop.mjs fix(opencode): retire private runtime fallback and restore first-run setup (#760) 2026-09-24 00:25:40 +02:00
test-opencode-setup-wsl.mjs chore(opencode): retire adaptations for runtimes and events OpenCode V2 no longer produces (#1034) 2026-10-20 19:19:47 +02:00
test-opencode-upgrade-native.mjs fix(opencode): share host plugin runtime and require 2.0.27 (#920) 2026-10-12 16:42:07 +02:00
test-output-limit-native.mjs chore(opencode): qualify runtime 2.0.29 and align client/plugin pins (#948) 2026-10-14 15:06:35 +02:00
test-panel-extension-native.mjs feat(extensions): add bounded current-session assets for API 2 panels (#874) 2026-10-07 22:54:06 +02:00
test-pending-snapshot-native.mjs fix(pending): stop cold-worktree recovery fallback; qualify OpenCode 2.0.24 (#865) 2026-10-06 23:06:50 +02:00
test-permission-receipts-native.mjs chore(opencode): qualify 2.1.0 and adopt its native contracts (#1029) 2026-10-20 16:46:38 +02:00
test-plugin-packages-native.mjs feat(plugins): native package check and update (6/8) (#794) 2026-10-15 02:54:19 +02:00
test-plugin-runtime-native.mjs fix(opencode): share host plugin runtime and require 2.0.27 (#920) 2026-10-12 16:42:07 +02:00
test-promise-tool-failure-native.mjs chore(opencode): qualify runtime 2.0.29 and align client/plugin pins (#948) 2026-10-14 15:06:35 +02:00
test-prompt-skills-native.mjs feat(composer): native skill attachments (3/8) (#791) 2026-10-02 13:23:42 +02:00
test-provider-account-selection-native.mjs feat(accounts): native account controls and opt-in Codex quota selection (#793) 2026-10-02 17:36:23 +02:00
test-provider-accounts-native.mjs feat(accounts): native account controls and opt-in Codex quota selection (#793) 2026-10-02 17:36:23 +02:00
test-provider-usage-native.mjs fix(usage): use selected native V2 Codex credentials (#811) 2026-09-30 17:29:13 +02:00
test-recurring-simple-native.mjs feat(missions): native project coordination, briefings and tracking (#866) 2026-10-11 14:55:49 +02:00
test-release-workspace-version.mjs chore(release): prepare CodeNomad 1.0.0 versions (#1045) 2026-10-20 20:36:44 +02:00
test-render-cost-audit.mjs fix: reduce compaction and cross-session responsiveness stalls 2026-10-02 00:40:45 +02:00
test-service-usage-native.mjs fix(stats): restore cached totals and refresh only while visible (#1041) 2026-10-20 19:49:45 +02:00
test-session-aside-native.mjs feat(chat): add native /btw side questions 2026-09-21 17:23:11 +02:00
test-session-environment-native.mjs feat(missions): native project coordination, briefings and tracking (#866) 2026-10-11 14:55:49 +02:00
test-session-fork-native.mjs chore(opencode): retire adaptations for runtimes and events OpenCode V2 no longer produces (#1034) 2026-10-20 19:19:47 +02:00
test-session-history-native.mjs feat(extensions): add bounded current-session assets for API 2 panels (#874) 2026-10-07 22:54:06 +02:00
test-session-interrupt-native.mjs fix(sessions): keep Stop and double Escape from restarting the parent (#770) 2026-09-24 21:54:09 +02:00
test-session-lifecycle-native.mjs fix(sessions): wire finish, retry and usage signals to OpenCode V2 events (#1033) 2026-10-20 15:51:48 +02:00
test-session-navigation-native.mjs fix(timeline): mirror every transcript block in order and keep clicks on the clicked marker (#1086) 2026-10-22 05:32:43 +02:00
test-session-pruning-native.mjs test(pruning): align native UI journey with token grouping (#1040) 2026-10-20 19:37:16 +02:00
test-session-pruning-ui.mjs test(pruning): expect response usage to keep tool steps in one group (#1074) 2026-10-21 12:40:03 +02:00
test-subagent-depth-settings-native.mjs feat(missions): native project coordination, briefings and tracking (#866) 2026-10-11 14:55:49 +02:00
test-tauri-f6.ps1 test(tauri): fence F6 fixture profiles and post-input liveness 2026-10-08 00:24:06 +02:00
test-tauri-input-deadlock.mjs fix(tauri): prevent Windows input reentrancy deadlocks (#773) 2026-09-24 21:02:20 +02:00
test-tauri-macos-window-result.test.mjs fix(tauri): prevent macOS startup window event feedback (#821) 2026-10-01 14:58:32 +02:00
test-tauri-macos-window.mjs fix(tauri): prevent macOS startup window event feedback (#821) 2026-10-01 14:58:32 +02:00
test-tauri-runner-refcount.mjs ci: compare repacked deb hardlinks by type and accept callback faults in the Tauri negative control (#1083) 2026-10-21 16:44:23 +02:00
test-tauri-view-menu.mjs feat(timeline): follow Message content tool visibility (#1049) 2026-10-20 23:11:08 +02:00
test-temporary-workspaces-native.mjs feat: temporary instances that are kept or discarded when closed (#899) 2026-10-09 20:59:13 +02:00
test-websearch-settings-native.mjs feat(settings): scoped web search configuration (4/8) (#792) 2026-10-02 14:49:18 +02:00
test-worktree-families-native.mjs chore(opencode): retire adaptations for runtimes and events OpenCode V2 no longer produces (#1034) 2026-10-20 19:19:47 +02:00
verify-bundled-node.cjs build: bundle node runtime for desktop packages 2026-05-04 20:08:04 +01:00