mirror of
https://github.com/OpenRouterTeam/spawn.git
synced 2026-04-28 11:59:29 +00:00
* feat(cli): posthog feature flags + fast_provision experiment
Wires PostHog `/decide` into the CLI so we can A/B-test provisioning
behaviors. First experiment: `fast_provision` — for users who didn't
pass --beta or --fast manually, the `test` variant turns on
`tarball + images` by default. Hypothesis: faster provisioning →
fewer drop-offs in the "VM ready → install completed" leg of the
funnel.
What's added:
- `shared/install-id.ts` — stable per-machine UUID, persisted at
~/.config/spawn/.telemetry-id. Reuses telemetry's existing path
so existing users keep their PostHog identity. Falls back to an
ephemeral UUID on disk-write failure.
- `shared/feature-flags.ts` — hand-rolled POST to PostHog /decide
(no SDK dep). 1.5s timeout, fail-open. On-disk cache at
$SPAWN_HOME/feature-flags-cache.json with 1h TTL so cold starts
don't pay the network cost. SPAWN_FEATURE_FLAGS_DISABLED=1 kill
switch. Captures `$feature_flag_called` exposure events for both
arms so PostHog can compute conversion.
- `shared/telemetry.ts` — moves user-id loading into install-id.ts
so flags and events share the same `distinct_id`.
- `index.ts` — `await initFeatureFlags()` at the top of `main()`,
then applies `fast_provision`'s `test` variant by appending
`tarball,images` to SPAWN_BETA — but only if the user didn't
pass --beta or --fast (those always win, so opt-out is free).
Why tarball+images and not all four (`+parallel,docker`):
clean attribution. The hypothesis is about tarball/image; if we
ship the full --fast bundle we can't tell which feature moved the
metric. Keep --fast as the user-facing power-user knob.
Tests: 14 new (install-id roundtrip + format guard, feature-flags
fetch/timeout/HTTP500/malformed/disabled/idempotent/stale-cache,
exposure-event behavior). Full suite: 2183 pass, same 4 pre-existing
failures as upstream/main.
Bumps CLI to 1.0.23.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(cli): skip feature-flag fetch in pick/feedback fast path; implement real SWR
Two review-fix commits from PR feedback squashed into one:
1. Move `await initFeatureFlags()` below the `spawn pick` and
`spawn feedback` bypass clauses in `main()`. Both commands are called
from bash scripts and must stay fast; neither gates on a flag, so
there's no reason to pay up to 1.5s of network latency on cold cache.
2. Implement real stale-while-revalidate in `shared/feature-flags.ts`.
The prior implementation did a synchronous fetch on stale cache,
which contradicted the docstring and PR description. Now:
- fresh cache (<TTL) → use cache, no network
- stale cache (>=TTL) → use cache immediately, refresh in background
- no cache → await sync fetch (first run only)
Adds `_awaitBackgroundRefreshForTest()` so tests can deterministically
wait for the background refresh before asserting. Updated the existing
"stale cache" test to verify SWR semantics (stale served first, fresh
lands next invocation) and added a "fresh cache does not fetch" test.
All 2127 tests pass; biome clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude <claude@anthropic.com>
27 lines
696 B
JSON
27 lines
696 B
JSON
{
|
|
"name": "@openrouter/spawn",
|
|
"version": "1.0.23",
|
|
"type": "module",
|
|
"bin": {
|
|
"spawn": "cli.js"
|
|
},
|
|
"scripts": {
|
|
"dev": "bun run src/index.ts",
|
|
"build": "bun build src/index.ts --outfile cli.js --target bun --minify --packages bundle",
|
|
"compile": "bun build src/index.ts --compile --outfile spawn",
|
|
"lint": "biome lint src/",
|
|
"test": "bun test",
|
|
"test:watch": "bun test --watch"
|
|
},
|
|
"dependencies": {
|
|
"@clack/prompts": "1.0.0",
|
|
"@daytonaio/sdk": "0.160.0",
|
|
"@openrouter/spawn-shared": "workspace:*",
|
|
"picocolors": "1.1.1",
|
|
"valibot": "1.2.0"
|
|
},
|
|
"devDependencies": {
|
|
"@biomejs/biome": "2.4.3",
|
|
"@types/bun": "1.3.8"
|
|
}
|
|
}
|