bitfab-cli 0.2.414 → 0.2.416

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 +46 -26
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -29868,10 +29868,10 @@ var semver3 = __toESM(require_semver2(), 1);
29868
29868
 
29869
29869
  // ../bitfab-plugin-lib/dist/bakedSdkVersions.js
29870
29870
  var BAKED_SDK_VERSIONS = {
29871
- typescript: "0.64.0",
29872
- python: "0.64.0",
29873
- ruby: "0.64.0",
29874
- go: "0.64.0"
29871
+ typescript: "0.64.2",
29872
+ python: "0.64.2",
29873
+ ruby: "0.64.2",
29874
+ go: "0.64.1"
29875
29875
  };
29876
29876
 
29877
29877
  // ../bitfab-plugin-lib/dist/installedSdk.js
@@ -33797,6 +33797,23 @@ var FRAMEWORK_VARIABLES = {
33797
33797
  // ../bitfab-plugin-lib/dist/flows/replayFlags.js
33798
33798
  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.`;
33799
33799
 
33800
+ // ../bitfab-plugin-lib/dist/flows/replayRegistryRules.js
33801
+ var REGISTRY_PLACEMENT_RULES = [
33802
+ "**Put the registry where production builds the call.** Find the production code that calls the root and builds what it passes in (tools, clients, config). The registry goes in that package's scripts location (Go: `cmd/registry/main.go`), and `bitfab-replay` runs from that package's directory. When the root is defined in a lower-level library and an app package calls it with tools or clients it built, the registry goes in the app package, even when the Bitfab SDK is so far installed only in the library. Add the SDK to the app package's dependencies. That is normal setup, not a refactor or an architecture change, so it needs no confirmation. Name the added dependency in the summary you give the user. Never copy the app's dependencies into the library.",
33803
+ "**Never replay with less than production wiring.** An entry that calls the root with an empty or smaller toolset, a stub client, a no-op callback, or a hand-built runner that skips production wiring replays code production never runs. Never write one, not even temporarily with a TODO, and never run replay on one. An existing registry like that counts as missing. Fix it instead of running it, and do not offer running it as an option.",
33804
+ "**Rebuild what the recording cannot keep.** When the root takes live objects as arguments (tools with their functions, clients, callbacks), the recording keeps only their data. Rebuild them in the entry's input adapter (`adaptInputs` / `adapt_inputs` / `AdaptInputs`) by calling the same code production uses. If production builds them inline, extract that code into an exported function that production and the registry both call. That edits production code, so confirm it first. Show the user the function being extracted, the file it moves to, and each call site that changes, state that the logic moves unchanged, and wait for a yes before editing. Present it as a small visibility change, not an architecture change. If the user declines, stop and say that replay cannot rebuild these arguments without it.",
33805
+ "**Rebuilt tools run for real unless marked.** A tool call returns its recorded output during replay only inside a marked span (`mockOnReplay` / `mock_on_replay` / `WithMockOnReplay`). Tool calls recorded by a framework handler, such as the Claude Agent SDK handler's tool spans, are records only, so those tools run for real. Before any replay, list every tool the registry wires in and put each one that writes, sends, charges, or calls a paid API behind a marked span. If a tool cannot be marked because it runs where replay cannot reach it, stop and tell the user that replaying this workflow runs that tool for real.",
33806
+ "**Experiment settings are not registry entries.** Set a model swap or any other experiment setting through an environment variable the app already reads. `optionsFactory` / `options_factory` only changes replay options such as mocking, never how the app builds the root. Never add a second registry entry with the setting written into it.",
33807
+ "**Check the wiring before calling it done.** Run `--dry-run` first. The first real replay of an unchanged trace (after the replay safety check) should take the same tool path as the original. A tool the original called that the replay skips means production wiring is still missing."
33808
+ ];
33809
+ function bulletList(rules, indent) {
33810
+ return rules.map((rule) => `${indent}- ${rule}`).join("\n");
33811
+ }
33812
+ var REPLAY_REGISTRY_VARIABLES = {
33813
+ registryPlacementRules: bulletList(REGISTRY_PLACEMENT_RULES, ""),
33814
+ registryPlacementRulesNested: bulletList(REGISTRY_PLACEMENT_RULES, " ")
33815
+ };
33816
+
33800
33817
  // ../bitfab-plugin-lib/dist/flows/assistant.js
33801
33818
  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:
33802
33819
 
@@ -34052,6 +34069,7 @@ In sub-modes that take a function key, grep the codebase for \`<key>\` early so
34052
34069
  },
34053
34070
  variables: {
34054
34071
  ...FRAMEWORK_VARIABLES,
34072
+ ...REPLAY_REGISTRY_VARIABLES,
34055
34073
  /**
34056
34074
  * How a question is presented to the user. Claude / Cursor have the
34057
34075
  * `AskUserQuestion` tool ("via AskUserQuestion"); Codex doesn't and
@@ -34252,7 +34270,7 @@ If the user chooses **"Instrument now"**, tell the user to run \`{{cmd}}setup in
34252
34270
  title: "Check replay registry",
34253
34271
  body: `Search for a replay registry module that covers this trace function:
34254
34272
 
34255
- - Look for \`scripts/replayRegistry.*\`, \`scripts/replay_registry.*\`, or a module defining \`ReplayRegistry\` / \`defineReplayRegistry\`
34273
+ - Look for \`scripts/replayRegistry.*\`, \`scripts/replay_registry.*\`, \`cmd/registry/main.go\`, or a module defining \`ReplayRegistry\` / \`defineReplayRegistry\` / \`NewReplayRegistry\`
34256
34274
  - Read the registry and check that an entry maps a pipeline name to the target trace function key and the exact production root
34257
34275
  - Treat a project-owned file that parses replay flags or calls \`replay()\` as a legacy expanded script, not a current registry
34258
34276
 
@@ -34268,6 +34286,10 @@ If the user chooses **"Create registry entry now"**, fetch the SDK replay refere
34268
34286
 
34269
34287
  For decorated or manually wrapped roots, the registry must import the exact same exported top-level traced wrapper that production/runtime calls to create the root span. If production creates that wrapper inside a route, job, handler, callback, or local scope, extract it into the nearest import-safe service/module and update production and the registry to import the same symbol. Do not create duplicate semantic wrappers. For handler-instrumented keys, register the key with a plain callable that invokes the same framework entrypoint and reconstructs runtime wiring. If root parity is impossible, stop and document the concrete blocker.
34270
34288
 
34289
+ Placement and wiring rules for the registry:
34290
+
34291
+ {{registryPlacementRules}}
34292
+
34271
34293
  After editing, report \`Replay root parity:\`, \`Production root symbol:\`, \`Production import/path:\`, \`Registry symbol:\`, \`Registry import/path:\`, \`Same symbol? yes/no\`, and \`If no, why is this impossible?\`. Do not invoke \`{{cmd}}setup replay\` as a separate skill.
34272
34294
 
34273
34295
  ${REPLAY_SAFETY_CHECK}`,
@@ -36529,6 +36551,7 @@ If the block prints \`ERROR: Bitfab plugin not installed\`, the user hasn't inst
36529
36551
  variables: {
36530
36552
  ...SHARED_VARIABLES,
36531
36553
  ...FRAMEWORK_VARIABLES,
36554
+ ...REPLAY_REGISTRY_VARIABLES,
36532
36555
  /**
36533
36556
  * Tool-call syntax for spawning the 11b replay-pipeline subagent. Claude
36534
36557
  * Code's Task tool is invoked as `Agent(subagent_type="...")`; Cursor has
@@ -36862,7 +36885,7 @@ Then go to {{skill-ref:instrument}} and start at its first step. The guided path
36862
36885
  title: "Hand over the docs and stop",
36863
36886
  body: `The user is instrumenting on their own. Give them the pointers below in one short message, then **stop**: do not scan the codebase, read files, or edit anything.
36864
36887
 
36865
- - **Docs:** https://docs.bitfab.ai, start with the SDK documentation for their language (\`/typescript-sdk\`, \`/python-sdk\`, \`/ruby-sdk\`, \`/go-sdk\`); each one covers install, initialization, wrapping a workflow, and (outside Go) the replay registry module. Name the language's page directly if the project's language is already obvious from the conversation; do not go read the repo to find out.
36888
+ - **Docs:** https://docs.bitfab.ai, start with the SDK documentation for their language (\`/typescript-sdk\`, \`/python-sdk\`, \`/ruby-sdk\`, \`/go-sdk\`); each one covers install, initialization, wrapping a workflow, and the replay registry module. Name the language's page directly if the project's language is already obvious from the conversation; do not go read the repo to find out.
36866
36889
  - **API key:** their app needs \`BITFAB_API_KEY\` set in the environment it runs in before any trace will arrive. Tell them to get the key from the Bitfab MCP's \`get_bitfab_api_key\` tool. Do **not** call it yourself, and never print a key.
36867
36890
  - **Coming back:** \`{{cmd}}setup\` picks this flow back up, and \`{{cmd}}setup inspect\` diagnoses an instrumentation they wrote themselves (auth, what's instrumented, whether traces are arriving).
36868
36891
 
@@ -37140,7 +37163,7 @@ Recommend one to start with. **Ask the user to pick exactly ONE workflow to inst
37140
37163
  kind: "action",
37141
37164
  toolCalls: ["edit", "webFetch"],
37142
37165
  title: "Write instrumentation and replay registry together",
37143
- body: `{{^codex}}**Write the instrumentation edits (11a) and the replay registry module (11b) for this trace function in the same cycle.** Reuse the Replay section already in context. The project owns the registry module only; the installed SDK owns the executable. Skip 11b for Go-only projects.
37166
+ body: `{{^codex}}**Write the instrumentation edits (11a) and the replay registry module (11b) for this trace function in the same cycle.** Reuse the Replay section already in context. The project owns the registry module only; the installed SDK owns the executable. For Go, 11b is the compiled registry command \`cmd/registry/main.go\`.
37144
37167
 
37145
37168
  **Delegate 11b to a subagent only when 11a is itself a large mechanical fan-out** (>10 files) whose generation genuinely overlaps the registry work. The subagent must follow the same registry-only contract.
37146
37169
 
@@ -37154,13 +37177,14 @@ Recommend one to start with. **Ask the user to pick exactly ONE workflow to inst
37154
37177
  - **Replay root parity (hard rule)**: register the exact same exported top-level traced wrapper that production/runtime calls to create the root span. You must do this unless it is genuinely impossible in the host app; inconvenience, extra refactoring, an inline wrapper, or needing to move code is not impossible. If production creates it inline, extract it into the nearest appropriate service/module, export it, and update both production and replay to import and call that same symbol. Do not replay a convenient inner helper unless that exact helper is also the production root traced wrapper. Avoid duplicate semantic wrappers split across production and replay with names like \`runX\`, \`processX\`, or \`generateX\`. Handler roots register a plain callable that re-invokes the same framework entrypoint production calls with an explicit trace function key.
37155
37178
  {{handlerReplayBlock}}
37156
37179
  - **Registry target**: add the entry to the existing registry module or create one using the language convention: TypeScript default export from \`defineReplayRegistry\`, Python variable \`registry\`, Ruby constant \`REGISTRY\`.
37180
+ {{registryPlacementRulesNested}}
37157
37181
  - **Non-negotiables**: the module contains app bootstrap/imports, exact production roots, and per-function defaults only. It never parses CLI arguments, calls \`replay()\`, invokes a runner, installs lifecycle callbacks, prints output, or handles \`BITFAB_REPLAY_RESULT_PATH\`. Put the safety-audited mock strategy and input adapter on the registry entry. The SDK-installed \`bitfab-replay --registry <path> <pipeline> [options]\` command owns all common behavior.
37158
37182
  - **Replay-safety validation**: re-check every unsafe action against the safety-audited mock strategy before running the command. A synchronous TypeScript unsafe span cannot consume lazy \`mock: "marked"\` output; use \`all\` only when freezing every matched child is acceptable. Python worker-thread dispatch requires \`trace_across_threads=True\`. A Ruby child-thread, pre-created consumer, or process does not inherit replay interception. Do not hand-mock DB clients or other unsafe dependencies; keep the real call behind a selected replay-mockable marked span so its recorded output is served.
37159
37183
  - **Lifecycle and output contract**: do not implement either in project code; the installed executable owns progress callbacks, stderr summaries, stdout JSON, and result-file transport.
37160
37184
  - **Match the registry template exactly**: do not add speculative wrappers, arity branches, type-checker escape hatches, or untyped passthroughs. Use the per-entry input adapter for genuine historical signature drift.
37161
37185
  - **Per-item error tolerance**: do not catch errors inside the registered function or replace them with placeholders; the SDK executable preserves replay and trace errors while continuing the batch.
37162
37186
  - **Side-effect check**: if importing the instrumented function triggers module-level side effects (booting listeners/ports/prod connections), do not work around it silently; flag it to the user (a subagent returns that fact in its report so the main agent can flag it).
37163
- - **Result**: confirm the registry module path and the exact \`bitfab-replay --registry ...\` command. Surface signature mismatches or import side effects.{{/codex}}{{#codex}}**Write instrumentation AND the replay registry module for this trace function in the same cycle.** Skip the registry for Go-only projects.
37187
+ - **Result**: confirm the registry module path and the exact \`bitfab-replay --registry ...\` command. Surface signature mismatches or import side effects.{{/codex}}{{#codex}}**Write instrumentation AND the replay registry module for this trace function in the same cycle.** For Go, the registry is the compiled command \`cmd/registry/main.go\`.
37164
37188
 
37165
37189
  **Default instrumentation policy:** use opt-out tracing whenever the selected TypeScript or Python workflow supports it. TypeScript setup must configure the bundled \`@bitfab/sdk/transform\` adapter in the application build, then put \`withTrace\`/\`trace\` on the existing workflow root. Python 3.12+ uses \`trace\` on the root. Let first-party descendants be discovered automatically and use \`withNode\`/\`node\` for external reads, unsafe side effects, model calls, naming, typing, capture overrides, finalization, and replay mocking. Do not add \`withSpan\` inside an opt-out trace. Existing \`withSpan\` usage is not a reason to extend the opt-in pattern. When a manual span already runs inside the selected call stack, migrate the call stack instead of abandoning opt-out. Before converting a span-bearing helper in place, inspect every production caller and confirm each caller belongs to the same opt-out surface; if an opt-in caller remains, use a disjoint trace boundary or stop for refactor confirmation. Remove redundant span wrappers. Replace spans that carry policy with nodes and preserve that policy. TypeScript \`withNode\` requires a named function, so preserve an existing name or use an additive named function form; stop for refactor confirmation if naming it requires a non-additive rewrite. This tracing-surface migration is instrumentation work, not an application refactor. Stop for refactor confirmation only if preserving application behavior requires changing the underlying function or its callers. Spans remain supported, but during setup choose them only when opt-out is technically impossible: Ruby, Go, unsupported Python runtimes, a TypeScript build path unsupported by every documented transform adapter, or a live streaming root whose output opt-out tracing cannot finalize without changing behavior. Framework integrations and their generated spans remain nested beneath the opt-out root; they do not justify a span root. Adding a supported transform adapter, including the esbuild adapter used by tsup, is required setup work rather than a fallback reason. Report the concrete technical blocker and keep the selected call stack on one tracing surface.
37166
37190
 
@@ -37173,6 +37197,7 @@ Recommend one to start with. **Ask the user to pick exactly ONE workflow to inst
37173
37197
  - **Replay root parity (hard rule)**: register the exact same exported top-level traced wrapper that production/runtime calls to create the root span. You must do this unless it is genuinely impossible in the host app; inconvenience, extra refactoring, an inline wrapper, or needing to move code is not impossible. If production creates it inline, extract it into the nearest appropriate service/module, export it, and update both production and replay to import and call that same symbol. Do not replay a convenient inner helper unless that exact helper is also the production root traced wrapper. Avoid duplicate semantic wrappers split across production and replay with names like \`runX\`, \`processX\`, or \`generateX\`. Handler roots register a plain callable that re-invokes the same framework entrypoint production calls with an explicit trace function key.
37174
37198
  {{handlerReplayBlock}}
37175
37199
  - **Registry target**: add the entry to the existing registry module or create one using the language convention: TypeScript default export from \`defineReplayRegistry\`, Python variable \`registry\`, Ruby constant \`REGISTRY\`.
37200
+ {{registryPlacementRulesNested}}
37176
37201
  - **Non-negotiables**: the module contains app bootstrap/imports, exact production roots, and per-function defaults only. It never parses CLI arguments, calls \`replay()\`, invokes a runner, installs lifecycle callbacks, prints output, or handles \`BITFAB_REPLAY_RESULT_PATH\`. Put the safety-audited mock strategy and input adapter on the registry entry. The SDK-installed \`bitfab-replay --registry <path> <pipeline> [options]\` command owns all common behavior.
37177
37202
  - **Replay-safety validation**: re-check every unsafe action against the safety-audited mock strategy before running the command. A synchronous TypeScript unsafe span cannot consume lazy \`mock: "marked"\` output; use \`all\` only when freezing every matched child is acceptable. Python worker-thread dispatch requires \`trace_across_threads=True\`. A Ruby child-thread, pre-created consumer, or process does not inherit replay interception. Do not hand-mock DB clients or other unsafe dependencies; keep the real call behind a selected replay-mockable marked span so its recorded output is served.
37178
37203
  - **Lifecycle and output contract**: do not implement either in project code; the installed executable owns progress callbacks, stderr summaries, stdout JSON, and result-file transport.
@@ -37604,13 +37629,13 @@ If the user agrees, use the \`apiKey\` value from the switch step's JSON output
37604
37629
  stepStyle: "list",
37605
37630
  intro: `Create or update replay registry modules for instrumented trace functions. Requires instrumentation in the codebase; does **not** require existing traces, replay registry modules are created from trace function keys in the code, not captured trace data.
37606
37631
 
37607
- The SDK-installed \`bitfab-replay\` command lets the team regression-test any registered trace function against production data with one command: it fetches historical traces, re-runs them through the current code, and reports old vs. new outputs side-by-side. The project owns only the registry module. **Go supports programmatic replay through its SDK, but has no installed replay registry CLI.** For a Go-only project, point to https://docs.bitfab.ai/go-sdk.md and https://docs.bitfab.ai/reference/go.md for the replay API, then skip this registry-specific phase.
37632
+ The SDK-installed \`bitfab-replay\` command lets the team regression-test any registered trace function against production data with one command: it fetches historical traces, re-runs them through the current code, and reports old vs. new outputs side-by-side. The project owns only the registry module. **Go has no installed command: a Go project compiles its registry into its own command**, conventionally \`cmd/registry/main.go\`, which builds a \`bitfab.NewReplayRegistry()\` and passes it with \`os.Args[1:]\` to \`bitfab.RunReplayCLI\`. It runs as \`go run ./cmd/registry <pipeline> [flags]\` and takes the same flags. Wherever this phase says \`bitfab-replay --registry <path>\`, a Go project uses that command instead.
37608
37633
 
37609
37634
  **Relationship to Instrument.** Instrument's write-instrumentation step writes each replay pipeline alongside the instrumentation edits. Run this mode standalone (\`{{cmd}}setup replay\`) to catch pre-existing trace function keys that predate that step or were added outside the skill.
37610
37635
 
37611
37636
  **Source of truth:** two pages, read both before creating or modifying a replay registry module. Do not improvise from memory.
37612
- - **Canonical \`replay\` API signature, options, and return shape:** \`/reference/typescript.md\`, \`/reference/python.md\`, \`/reference/ruby.md\` (these are the languages supported by this registry workflow). Use this for the exact field names (\`result\` / \`originalOutput\` vs \`original_output\`), default \`limit\`, \`maxConcurrency\`/\`max_concurrency\`, error behavior.
37613
- - **Copy-pasteable registry template + installed-command contract + input serialization caveat:** \`/typescript-sdk.md\`, \`/python-sdk.md\`, \`/ruby-sdk.md\`. Use this for the language-specific registry shape and the standard \`bitfab-replay --registry <path> <pipeline>\` invocation.`,
37637
+ - **Canonical \`replay\` API signature, options, and return shape:** \`/reference/typescript.md\`, \`/reference/python.md\`, \`/reference/ruby.md\`, \`/reference/go.md\`. Use this for the exact field names (\`result\` / \`originalOutput\` vs \`original_output\`), default \`limit\`, \`maxConcurrency\`/\`max_concurrency\`, error behavior.
37638
+ - **Copy-pasteable registry template + installed-command contract + input serialization caveat:** \`/typescript-sdk.md\`, \`/python-sdk.md\`, \`/ruby-sdk.md\`, \`/go-sdk.md\`. Use this for the language-specific registry shape and the standard \`bitfab-replay --registry <path> <pipeline>\` invocation (Go: \`go run ./cmd/registry <pipeline>\`).`,
37614
37639
  steps: [
37615
37640
  {
37616
37641
  id: "gather-keys",
@@ -37625,7 +37650,7 @@ The SDK-installed \`bitfab-replay\` command lets the team regression-test any re
37625
37650
  kind: "action",
37626
37651
  toolCalls: ["glob", "grep"],
37627
37652
  title: "Search for existing replay registries",
37628
- body: "**Search for existing replay registry modules**: files matching `scripts/replayRegistry.*`, `scripts/replay_registry.*`, or files defining an SDK `ReplayRegistry` / `defineReplayRegistry` (fall back to direct replay API calls for legacy scripts).",
37653
+ body: "**Search for existing replay registry modules**: files matching `scripts/replayRegistry.*`, `scripts/replay_registry.*`, or `cmd/registry/main.go`, or files defining an SDK `ReplayRegistry` / `defineReplayRegistry` / `NewReplayRegistry` (fall back to direct replay API calls for legacy scripts).",
37629
37654
  next: "replay/compare-coverage"
37630
37655
  },
37631
37656
  {
@@ -37652,24 +37677,19 @@ The SDK-installed \`bitfab-replay\` command lets the team regression-test any re
37652
37677
  kind: "action",
37653
37678
  toolCalls: ["webFetch", "write", "edit"],
37654
37679
  title: "Create or update replay registry",
37655
- body: `**Create the replay registry module** following the example in the SDK reference's Replay section (\`https://docs.bitfab.ai/<language>-sdk.md\`), adapted to this codebase. The project file must contain only normal app bootstrap/imports, registry entries, and per-function defaults. It must not invoke a replay runner. The SDK-installed \`bitfab-replay\` executable loads the module passed through \`--registry\` and owns argument parsing, progress callbacks, code-change loading, summaries, and result serialization. The non-negotiables are:
37656
- - **Ground the registry in the docs, not memory.** Before writing it, fetch \`https://docs.bitfab.ai/reference/<language>.md\` for the canonical registry shape, then \`https://docs.bitfab.ai/<language>-sdk.md\` for the module template and executable command. Quote the exact registry export convention and command in your plan.
37657
- - **For keys with a decorated function in the app: register the decorated function itself, not an undecorated wrapper.** The trace function key is read from the decorator/attribute on the function stored in the registry. A plain closure around the decorated function (for example \`(x) => fn(x)\`) carries no key and would create a duplicate nested root, so register the decorated function directly. For Python class methods, register \`Class.method\` or a bound \`instance.method\`. For Ruby, register the production \`receiver\` and \`method_name\`.
37658
- - **Handler-instrumented keys (no decorated function in the app) register an explicit key.** When a key is recorded only via a framework handler ({{keyedHandlerKeyRefs}}), register the plain callable that re-invokes the same production framework entrypoint, plus the key explicitly (TypeScript \`traceFunctionKey\`; Python/Ruby \`trace_function_key\`). The callable receives the recorded root input and reconstructs only the runtime wiring the production entrypoint needs. Every unsafe production action reached through that wiring must remain behind a replay-mockable marked span. Use a no-op only for a genuinely replay-only callback slot with no production action and no recorded call to mock.
37680
+ body: `**Create the replay registry module** adapted to this codebase. Ground it in the docs, not memory: fetch \`https://docs.bitfab.ai/reference/<language>.md\` for the canonical registry shape, then \`https://docs.bitfab.ai/<language>-sdk.md\` for the module template, the executable command, and the worked example under "When the traced function needs the app's dependencies". Quote the exact registry export convention and command in your plan.
37681
+
37682
+ The project file holds only app imports and bootstrap, registry entries, and per-function defaults (\`adaptInputs\` / \`adapt_inputs\`, mock overrides, database branching). The SDK-installed \`bitfab-replay\` executable loads it through \`--registry\` and owns everything else: every flag (\`--limit\`, \`--trace-ids\`, \`--dataset-ids\`, \`--mock\`, and the rest), progress callbacks, code-change loading, the stderr summary, stdout JSON, and \`BITFAB_REPLAY_RESULT_PATH\`. The registry never invokes a replay runner and never parses, forwards, or prints any of that. The one exception is Go, whose registry command ends by passing \`os.Args[1:]\` to \`bitfab.RunReplayCLI\`, which then owns all of it. The non-negotiables are:
37683
+ {{registryPlacementRules}}
37684
+ - **Register the production root itself, with the app's own client.** For a decorated root, register the decorated function directly: its trace function key comes from the decorator, and a plain closure around it (for example \`(x) => fn(x)\`) carries no key and nests a duplicate root. For a TypeScript decorated method, register \`instance.method.bind(instance)\`, which keeps its key. For Python class methods, register \`Class.method\` or a bound \`instance.method\`; for Ruby, the production \`receiver\` and \`method_name\`; for Go, the production function or method value with \`TraceFunctionKey\`, since a plain Go function carries no key. Import the \`Bitfab\` client the instrumentation uses; never construct a second one. Never register a stub or identity function; reshape old inputs with the entry's input adapter instead.
37659
37685
  - **Replay root parity (hard rule):** for keys with a decorated or manually wrapped root function, the function stored in the registry must be the exact same exported top-level traced wrapper that production/runtime calls to create the root span. You must do this unless it is genuinely impossible in the host app; inconvenience, extra refactoring, an inline wrapper, or needing to move code is not impossible. If production creates that wrapper inline inside a route, job, handler, callback, or local file scope, extract it into the nearest appropriate service/module, export it, and update both production and replay to import and call that same symbol. Do not replay a convenient inner helper unless that exact helper is also the production root traced wrapper. Avoid duplicate semantic wrappers split across production and replay with names like \`runX\`, \`processX\`, or \`generateX\`. For handler-instrumented keys with explicit-key replay, verify parity against the production keyed handler/run-wrapper entrypoint that re-invokes the same framework entrypoint production calls. If exported-symbol parity is impossible, stop and document the concrete blocker.
37660
37686
  - **Replay root parity verification:** when reporting replay setup completion, include the required final verification section: \`Replay root parity:\`, \`Production root symbol:\`, \`Production import/path:\`, \`Replay symbol:\`, \`Replay import/path:\`, \`Same symbol? yes/no\`, and \`If no, why is this impossible?\`.
37661
- - **Use the same \`Bitfab\` client across instrumentation and replay.** Import it from the instrumented module or a shared singleton; never construct a second client inside the registry module.
37662
- - Register every pipeline name with the same client and exact production function/method. Decorated roots supply their trace function key automatically; plain handler roots declare it on the registry entry.
37663
- - The SDK-installed \`bitfab-replay\` executable supplies \`--limit\`, \`--trace-ids\`, \`--name\`, \`--concurrency\`, \`--code-change\`, \`--experiment-group-id\`, \`--dataset-ids\` (and its \`--dataset-id\` spelling), \`--grader-ids\`, and \`--mock\`. Never parse or forward these in the registry module.
37664
- - Put only function-specific defaults such as \`adaptInputs\` / \`adapt_inputs\`, mock overrides, or database snapshots on the registry entry.
37665
- - **Each registry entry MUST reference the actual instrumented function** (for handler-instrumented keys: a callable that re-invokes the actual framework entrypoint), never a stub or identity function. If historical inputs need reshaping, use the registry entry's input adapter.
37666
- - **Load the app normally.** The registry module imports app code as a library, and the executable loads that module. Use the project's normal env loader around \`bitfab-replay\` when needed and keep module-scoped clients, config, and models wired as the app expects. This is for dependency resolution and fidelity, not safety.
37687
+ - **Handler-instrumented keys (no decorated function in the app) register an explicit key.** When a key is recorded only via a framework handler ({{keyedHandlerKeyRefs}}), register the plain callable that re-invokes the same production framework entrypoint, plus the key explicitly (TypeScript \`traceFunctionKey\`; Python/Ruby \`trace_function_key\`). The callable receives the recorded root input and reconstructs only the runtime wiring the production entrypoint needs. Every unsafe production action reached through that wiring must remain behind a replay-mockable marked span. Use a no-op only for a genuinely replay-only callback slot with no production action and no recorded call to mock.
37688
+ - **Load the app normally, through its own wiring.** The registry imports app code as a library, with the project's normal env loader and the module-scoped clients, config, and models the app expects. When production builds the agent and its tools in a factory at startup, call that same factory once in the registry and register the traced function it returns. Never hand-build a smaller toolset or a replay-only agent.
37667
37689
  - **Handler wiring safety:** synthesize only genuinely replay-only slots with no production action and no recorded call to mock. Every production billing, notification, write, or other unsafe callback must retain its real wiring behind a selected replay-mockable marked span. For factory-created instrumented functions (taking session or stream writers via closure), the wrapper may pass:
37668
37690
  - Stream/socket writers: no-op (\`{ write: () => {}, merge: () => {} }\`), no client on the other end
37669
37691
  - Session/request identifiers: minimal stub with the fields the function reads
37670
- - **Caveat: watch for module-level import side effects.** Loading the registry transitively runs the app's module initialization before replay interception exists. If that opens listeners, binds ports, or performs unsafe external actions, stop and move those actions behind a replay-mockable boundary.
37671
- - The SDK executable owns the Replay Output Contract, including plugin progress, stderr summary, stdout JSON, and \`BITFAB_REPLAY_RESULT_PATH\`; do not duplicate any of it.
37672
- - Live in a \`scripts/\` directory (or the project's existing scripts location)`,
37692
+ - **Caveat: watch for module-level import side effects.** Loading the registry transitively runs the app's module initialization before replay interception exists. If that opens listeners, binds ports, or performs unsafe external actions, stop and move those actions behind a replay-mockable boundary.`,
37673
37693
  next: "replay/safety-net"
37674
37694
  },
37675
37695
  {
@@ -37678,7 +37698,7 @@ The SDK-installed \`bitfab-replay\` command lets the team regression-test any re
37678
37698
  toolCalls: ["ask", "edit"],
37679
37699
  refs: ["refactor-confirmation"],
37680
37700
  title: "Legacy instrumentation with a non-replayable root",
37681
- body: `**Legacy instrumentation with a non-replayable root.** First decide whether any instrumented trace function can't be replayed from the replay registry module. Two failure modes: **(1) not invocable**, the function isn't exported or is defined inline in a route handler; **(2) not replayable**, its root takes unserializable inputs (live SDK/DB clients, HTTP \`Request\`/\`Response\`, stream writers, sockets, opaque request contexts), so even an invocable call replays with empty or stubbed args. Such functions were introduced before Instrument's trace-boundary serializability requirement, or via another path. Reason from each function's signature and visibility, and where a captured trace exists for the key, compare the signature against the trace data: an empty or \`<unserializable: ...>\`-stubbed recorded root input confirms the root isn't replayable. Do not execute replay to detect this.
37701
+ body: `**Legacy instrumentation with a non-replayable root.** First decide whether any instrumented trace function can't be replayed from the replay registry module. Two failure modes: **(1) not invocable**, the function isn't exported or is defined inline in a route handler; **(2) not replayable**, its root takes unserializable inputs (live SDK/DB clients, HTTP \`Request\`/\`Response\`, stream writers, sockets, opaque request contexts), so even an invocable call replays with empty or stubbed args. Such functions were introduced before Instrument's trace-boundary serializability requirement, or via another path. Reason from each function's signature and visibility, and where a captured trace exists for the key, compare the signature against the trace data: an empty or \`<unserializable: ...>\`-stubbed recorded root input confirms the root isn't replayable. Do not execute replay to detect this. **A root whose only live arguments are objects the app builds from its own code (tools with their functions, clients, callbacks) is replayable, not a failure:** the recording keeps the rest of its input, and the registry entry rebuilds those objects in its input adapter with the same code production uses (see the create step). Treat it as replayable once the entry does that.
37682
37702
 
37683
37703
  **Keyed root-handler keys are not affected.** A key registered only via a callback handler or a trace-processor run wrapper ({{replayableRootHandlerNames}}) has no decorated function by design and records the framework's serializable input as the root; create its pipeline with the key-based replay pattern from step {{step:replay/create-scripts}} instead of offering these resolutions. **Bare trace-processor-only keys ({{traceProcessorNames}} over plain \`run()\`) ARE affected, not exempt:** the processor records an empty-input root, so a processor-only key without the run wrapper or an application root is not replayable. Offer "add a \`withTrace\`/\`trace\` root that takes the run input, or route the run through the run wrapper" in supported subtree runtimes; offer a manual span root only when opt-out is technically unavailable.
37684
37704
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bitfab-cli",
3
- "version": "0.2.414",
3
+ "version": "0.2.416",
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",