Skip to content

feat(polli-cli): polli harness codex + claude-code via pinned routers - #15241

Open
afanasevmylife wants to merge 3 commits into
pollinations:mainfrom
afanasevmylife:quest-15218-harness-codex-claude-code
Open

afanasevmylife wants to merge 3 commits into
pollinations:mainfrom
afanasevmylife:quest-15218-harness-codex-claude-code

Conversation

@afanasevmylife

Copy link
Copy Markdown
Contributor

Fixes #15218.

Adds polli harness codex on|off|status and polli harness claude-code on|off|status, driving the two community routers the quest names - Codex Router and Claude Code Router - each pinned to an exact version so the integration cannot drift under us.

Codex (src/harnesses/codex.ts)

  • Installs the router clone into ~/.pollinations/harnesses/codex/codex-router, pinned to commit 5e1b49e (v0.6.0); any other version is refused, not driven.
  • All router mutations go through the router's own documented commands (providers generic add/show/enable/disable/remove, curate-models --models/--remove --apply, credential ... status, doctor). polli never edits router state files.
  • The one exception, deliberate: the dedicated child key is written to the router's documented protected credential file generic-provider-credentials/pollinations.key using the router's own protocol (temp file + rename, 0o600), because the router's credential set reads only from a hidden TTY prompt. The write is verified afterwards with providers generic credential pollinations status; mismatch = stop, no guessing.
  • Dedicated key: reuses the still-valid stored key, otherwise mints polli-harness-codex (child key), like the other adapters.
  • Curated catalog = live first-party tool-calling models (fetchHarnessModels); --model <id> picks the active one.
  • Crash safety: a WAL journal (tx.json) records intent before each mutation; an interrupted on is reconciled on the next run - rollback removes only what the journal proves we created (conditional on the managed-by: polli-cli harness codex description marker). After the commit boundary (key publication) on only continues idempotently.
  • off removes our curated models, the credential file, disables/removes the provider only per first-run facts (a provider that existed before us, or was enabled before us, is left in its previous state), verifies absence, then revokes the child key(s) by name.
  • Foreign provider with the same id (no ownership marker) → refused, nothing touched.

Claude Code (src/harnesses/claude-code.ts)

CCR's only supported way to create providers/profiles is its management UI (config.sqlite is "do not edit live"; the management RPC is undocumented), so this adapter is an honest semi-automatic path:

  • Installs @musistudio/claude-code-router@3.1.1 if missing (any other installed version → refused), requires Claude Code major 2, starts the service.
  • Opens http://127.0.0.1:3458 with exact values: provider pollinationshttps://gen.pollinations.ai/v1 (OpenAI Chat) + a freshly minted child key (printed once, never stored by polli), then an agent profile (provider + model + enabled).
  • Waits read-only on config.sqlite (SELECT value_json FROM app_config WHERE key='default', SQLite opened readOnly: true, never written) until the new entries verify. Ownership is proven against a pre-state id snapshot taken before the intent - a provider that existed before our on is never claimed.
  • Interrupt-safe: exit 3 (awaiting-provider / awaiting-profile); re-running on resumes, status shows the lifecycle state (router-missing / client-missing / not-configured / awaiting-* / key-valid / key-invalid).
  • off asks the user to delete the two entries in the UI, verifies their absence read-only, then revokes the child key and clears state (manual-pending, exit 3, while entries remain).

Shared

  • Exit codes per adapter contract: 0 ok · 2 refused prerequisite/version · 3 awaiting manual steps · 4 not configured (status). New --smoke flag sends one billable request after setup (smoke-test <model> --yes --json for Codex; gateway health + guidance for CCR, whose billable gateway call needs a UI-created client key).
  • Foundation additions are additive only: HarnessOnOptions.smoke, HarnessResult.state/exitCode/notes, exported keyIsValid, and revokeHarnessKeys (delete by name - the key endpoint enforces no name uniqueness).
  • Docs: CODING_HARNESSES.md sections for both adapters, README + SKILL.md adapter lists.

Tests

24 new tests (169/169 green in packages/polli-cli): fresh/existing/foreign configs, crash-recovery journal, byte-preserving off for pre-existing providers, ownership exclusion via pre-state, version-gate refusals, key-valid/key-invalid lifecycle, manual-pending off. Biome clean on all touched files.

Honest limits

  • The Codex Router provider/key/curation path was validated against the router's real source at the pinned commit (command schema, state paths, credential protocol) with fakes implementing that exact schema; a live Codex + router end-to-end run was not possible in this environment.
  • CCR was validated against the published 3.1.1 package (sqlite schema, home resolution, CLI surface); the UI steps themselves are manual by design (that is CCR's only supported path).

Quest pollinations#15218. Two router-backed harness adapters (codex via Codex
Router 5e1b49e/v0.6.0, claude-code via Claude Code Router 3.1.1):
documented router commands only, dedicated child keys, WAL journal
recovery, ownership markers, read-only CCR sqlite verification,
fail-closed version gates, exit codes 0/2/3/4, opt-in --smoke.
24 new tests; 169/169 green; biome clean.
@strix-security

strix-security Bot commented Sep 20, 2026

Copy link
Copy Markdown

Strix Security Review

Warning

This pull request has 6 commits after the last Strix review (2b6ef4e). Strix has not reviewed these changes.
Automatic review on push is off for this repository. To review the latest changes, tag @strix-security in a comment, or turn on re-review on push.

No security issues found.

Updated for 2b6ef4e.


Reviewed by Strix
Re-run review · Configure security review settings

- interprocess lock (mkdir mutex) around codex on/off and claude-code on/off
- reconcile never deletes a pre-existing credential file
- off rebuilds ownership baseline from a committed tx journal
- claude-code on re-mints and repairs when the stored key stops validating
- saved CCR ids re-validated against config shape; off requires context
- spawnCommand for Windows .cmd shims; key never printed on non-TTY
- router not-found matched on exact stderr text; pin enforced on mutations
- regression tests for all of the above (173 tests green)
@afanasevmylife

Copy link
Copy Markdown
Contributor Author

Cross-review round completed (independent reviewer pass over the full diff). All 11 findings were real and are fixed in 62cc1d6:

High

  • Pre-commit rollback no longer deletes a pre-existing credential file (only polli-published credentials are ever touched).
  • Added an interprocess lock (atomic mkdir mutex with stale-break) around on/off in both adapters, so two concurrent polli harness processes cannot misread each other's transaction journal.

Medium

  • off now rebuilds the ownership baseline from a committed tx journal if the baseline write was lost in a crash.
  • claude-code on validates the stored key even when the structure verifies; an invalid key triggers a re-mint + replace flow instead of a false "verified".
  • Saved CCR provider/profile ids are re-validated against the config shape before use; off requires our context journal before touching anything.
  • Windows .cmd shims are now spawned through a shell wrapper (codex/ccr/claude resolution).
  • The raw key is only printed on an interactive TTY; non-interactive runs point to the account page instead.
  • Router "provider not found" is matched on the exact stderr text, so unrelated router failures are no longer mistaken for absence.
  • The router pin check now also gates mutations in off, not just on.

Low

  • openUrl has a production default (dynamic open import) instead of requiring injection.

Regression tests added for the credential-preservation, committed-tx recovery, key-repair, and no-context-off paths. Full suite: 173/173 green locally; biome clean on all touched files.

@afanasevmylife

Copy link
Copy Markdown
Contributor Author

@strix-security re-run review please - 6 commits landed since the last pass at 2b6ef4e (merge with upstream main at 1d7fde2). Current head is the same code as the reviewed diff plus upstream sync; CI is green (11/11 check runs).

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[QUEST] Add Pollinations setup for Codex and Claude Code routers

1 participant