bitfab-cli 0.2.406 → 0.2.408

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +32 -21
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -24697,10 +24697,10 @@ var semver3 = __toESM(require_semver2(), 1);
24697
24697
 
24698
24698
  // ../bitfab-plugin-lib/dist/bakedSdkVersions.js
24699
24699
  var BAKED_SDK_VERSIONS = {
24700
- typescript: "0.62.8",
24701
- python: "0.62.7",
24702
- ruby: "0.62.7",
24703
- go: "0.62.7"
24700
+ typescript: "0.63.1",
24701
+ python: "0.63.1",
24702
+ ruby: "0.63.1",
24703
+ go: "0.63.1"
24704
24704
  };
24705
24705
 
24706
24706
  // ../bitfab-plugin-lib/dist/installedSdk.js
@@ -28623,6 +28623,9 @@ var FRAMEWORK_VARIABLES = {
28623
28623
  }
28624
28624
  };
28625
28625
 
28626
+ // ../bitfab-plugin-lib/dist/flows/replayFlags.js
28627
+ var SKIP_ASSERTION_JUDGING_FLAG = `**Add \`--skip-assertion-judging\` when the installed replay command accepts it.** Run the SDK-installed \`bitfab-replay --help\` once per workspace and SDK version, with the same package runner as the replay itself. When its options list \`--skip-assertion-judging\`, add it to every replay command in this step. Newer SDKs otherwise have the server judge each replay's approved assertions as it finishes, which would write a second set of verdicts beside the ones this flow writes and pay for both. Older SDKs reject the flag, so leave it off when \`--help\` does not list it.`;
28628
+
28626
28629
  // ../bitfab-plugin-lib/dist/flows/assistant.js
28627
28630
  var FAN_OUT_JUDGING = `{{#claude}}**Scale the judging with fan-out when there are many items.** Per-item judging is embarrassingly parallel: each verdict depends only on that one item's own artifacts (plus the fixed rubric and any shared context you gather once below), never on the other items, and the judge only reasons and returns JSON, it never edits files. So pick serial or fan-out by the item count:
28628
28631
 
@@ -30195,6 +30198,8 @@ The schema is flat, every file object is exactly \`{ path, before, after }\`. Do
30195
30198
  - **Initial \`fix\` pass (\`fixReplayScope = "single-trace"\`)**: pass \`--trace-ids <targetTraceId>\` (the trace ID held from Phase Fix \`resolve\`) and do NOT pass \`--dataset-id\`. This is the user's requested targeted replay. It proves the bug turned green before anything is added to a dataset or the rest of the dataset is run.
30196
30199
  - **Full dataset runs**: check the \`supportsDatasetId\` flag (from \`detect-replay-capabilities\`). When true, this is the **preferred way to replay the dataset**: pass \`--dataset-id <datasetId>\` (the dataset id held in working context: from \`pick-dataset\` in \`experiment\` / \`cost-optimize\` / \`benchmark\` modes, or from \`fix-add-to-dataset\` in \`fix\` mode, which skips \`pick-dataset\`) and **omit \`--trace-ids\` entirely**. The server replays exactly the dataset's traces and durably attributes the experiment to the dataset, so it shows under the dataset's experiments even when trace lineage can't be reconstructed, and you don't have to enumerate the dataset's trace IDs by hand. Only when \`supportsDatasetId\` is false do you fall back to \`--trace-ids <the dataset's resolved trace ids>\` (attribution then relies on the derived trace-lineage join). If the installed SDK lacks \`--dataset-id\`, prefer upgrading it (see \`upgrade-replay-script\`) over the trace-ids fallback.
30197
30200
 
30201
+ ${SKIP_ASSERTION_JUDGING_FLAG}
30202
+
30198
30203
  **Run the replay through \`{{command:replayProgress}}\` in the background, then relay the progress lines it prints.** Before starting, choose a unique run directory for this replay, for example \`.bitfab/replays/<experimentN>-<timestamp>-<short-random>\`, pass it with \`--run-dir\`, and hold that path in context; do not use a shared \`--events-log\` path. A foreground run blocks you for the whole replay and the user just sees "a shell is running" with no detail. \`{{command:replayProgress}}\` runs the replay, turns the SDK's per-trace \`@@bitfab:progress\` events into one self-contained line per trace on its stdout (a header, then for each trace as it finishes a pass/fail glyph, the running \`n/total\`, and that trace's duration, with the error reason inline on failure, plus a liveness heartbeat line when a slow trace goes quiet so the run never looks frozen, then a final summary with total + average time), and writes a small JSONL event log at \`<run-dir>/events.jsonl\`: \`type: "progress"\` rows as items finish, then a final \`type: "complete"\` row. Large per-item payloads are written atomically under \`<run-dir>/items/\` and referenced by \`item.itemPath\` / \`items[].itemPath\`, so outputs are not duplicated in the event log. It also tees every human line to \`<run-dir>/progress.log\`, so the user can \`tail -f\` it in a separate terminal for a live view that never collapses the way a tool card does. The wrapper writes \`<run-dir>/run.json\`; once the server experiment ID is known it also writes \`<parent-of-run-dir>/by-experiment/<experimentId>/run.json\` pointing back to the run directory. If the replay finishes no traces at all (an \`@bitfab/sdk\` too old to carry the lifecycle reporter, or an SDK too old to emit installed-command lifecycle events), it closes with a \`\u26A0 done \xB7 replay finished but reported no progress\` line instead of ending silently, so a missing stream of per-trace lines never reads as a hang, fix it via \`upgrade-replay-script\` and re-run. If the replay command exits 0 but its local \`ReplayResult\` capture is unavailable, the wrapper also exits 0, emits a \`\u26A0 unverified\` capture warning, and records \`status: "unverified"\` with \`resultCaptured: false\` in \`run.json\`: this prevents the host and metadata consumers from falsely reporting either failure or completion. Progress lines alone do not verify the result. Treat the outcome as unverified until the server experiment status resolves it; then explicitly report the server-confirmed outcome. You do NOT decide what or when to print: it does the formatting; you just show each new line.
30199
30204
 
30200
30205
  With a current replay-capable SDK, the event log also contains \`type: "started"\` lifecycle rows. These identify historical trace IDs that have entered a worker but have not necessarily settled; they are diagnostic only and must not be evaluated as completed items.
@@ -30984,7 +30989,7 @@ ${REPLAY_SAFETY_CHECK}
30984
30989
  toolCalls: ["bash"],
30985
30990
  title: "Run replay against the single trace",
30986
30991
  emit: "Running replay",
30987
- body: `**Run the replay against the one trace ID. No user interaction, no extra flags.** Invoke the SDK-installed executable with the registry and pipeline located in \`setup\`:
30992
+ body: `**Run the replay against the one trace ID. No user interaction, and no extra flags beyond the one below.** Invoke the SDK-installed executable with the registry and pipeline located in \`setup\`:
30988
30993
 
30989
30994
  \`\`\`bash
30990
30995
  # TypeScript: cd <project-dir> && pnpm exec bitfab-replay --registry <registry-path> <pipeline> --trace-ids <trace-id>
@@ -30992,6 +30997,8 @@ ${REPLAY_SAFETY_CHECK}
30992
30997
  # Ruby: cd <project-dir> && bundle exec bitfab-replay --registry <registry-path> <pipeline> --trace-ids <trace-id>
30993
30998
  \`\`\`
30994
30999
 
31000
+ ${SKIP_ASSERTION_JUDGING_FLAG}
31001
+
30995
31002
  This is a single-trace, in-chat path: run the replay directly, no progress-bar wrapper (one item has nothing to track). Do **not** pass \`--code-change\` or \`--experiment-group-id\`, this minimal path skips code-change payloads and experiment groups (persisting the verdict in the next step needs neither). Capture the full replay-result JSON and exit code, and from it hold the run's experiment ID (\`experimentId\` in TS, \`experiment_id\` in Python/Ruby; older SDKs print \`testRunId\` / \`test_run_id\`) and the completed item's trace id (\`traceId\` in TS, \`trace_id\` in Python/Ruby). **In the final replay result this trace id is already the SERVER replay trace id** (the SDK's \`completeReplay\` overwrites the local id with the server row id before returning), so the verdict step persists against it directly, no \`get_replay_status\` mapping. **If it is \`null\`, persistence is impossible this run** (an old server/SDK that returns no server-trace-id mapping), note that so the verdict step falls back to an in-chat-only verdict.
30996
31003
 
30997
31004
  **Quick health check.** If the replay crashed (non-zero exit, no items) or the single item has \`item.error\` set, hold the error for the verdict step. Otherwise hold the completed item's new output alongside the original output you read in \`setup\`.`,
@@ -31337,7 +31344,7 @@ If the block prints \`ERROR: Bitfab plugin not installed\`, the user hasn't inst
31337
31344
  inspect: "Diagnose (and offer to fix) your tracing setup: auth, what's instrumented, plugin/SDK freshness, replay coverage, trace arrival.",
31338
31345
  "switch-org": "Switch which Bitfab org the plugin reads and writes (replaces the local API key).",
31339
31346
  replay: "Create or update replay registry modules for instrumented workflows.",
31340
- cloud: "Set up replay in your own GitHub Actions using local gh authentication. No Bitfab repository connection required.",
31347
+ cloud: "Run your normal replay on your own GitHub Actions by adding --cloud. One workflow file in the repository; no Bitfab repository connection or GitHub CLI required.",
31341
31348
  "db-snapshot": "Set up per-trace database snapshots so replay runs against the DB state at trace time (TypeScript, Python, Ruby).",
31342
31349
  templates: "Iterate on the span-rendering templates for one trace function.",
31343
31350
  "analyze-repo": "Read-only discovery: scan source, rank the top workflows to instrument, and report recommendations without creating artifacts or changing code."
@@ -31401,31 +31408,35 @@ Never modify existing code on a refactor path without completing this three-step
31401
31408
  kind: "action",
31402
31409
  title: "Inspect the replay environment",
31403
31410
  toolCalls: ["bash", "read", "glob", "grep", "ask"],
31404
- body: `Read the existing GitHub Actions, runtime manifests, lockfiles, replay registry, gitignore, and environment-variable NAMES. Never read or print secret values. Check git origin, Python 3.10+, and gh authentication. Local dispatch supports macOS/Linux and github.com. Inspect all push-triggered workflows and deployment integrations. Temporary branches use bitfab-replay/** and can trigger those systems. Offer the usual fixes: a push workflow can add bitfab-replay/** to branches-ignore, or, when its push trigger already lists branches (GitHub does not allow both keys on one trigger), add !bitfab-replay/** as the last entry of that list, and a Vercel project can skip those branches with git.deploymentEnabled {"bitfab-replay/**": false} in its vercel.json or an Ignored Build Step in the dashboard. Ask before changing existing CI or deployment behavior. Do not set pushTriggersReviewed until these triggers have been reviewed with the user.
31411
+ body: `Cloud replay runs the replay the user already runs locally on their own GitHub Actions: they add --cloud to their normal bitfab-replay command and every other option works the same. The code that snapshots, dispatches, watches, and runs the replay ships inside the SDK, and the repository keeps one file: .github/workflows/bitfab-replay.yml, which holds only settings (install steps, the secrets the replay reads, the runner, and an optional Environment). Nothing else is written to the repository.
31412
+
31413
+ Read the existing GitHub Actions, runtime manifests, lockfiles, replay registry, gitignore, and environment-variable NAMES. Never read or print secret values. Check the git origin is github.com and Python 3.10+ exists (macOS or Linux). GitHub access needs no GitHub CLI: the SDK uses gh when it is logged in, otherwise GH_TOKEN or GITHUB_TOKEN, otherwise the github.com credential git already stores for pushing. Only copying secrets from local files needs gh. Run the installed SDK's bitfab-replay --cloud --help; if it does not describe --cloud-init with --secret, upgrade the SDK through bitfab:update before continuing.
31405
31414
 
31406
- Choose one existing replay registry and reproduce its runtime, dependency installation, build steps, working directory, caches, and required services from CI. Cover what every pipeline in that registry needs, since cloud replay allows all of them by default. Use the installed SDK's cloud-capable CLI: run its bitfab-replay --cloud --help now. If it does not list --cloud-init, the project's SDK predates this setup, so upgrade it through bitfab:update before continuing. The code that submits, watches, and runs cloud replays ships inside the SDK and updates with it; the repository keeps only settings: .bitfab/cloud.json and a workflow whose Replay step runs the SDK's bitfab-replay command with --cloud-execute. The runner reports its result as a job annotation, so the workflow needs no upload step. When the repository already has an older generated workflow (a Save replay identity upload step, a job timeout-minutes of 35, or a Replay step that runs .bitfab/cloudReplay.py), offer to update it: from workingDirectory run the SDK's bitfab-replay command with --cloud-init. On an existing setup it rewrites the Replay step to run the SDK command and removes two things older setups generated that the SDK now owns: the separate Save replay identity upload step and a job timeout-minutes of exactly 35. It keeps the checkout, other setup steps, secrets, runner, environment, services, and any timeout the user chose, and does nothing when the setup is already current. When the old step ran .bitfab/cloudReplay.py rather than the SDK, pass --config with a JSON file holding just cliCommand, the argv that starts bitfab-replay from workingDirectory. Delete any file the result lists as removable. Show the diff, and treat merging it like any other workflow change. TypeScript/Python/Ruby registry imports happen on the runner only. Go must dispatch cloud flags before building its registry or initializing the application. For database reads, prefer database branching. When the Bitfab organization has a database connected, each replay item gets a branch at its trace's captured instant, and the runner needs no database secret. That works only when every registry entry that reads the database sets dbBranch, and the application takes its connection per call from the replay branch URL (getCurrentReplayBranch().databaseUrl, or the Python, Ruby, or Go equivalent), falling back to its normal URL. A pool or engine created once at import from DATABASE_URL never sees the branch, and the SDK does not change DATABASE_URL, so check how the application builds its database client. When either piece is missing, offer to run db-snapshot mode first. Without branching, a private database needs runner network access or a replay-safe service fixture. Do not silently give replay production side effects. Submodules/gitlinks and credential-like tracked files are rejected by the snapshot helper. A gitlink with no .gitmodules entry is usually a nested repository committed by accident: offer to untrack it with git rm --cached and ignore its folder. Surface blockers instead of claiming the environment is ready.
31415
+ When the repository has .bitfab/cloud.json from an older SDK, run bitfab-replay --cloud-init from the directory where replay normally runs. It moves the settings into the workflow, removes .bitfab/cloud.json and any old .bitfab/cloudReplay.py, and reports droppedCommand when cloud.json had a custom replay command: the runner now starts the same bitfab-replay the user runs locally, so move any environment variables that command set into the Replay step's env. When the Replay step did not run the SDK command, pass --run with the command that starts bitfab-replay. Show the diff.
31407
31416
 
31408
- Say plainly which identity the runner uses: it authenticates only with the credentials in its GitHub secrets, never as the user. Local gcloud, AWS, or other cloud logins do not travel to the runner, so a bucket or API the user can reach from their laptop can still refuse the runner. When a cloud credential secret is a service account, ask for the account's email (never the key), and when the user's own CLI is logged in, check that the account can read what replay reads with an impersonated read, such as gcloud storage ls gs://<bucket> --impersonate-service-account=<email> or aws sts assume-role for a role. Report a refusal as the fix to make before the first run, not a warning.
31417
+ Inspect push-triggered workflows and deployment integrations: each replay pushes a temporary bitfab-replay/<UUID> branch. --cloud-init lists the ones it finds in reviewPushTriggers. Offer the usual fixes: a push workflow can add bitfab-replay/** to branches-ignore, or, when its push trigger already lists branches (GitHub does not allow both keys on one trigger), add !bitfab-replay/** as the last entry of that list, and a Vercel project can skip those branches with git.deploymentEnabled {"bitfab-replay/**": false} in its vercel.json or an Ignored Build Step in the dashboard. Ask before changing existing CI or deployment behavior.
31409
31418
 
31410
- State who can start a replay: once GitHub has registered the workflow, anyone with write access to the repository can dispatch it on any branch, including code the user never reviewed, and that run receives every runner secret. Recommend a GitHub Environment by default (environment: bitfab-replay) holding the replay secrets, with required reviewers, so no run gets credentials until someone approves it. Name the tradeoff: every replay then waits for an approval. Let the user decline, and record the choice.
31419
+ Compare what --cloud-init will detect with the project's CI (its result lists what it detected): the runtime and version, package manager, install command, build or code-generation steps, services, and working directory every pipeline in the registry needs. Go needs --run with the command that starts its registry program, such as go run ./cmd/registry, and the program must call RunCloudReplayCLI before building its registry. For database reads, prefer database branching: when the Bitfab organization has a database connected, each replay item gets a branch at its trace's captured instant and the runner needs no database secret. That works only when every registry entry that reads the database sets dbBranch and the application takes its connection per call from the replay branch URL (getCurrentReplayBranch().databaseUrl, or the Python, Ruby, or Go equivalent). A pool created once at import from DATABASE_URL never sees the branch, so check how the application builds its database client, and offer db-snapshot mode when either piece is missing. Without branching, a private database needs runner network access or a replay-safe fixture. Do not silently give replay production side effects. Submodules/gitlinks and credential-like tracked files are refused by the snapshot; a gitlink with no .gitmodules entry is usually a nested repository committed by accident, so offer to untrack it with git rm --cached and ignore its folder.
31411
31420
 
31412
- Present the proposed workflow, fixed replay command, required secret/variable names, the Environment choice, and any required CI trigger exclusions. Ask only about unresolved project choices. Never ask for secret values in chat.`,
31421
+ Say plainly which identity the runner uses: it authenticates only with the credentials in its GitHub secrets, never as the user. Local gcloud, AWS, or other cloud logins do not travel to the runner, so a bucket the user can read from their laptop can still refuse the runner. When a credential secret is a service account, ask for its email (never the key) and, when the user's own CLI is logged in, check that the account can read what replay reads, such as gcloud storage ls gs://<bucket> --impersonate-service-account=<email>. Report a refusal as the fix to make before the first run.
31422
+
31423
+ State who can start a replay: once GitHub has registered the workflow, anyone with write access to the repository can dispatch it on any branch, including code the user never reviewed, and that run receives every secret the workflow reads. Recommend a GitHub Environment (environment: bitfab-replay, set with --environment bitfab-replay) holding the replay secrets, with required reviewers, so no run gets credentials until someone approves it. Name the tradeoff: every replay then waits for an approval. Let the user decline.
31424
+
31425
+ Present the secret names the replay needs, the Environment choice, and any push-trigger exclusions. Ask only about unresolved choices. Never ask for secret values in chat.`,
31413
31426
  next: "cloud/install"
31414
31427
  },
31415
31428
  {
31416
31429
  id: "install",
31417
31430
  kind: "action",
31418
- title: "Install the cloud replay settings",
31431
+ title: "Write the cloud replay workflow",
31419
31432
  toolCalls: ["bash", "read", "write", "edit"],
31420
- body: `Create a reviewed JSON setup specification containing version: 1, provider: "github", workflow: "bitfab-replay.yml", workingDirectory (repository-relative), registry (repository-relative path or null for Go), pipeline (null allows every pipeline in the registry and is the default; a name restricts replay to that one pipeline, for when the others need credentials or services the runner should not have), command (the JSON argv array the runner uses to run the replay itself: the project's normal bitfab-replay invocation including --registry when the registry needs it, without the pipeline argument or any cloud flags; the runner appends the pipeline, --trace-ids, and --max-concurrency), cliCommand (the JSON argv array that starts the SDK's bitfab-replay command from workingDirectory, with no flags, such as ["npx", "--no-install", "bitfab-replay"] or ["node", "node_modules/@bitfab/sdk/dist/replayCli.js"]; the generated Replay step runs it with --cloud-execute), pushTriggersReviewed: true, setupSteps (GitHub Actions step objects), secrets (names including BITFAB_API_KEY), and variables (names only). Use optional env for anything else the replay step needs, mapping each environment variable name to {"secret": "<GitHub secret name>"} when the secret has another name, such as "OPENAI_API_KEY": {"secret": "EVAL_OPENAI_API_KEY"}, or to {"variable": "<repository variable name>"} for a non-secret value. Never hand-edit these into the workflow: cloud.json is what --cloud-secrets and the runner's empty-secret check read, so a mapping that lives only in the workflow is set under the wrong name and never checked. Optional checkCommand is a JSON argv array the runner executes from workingDirectory during --cloud-check, before any replay, to prove the environment works, such as a small script that reads one object from the bucket replay uses; propose one when replay reads cloud storage or another service with its own credentials. The runner always provides BITFAB_API_KEY. Find the variable the registry's Bitfab client actually reads its key from, and when it is another name, map it in the command, for example ["sh", "-c", "APP_KEY_NAME=\\"$BITFAB_API_KEY\\" exec <command> \\"$@\\"", "sh"]. Optional secretPrefix (uppercase, ending in an underscore) names the GitHub secret each one is read from without changing the environment variable the replay sees; it defaults to BITFAB_CLOUD_, and only an explicit empty string turns prefixing off. Optional runsOn and services match the existing CI. Set environment to the Environment chosen during inspection (bitfab-replay by default). When a setup step needs a credential file, such as a Google service account JSON, write it under $RUNNER_TEMP with umask 077 and export its path through $GITHUB_ENV: a step whose env maps GOOGLE_CREDENTIALS_JSON from its secret and whose run is umask 077; printf '%s' "$GOOGLE_CREDENTIALS_JSON" > "$RUNNER_TEMP/google.json"; echo "GOOGLE_APPLICATION_CREDENTIALS=$RUNNER_TEMP/google.json" >> "$GITHUB_ENV", and keep the name in secrets so the empty-secret check covers it. Do not use google-github-actions/auth or similar actions that write the key file into the checked-out workspace. Pin third-party actions to reviewed commit SHAs. Ensure Python 3.10+ exists on the runner. Commands run in workingDirectory. Registry in the command must be relative to that directory. Set step working-directory explicitly where needed. Do not copy deployment steps, local env values, or API keys into the specification.
31421
-
31422
- From workingDirectory, run the SDK's bitfab-replay command with --cloud-init --config <specification-path>. This creates .bitfab/cloud.json and .github/workflows/bitfab-replay.yml. The generated workflow is JSON, which is valid YAML. Its run-name and its execution_id and request inputs are how the SDK finds and feeds each run; never rename them. Running --cloud-init again is safe: on an existing setup it ignores the rest of the specification and only brings the Replay step up to date as described above, so change other settings by editing the files and reviewing the diff. Remove only your temporary specification after successful installation. If .bitfab is ignored, propose a narrow gitignore exception for .bitfab/cloud.json. Never force-add secrets or arbitrary ignored files.
31433
+ body: `From the directory where replay normally runs, run the SDK's bitfab-replay --cloud-init with --secret <NAME> for each environment variable the replay reads from a secret (BITFAB_API_KEY is always included), --environment <name> when the user chose one, and --check "<command>" when replay reads cloud storage or another service with its own credentials, such as a small script that reads one object from the bucket. Add --run "<command>" for Go or when the detected command is wrong, and --runs-on <label> to match existing CI. It detects the runtime, package manager, and install command from the directory it runs in, and writes .github/workflows/bitfab-replay.yml, the only file it creates. Running it again on a current setup changes nothing.
31423
31434
 
31424
- Tell the user which repository or Environment secrets to create in GitHub Settings \u2192 Secrets and variables \u2192 Actions. BITFAB_API_KEY belongs to the Bitfab organization that holds the registry's traces; confirm that with the user, because a key from another organization finds none of them. Have the user create a dedicated key for the runner on the API keys page of the Bitfab dashboard, named for what it is (such as "GitHub cloud replay"), rather than reusing the key the plugin logged in with or their personal development key, so it can be revoked or rotated without touching anyone's own setup. Other names come from their application, such as OPENAI_API_KEY. BITFAB_SERVICE_URL is optional. Do not override the SDK's default with an empty GitHub variable. Runtime secrets belong on the replay step. Any install-time credentials need explicit references on the relevant setup step. Local gh authentication is separate from these runner secrets. Do not create a Bitfab cloud target, install a GitHub App, or request a repository connection.
31435
+ Review the generated workflow against the project's CI and edit it directly for anything detection missed, such as a build step, code generation, a monorepo install filter, or services. When the user normally starts replay through a wrapper script that sets environment variables, add those variables to the Replay step's env, because the runner starts bitfab-replay itself. Pin any third-party action you add to a reviewed commit SHA. Keep its run-name and its execution_id and request inputs as generated: the SDK finds and feeds each run through them. Put every variable the replay reads from a secret in the Replay step's env, written like the generated entries: a GitHub expression reading secrets.<GitHub secret name>. That mapping is what --cloud-secrets and the runner's empty-secret check read, so a secret stored under another name is mapped there directly, such as OPENAI_API_KEY reading secrets.EVAL_OPENAI_API_KEY, and a non-secret value reads vars.<name>. When the registry's Bitfab client reads its key from another variable, map the same secret to that name too. When a setup step needs a credential file, such as a Google service account JSON, write it under $RUNNER_TEMP with umask 077 and export its path through $GITHUB_ENV: a step whose env maps GOOGLE_CREDENTIALS_JSON from its secret and whose run is umask 077; printf '%s' "$GOOGLE_CREDENTIALS_JSON" > "$RUNNER_TEMP/google.json"; echo "GOOGLE_APPLICATION_CREDENTIALS=$RUNNER_TEMP/google.json" >> "$GITHUB_ENV". Do not use google-github-actions/auth or similar actions that write the key file into the checked-out workspace. Do not copy deployment steps, local env values, or API keys into the workflow.
31425
31436
 
31426
- Init records the secret names and the resolved prefix in .bitfab/cloud.json, so later lifecycle commands reuse them without being told again. Runner secrets are prefixed BITFAB_CLOUD_ unless the user asks otherwise, so the runner reads BITFAB_CLOUD_OPENAI_API_KEY and exposes it to the replay as OPENAI_API_KEY. Replay credentials then never collide with secrets the repository already uses, and can carry narrower scopes or a different Bitfab organization than production. Pass a different prefix, or an empty string to reuse the repository's existing bare-named secrets, only when the user wants that. Report the names in requiredSecrets and requiredVariables as the ones to create. When --cloud-init on an existing setup reports conflicts or undeclared names, the Replay step sets those differently from cloud.json or without it; move each one into cloud.json env and rerun, so --cloud-secrets and the empty-secret check agree with the workflow.
31437
+ Secrets are read from GitHub secrets prefixed BITFAB_CLOUD_ unless the user asks otherwise (--secret-prefix, or an empty prefix to reuse bare-named secrets), so BITFAB_CLOUD_OPENAI_API_KEY reaches the replay as OPENAI_API_KEY and replay credentials never collide with secrets the repository already uses. Tell the user which secrets to create (the init result lists them) in GitHub Settings \u2192 Secrets and variables \u2192 Actions, in the repository or the Environment. BITFAB_API_KEY belongs to the Bitfab organization that holds the registry's traces; confirm that, because a key from another organization finds none of them. Have the user create a dedicated key for the runner on the API keys page of the Bitfab dashboard, named for what it is (such as "GitHub cloud replay"), rather than reusing the key the plugin logged in with or their personal development key, so it can be revoked or rotated on its own. BITFAB_SERVICE_URL is optional; do not override the SDK default with an empty variable. Do not create a Bitfab cloud target, install a GitHub App, or request a repository connection.
31427
31438
 
31428
- When the project keeps local environment files, list the NAMES each required secret could come from and ask whether to copy those local values into GitHub. Never read, print, or compare the values, and ask once for the whole set rather than per secret. On a yes, run the SDK's bitfab-replay command with --cloud-secrets --env-file <file> [--env-file <file>] [--environment <name>], which reads the recorded names and prefix, parses quoted, multi-line, and JSON values correctly, and pipes each value to gh on standard input so it never appears in arguments, process listings, or shell history. Never hand-extract a value with grep, cut, or a shell variable, and never pass one through gh secret set --body. Use --dry-run first to report which names the files define. The command reports set, missing, and empty names only; create the missing ones by hand. A name your files define as blank is skipped rather than uploaded, because an empty secret replaces a working default with nothing. Warn before copying a value whose own configuration points somewhere a runner cannot reach, such as a localhost service URL, or that grants more than the replay needs, and let the user decide. Leave BITFAB_API_KEY out of the copy by default and have the user set the dedicated runner key by hand, since a local file usually holds their personal or development key. Environment secrets need the Environment to exist: check with gh api repos/<owner>/<repo>/environments, and when it is missing, ask before creating it with gh api -X PUT repos/<owner>/<repo>/environments/<name>, offering the user as a required reviewer. Setting secrets requires the same explicit authorization as any other remote write, and a wrong value only surfaces when the first real replay runs, since the dry run never calls the application.`,
31439
+ When the project keeps local environment files, list the NAMES each secret could come from and ask once whether to copy those local values into GitHub. Never read, print, or compare the values. On a yes, run bitfab-replay --cloud-secrets --env-file <file> [--env-file <file>] --dry-run first, then without --dry-run. It reads the secret names and the Environment from the workflow, parses quoted, multi-line, and JSON values, and pipes each value to gh on standard input so it never appears in arguments, process listings, or shell history. Without gh it says which secrets to create by hand and where. Never hand-extract a value with grep, cut, or a shell variable, and never pass one through gh secret set --body. A name the files define as blank is skipped, because an empty secret replaces a working default with nothing. Warn before copying a value that points somewhere a runner cannot reach, such as a localhost URL, or that grants more than replay needs. Leave BITFAB_API_KEY out of the copy by default and have the user set the dedicated runner key by hand. Environment secrets need the Environment to exist: check with gh api repos/<owner>/<repo>/environments, and ask before creating it with gh api -X PUT repos/<owner>/<repo>/environments/<name>, offering the user as a required reviewer. Setting secrets requires the same explicit authorization as any other remote write.`,
31429
31440
  next: "cloud/verify"
31430
31441
  },
31431
31442
  {
@@ -31433,11 +31444,11 @@ When the project keeps local environment files, list the NAMES each required sec
31433
31444
  kind: "action",
31434
31445
  title: "Verify and hand off",
31435
31446
  toolCalls: ["bash", "read", "ask"],
31436
- body: `Validate workflow syntax (actionlint when available) and run the installed SDK CLI with --cloud --help. GitHub must have registered the workflow before it can be dispatched, and merging it to the default branch once registers it. After that, each replay dispatches the workflow as it is in that replay's snapshot, so later workflow edits apply on the next replay without merging, and the SDK only requires that the workflow is registered and enabled. Explain the required commit/merge for the first registration. Do not push, merge, change repository permissions, or set secrets without authorization.
31447
+ body: `Validate workflow syntax (actionlint when available). GitHub must register the workflow before it can be dispatched, and merging it to the default branch once registers it. After that, each replay dispatches the workflow as it is in that replay's snapshot, so later edits apply on the next replay without merging. Explain the one required merge. Do not push, merge, change repository permissions, or set secrets without authorization.
31437
31448
 
31438
- After the setup files are tracked (until then, pass each one with --cloud-include; the helper names any that are missing), run bitfab-replay --cloud <pipeline> --trace-ids <real-trace-uuid> --cloud-dry-run using the selected SDK command. It reports changed tracked files and omitted new files. Include new source files explicitly with repeated --cloud-include <repository-relative-file>. Review the entire snapshot for credentials. Filename screening is not a secret scanner. Then, once the workflow is merged and the secrets are set, run the same command with --cloud-check in place of --cloud-dry-run, when remote runs are authorized. It dispatches a real run that replays nothing: the runner stops with the names of any configured secrets that are empty (GitHub turns a secret that does not exist into an empty string), runs checkCommand, and resolves the traces with the replay's --dry-run, which loads the registry and proves the Bitfab key reaches the traces. Fix what it reports before the first replay, and read the Replay step log it links when it fails. Then, only when remote replay is authorized, run without --cloud-check. Any replay option the user would pass locally, such as --name, --dataset-ids in place of --trace-ids, --attempts, --judge-assertions, or --resume, goes after the pipeline and is passed to the replay on the runner as given; --params and --code-change files must be in the snapshot. --registry comes from cloud.json, and --dry-run and seeding stay local. Add --fail-on-error when a script should exit 1 on errored items. When items error, the runner prints each item's error, shortened, in the step log and the job summary. The helper creates a commit through an isolated index, pushes bitfab-replay/<UUID>, dispatches that branch, waits, retrieves the test-run identity, and deletes the branch with an exact-SHA lease. HEAD, staged changes, and working files stay untouched. Never reset or undo the user's work.
31449
+ Verify with the replay command the user already runs, plus cloud flags. First add --cloud --cloud-dry-run, which pushes nothing and reports the changed tracked files and omitted new files; include new source files with repeated --cloud-include <repository-relative-file> (until the workflow is committed, include it too). Review the entire snapshot for credentials; filename screening is not a secret scanner. Then, once the workflow is merged and the secrets are set, and when remote runs are authorized, run the same command with --cloud --dry-run. That dispatches a real run that replays nothing but receives the workflow's secrets, so it needs the same authorization as a replay: it stops with the names of any mapped secrets that are empty (GitHub turns a secret that does not exist into an empty string), runs the --check command, and resolves the traces with the replay's own --dry-run, proving the registry loads and the Bitfab key reaches the traces. --cloud-check is the same. Fix what it reports before the first replay, reading the Replay step log it links. Then, only when remote replay is authorized, run with just --cloud. Every replay option works as it does locally, in any order; --params and --code-change files must be in the snapshot; seeding stays local. Add --fail-on-error when a script should exit 1 on errored items. HEAD, staged changes, and working files stay untouched; never reset or undo the user's work.
31439
31450
 
31440
- Use --cloud-detach to return immediately; always detach from an agent session, since a replay can run for hours and, once GitHub shows the run, the wait has no local limit (it gives up only when GitHub shows no run for a dispatch within 10 minutes). Pass --cloud-timeout <minutes> (1..7200) to stop one replay early: the runner stops it cleanly and finished traces stay saved as an interrupted experiment. The generated job sets no timeout, so GitHub's 6-hour limit for its own runners applies; longer replays need a self-hosted runner with timeout-minutes set on the job. Explain --cloud-status, --cloud-watch, --cloud-cancel, and --cloud-cleanup with the printed execution UUID. Records live under this worktree's Git directory. Interrupted/lost-response submissions must be recovered, not blindly dispatched again. Cancel requests do not imply the job stopped. Watch/status confirms completion before deleting the branch. Detached jobs do not automatically clean themselves without a later local lifecycle command. Report separately whether files are generated, secrets configured, workflow merged, dry-run verified, cloud check passed, and an actual remote replay completed. Never call a mock smoke run a real replay.`,
31451
+ Always add --cloud-detach from an agent session, since a replay can run for hours and, once GitHub shows the run, the wait has no local limit (it gives up only when GitHub shows no run within 10 minutes). --cloud-timeout <minutes> (1..7200) stops one replay early and keeps finished traces as an interrupted experiment. The generated job sets no timeout, so GitHub's 6-hour limit for its own runners applies. Explain --cloud-status, --cloud-watch, --cloud-cancel, and --cloud-cleanup with the printed execution UUID; records live under this worktree's Git directory, and a detached run's branch is removed only by a later watch, status, or cleanup. Recover interrupted submissions with --cloud-request-id instead of dispatching again. Report separately whether the workflow is written, secrets configured, workflow merged, snapshot dry run reviewed, cloud dry run passed, and a real replay completed.`,
31441
31452
  next: "cleanup/finish"
31442
31453
  }
31443
31454
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bitfab-cli",
3
- "version": "0.2.406",
3
+ "version": "0.2.408",
4
4
  "description": "Install and configure the Bitfab plugin in Claude Code, Codex, or Cursor, or the Bitfab skill pack in Amp (Alpha).",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",