bitfab-cli 0.2.363 → 0.2.365

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 +28 -12
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -23537,11 +23537,20 @@ var getTraces = {
23537
23537
  var getTraceLabels = {
23538
23538
  name: "get_trace_labels",
23539
23539
  title: "Get Trace Labels",
23540
- description: `Read just the labels for one or more traces by ID: returns each trace's pass/fail verdict, its annotation (the reviewer's reasoning), and whether the label is human-validated (a human authored or approved it). Per-assertion verdicts follow on indented lines, one per assertion, keyed by the assertionId the write used, each with its own verdict, annotation, confidence, and author, so a verdict written per assertion reads back per assertion rather than as a tally. No span content, inputs, or outputs are loaded, so the response is small and one call accepts up to ${GET_TRACE_LABELS_MAX_IDS} IDs. Use this to load a whole dataset's verdicts into context in a single call (e.g. when building or confirming a dataset). When you need a trace's actual inputs/outputs/spans, use get_traces instead. This returns verdicts on runs that already happened; for what a trace SHOULD do on its next replay, use get_trace_assertions.`,
23540
+ description: `Read just the labels for one or more traces by ID: returns each trace's pass/fail verdict, its annotation (the reviewer's reasoning), its saved { spanId, text } evidence, and whether the label is human-validated (a human authored or approved it). Per-assertion verdicts follow on indented lines, one per assertion, keyed by the assertionId the write used, each with its own verdict, annotation, evidence, confidence, and author, so a verdict written per assertion reads back per assertion rather than as a tally. No span content, inputs, or outputs are loaded, so the response is small and one call accepts up to ${GET_TRACE_LABELS_MAX_IDS} IDs. Use this to load a whole dataset's verdicts into context in a single call (e.g. when building or confirming a dataset). When you need a trace's actual inputs/outputs/spans, use get_traces instead. This returns verdicts on runs that already happened; for what a trace SHOULD do on its next replay, use get_trace_assertions.`,
23541
23541
  inputSchema: {
23542
23542
  traceIds: external_exports.preprocess(parseJsonString, external_exports.array(external_exports.uuid()).min(1).max(GET_TRACE_LABELS_MAX_IDS)).describe(`Trace IDs to read labels for (1-${GET_TRACE_LABELS_MAX_IDS})`)
23543
23543
  }
23544
23544
  };
23545
+ var getLabelEvidence = {
23546
+ name: "get_label_evidence",
23547
+ title: "Get Label Evidence",
23548
+ description: "Suggest span-by-span evidence that could support a label on a trace or one of its assertions. This discovery API is currently stubbed and returns an empty evidence list. Saved evidence is read with get_trace_labels instead.",
23549
+ inputSchema: {
23550
+ traceId: external_exports.uuid().describe("The trace whose spans could provide evidence"),
23551
+ assertionId: external_exports.uuid().optional().describe("The assertion the potential evidence would support. Omit it for the whole-trace label.")
23552
+ }
23553
+ };
23545
23554
  var getSpanField = {
23546
23555
  name: "get_span_field",
23547
23556
  title: "Get Span Field",
@@ -23553,10 +23562,14 @@ var getSpanField = {
23553
23562
  maxChars: external_exports.preprocess(parseJsonString, external_exports.number().int().positive()).optional().describe("Maximum characters to return (default 100000). Raise it to read further into an extremely large field.")
23554
23563
  }
23555
23564
  };
23565
+ var labelEvidenceShape = external_exports.preprocess(parseJsonString, external_exports.array(external_exports.object({
23566
+ spanId: external_exports.uuid(),
23567
+ text: external_exports.string().trim().min(1).max(1e4)
23568
+ })).min(1).max(50));
23556
23569
  var saveAgentLabels = {
23557
23570
  name: "save_agent_labels",
23558
23571
  title: "Save Agent Labels",
23559
- description: "Set, skip, or archive the agent's pass/fail verdict on one or more traces (`labelSource=\"agent\"`). Use this AFTER you have read the traces with get_traces and decided yourself whether each one looks like a pass, a fail, or genuinely cannot be judged. To set a verdict, pass `label` (true=PASS, false=FAIL) and `annotation` (your reasoning, shown to the human reviewer in the labeling UI). Optionally pass `confidence` (`VeryLow|Low|Medium|High|VeryHigh`) to record how confident you are - surfaced in the labeling UI so reviewers can prioritize low-confidence verdicts. To explicitly skip a trace you cannot decide on (instead of leaving it unlabeled), pass `skip: true` and omit label/annotation - this records an explicit skip so coverage checks know you intentionally did not verdict it. To clear a previously-set agent verdict (e.g., you changed your mind or labeled the wrong trace), pass `archive: true` and omit label/annotation. New verdicts start unapproved (`approvedAt=null`); once a human approves one, it joins the validated dataset (queryable via `search_traces` with `validated: true`). Archiving is non-destructive - the row is hidden from all reads but kept for audit, and you can immediately re-label the trace from scratch. For replay results, key each label by the replay item's `originalTraceId` (the original trace it was replayed from; `sourceTraceId` is accepted as a deprecated alias) plus the top-level `testRunId` instead of a `traceId`: the server resolves it to the replay trace via lineage, so you never need a server-generated replay trace id. When the experiment ran each trace more than once, also pass the item's `attempt` so each attempt gets its own verdict. Returns an agent-readable summary with one parseable effective label line per updated trace, keyed by the id you supplied (`originalTraceId` for replay verdicts, otherwise `traceId`), so command callers can verify persistence. Before judging a replay, call get_trace_assertions on the original trace ids: an assertion says what the user asked this specific case to do, so the verdict is measured against that rather than a guess. When an assertion's target cannot be found on the trace you are judging, the check never ran, so pass `skip: true` for that trace rather than recording a FAIL. Pass `assertionId` to score ONE assertion on the trace (the `[ID: ...]` get_trace_assertions prints), one entry per assertion, all in the same call. Omit it for the trace's single whole-trace verdict. get_trace_labels reads these back one line per assertion, keyed by the same assertionId, so a per-assertion write is verifiable per assertion.",
23572
+ description: "Set, skip, or archive the agent's pass/fail verdict on one or more traces (`labelSource=\"agent\"`). Use this AFTER you have read the traces with get_traces and decided yourself whether each one looks like a pass, a fail, or genuinely cannot be judged. To set a verdict, pass `label` (true=PASS, false=FAIL) and `annotation` (your reasoning, shown to the human reviewer in the labeling UI). Add `evidence` as `{ spanId, text }` entries to ground that reasoning in spans on the evaluated trace. Optionally pass `confidence` (`VeryLow|Low|Medium|High|VeryHigh`) to record how confident you are - surfaced in the labeling UI so reviewers can prioritize low-confidence verdicts. To explicitly skip a trace you cannot decide on (instead of leaving it unlabeled), pass `skip: true` and omit label/annotation - this records an explicit skip so coverage checks know you intentionally did not verdict it. To clear a previously-set agent verdict (e.g., you changed your mind or labeled the wrong trace), pass `archive: true` and omit label/annotation. New verdicts start unapproved (`approvedAt=null`); once a human approves one, it joins the validated dataset (queryable via `search_traces` with `validated: true`). Archiving is non-destructive - the row is hidden from all reads but kept for audit, and you can immediately re-label the trace from scratch. For replay results, key each label by the replay item's `originalTraceId` (the original trace it was replayed from; `sourceTraceId` is accepted as a deprecated alias) plus the top-level `testRunId` instead of a `traceId`: the server resolves it to the replay trace via lineage, so you never need a server-generated replay trace id. When the experiment ran each trace more than once, also pass the item's `attempt` so each attempt gets its own verdict. Returns an agent-readable summary with one parseable effective label line per updated trace, keyed by the id you supplied (`originalTraceId` for replay verdicts, otherwise `traceId`), so command callers can verify persistence. Before judging a replay, call get_trace_assertions on the original trace ids: an assertion says what the user asked this specific case to do, so the verdict is measured against that rather than a guess. When an assertion's target cannot be found on the trace you are judging, the check never ran, so pass `skip: true` for that trace rather than recording a FAIL. Pass `assertionId` to score ONE assertion on the trace (the `[ID: ...]` get_trace_assertions prints), one entry per assertion, all in the same call. Omit it for the trace's single whole-trace verdict. get_trace_labels reads these back one line per assertion, keyed by the same assertionId, so a per-assertion write is verifiable per assertion.",
23560
23573
  inputSchema: {
23561
23574
  testRunId: external_exports.uuid().optional().describe("The replay test run id. Required when any label targets a trace by originalTraceId (replay verdicts); ignored otherwise."),
23562
23575
  labels: external_exports.preprocess(parseJsonString, external_exports.array(external_exports.object({
@@ -23569,21 +23582,23 @@ var saveAgentLabels = {
23569
23582
  skip: external_exports.boolean().optional().describe("If true, record an explicit skip (cannot judge) and ignore label/annotation/confidence. Default false."),
23570
23583
  label: external_exports.boolean().optional().describe("true for PASS, false for FAIL. Required when archive and skip are both false/omitted."),
23571
23584
  annotation: external_exports.string().min(1).optional().describe("Your reasoning for the verdict - shown to the human reviewer in the labeling UI. Required when archive and skip are both false/omitted."),
23572
- confidence: external_exports.enum(["VeryLow", "Low", "Medium", "High", "VeryHigh"]).optional().describe("How confident you are in this verdict: VeryLow / Low / Medium / High / VeryHigh. Surfaced as a chip in the labeling UI; low-confidence labels are prioritized for human review. Optional; only meaningful when paired with a label.")
23585
+ confidence: external_exports.enum(["VeryLow", "Low", "Medium", "High", "VeryHigh"]).optional().describe("How confident you are in this verdict: VeryLow / Low / Medium / High / VeryHigh. Surfaced as a chip in the labeling UI; low-confidence labels are prioritized for human review. Optional; only meaningful when paired with a label."),
23586
+ evidence: labelEvidenceShape.nullable().optional().describe("Span-by-span evidence for this verdict. Omit it to preserve existing evidence. Pass null to clear existing evidence.")
23573
23587
  })).min(1).max(200)).describe("One entry per assertion on traces that have assertions, otherwise one whole-trace entry (1-200)")
23574
23588
  }
23575
23589
  };
23576
23590
  var saveHumanLabels = {
23577
23591
  name: "save_human_labels",
23578
23592
  title: "Save Human Labels",
23579
- description: "Record one or more human-authored pass/fail verdicts that are VALIDATED immediately (`labelSource=\"human\"`, no approval step). Unlike save_agent_labels (which writes agent suggestions that start unapproved), labels set here join the validated dataset the instant they are written and satisfy `search_traces` with `validated: true`. Pass `label` (true=PASS, false=FAIL), `annotation` (the reasoning behind the verdict), and optionally `confidence` (`VeryLow|Low|Medium|High|VeryHigh`). USE ONLY when a human has explicitly decided the verdict, for example saving a known production bug as a test case. This records a verdict on a run that already happened; to record what a trace should do on its next replay, use save_trace_assertions. Do NOT use this for the agent's own first-pass guesses on traces awaiting human review; use save_agent_labels for those so they go through the normal approve/edit loop. Pass `assertionId` when the human judged ONE assertion (the `[ID: ...]` get_trace_assertions prints), one entry per assertion. Omit it for the trace's single whole-trace verdict. get_trace_labels reads these back one line per assertion, keyed by the same assertionId, so a per-assertion write is verifiable per assertion.",
23593
+ description: "Record one or more human-authored pass/fail verdicts that are VALIDATED immediately (`labelSource=\"human\"`, no approval step). Unlike save_agent_labels (which writes agent suggestions that start unapproved), labels set here join the validated dataset the instant they are written and satisfy `search_traces` with `validated: true`. Pass `label` (true=PASS, false=FAIL), `annotation` (the reasoning behind the verdict), and optionally `evidence` as `{ spanId, text }` entries grounded in the evaluated trace. Optionally pass `confidence` (`VeryLow|Low|Medium|High|VeryHigh`). USE ONLY when a human has explicitly decided the verdict, for example saving a known production bug as a test case. This records a verdict on a run that already happened; to record what a trace should do on its next replay, use save_trace_assertions. Do NOT use this for the agent's own first-pass guesses on traces awaiting human review; use save_agent_labels for those so they go through the normal approve/edit loop. Pass `assertionId` when the human judged ONE assertion (the `[ID: ...]` get_trace_assertions prints), one entry per assertion. Omit it for the trace's single whole-trace verdict. get_trace_labels reads these back one line per assertion, keyed by the same assertionId, so a per-assertion write is verifiable per assertion.",
23580
23594
  inputSchema: {
23581
23595
  labels: external_exports.preprocess(parseJsonString, external_exports.array(external_exports.object({
23582
23596
  traceId: external_exports.uuid().describe("The trace ID to label"),
23583
23597
  assertionId: external_exports.uuid().optional().describe("The assertion this verdict scores, taken from the `[ID: ...]` get_trace_assertions prints. Omit it to set the trace's whole-trace verdict, of which there is one."),
23584
23598
  label: external_exports.boolean().describe("true for PASS, false for FAIL. Required."),
23585
23599
  annotation: external_exports.string().min(1).describe("The reasoning behind the verdict. Required."),
23586
- confidence: external_exports.enum(["VeryLow", "Low", "Medium", "High", "VeryHigh"]).optional().describe("How confident the verdict is: VeryLow / Low / Medium / High / VeryHigh. Optional.")
23600
+ confidence: external_exports.enum(["VeryLow", "Low", "Medium", "High", "VeryHigh"]).optional().describe("How confident the verdict is: VeryLow / Low / Medium / High / VeryHigh. Optional."),
23601
+ evidence: labelEvidenceShape.nullable().optional().describe("Span-by-span evidence for this verdict. Omit it to preserve existing evidence. Pass null to clear existing evidence.")
23587
23602
  })).min(1).max(200)).describe("One entry per assertion on traces that have assertions, otherwise one whole-trace entry (1-200)")
23588
23603
  }
23589
23604
  };
@@ -23950,6 +23965,7 @@ var ALL_TOOL_CONTRACTS = [
23950
23965
  searchTraces,
23951
23966
  getTraces,
23952
23967
  getTraceLabels,
23968
+ getLabelEvidence,
23953
23969
  getSpanField,
23954
23970
  saveAgentLabels,
23955
23971
  saveHumanLabels,
@@ -24581,10 +24597,10 @@ var semver3 = __toESM(require_semver2(), 1);
24581
24597
 
24582
24598
  // ../bitfab-plugin-lib/dist/bakedSdkVersions.js
24583
24599
  var BAKED_SDK_VERSIONS = {
24584
- typescript: "0.57.3",
24585
- python: "0.57.3",
24586
- ruby: "0.57.3",
24587
- go: "0.57.3"
24600
+ typescript: "0.57.4",
24601
+ python: "0.57.5",
24602
+ ruby: "0.57.4",
24603
+ go: "0.57.4"
24588
24604
  };
24589
24605
 
24590
24606
  // ../bitfab-plugin-lib/dist/installedSdk.js
@@ -29401,7 +29417,7 @@ Hold the chosen mode in working context, the next steps branch on it.
29401
29417
  body: `**Seed dataset from existing validated labels.** Reachable only when the user picked Option B in \`ask-search-mode\`. Pull traces that already have a validated label (human-authored, or agent-authored and human-approved) for this function, attach them to the picked dataset, and route on whether the user also wants to add more.
29402
29418
 
29403
29419
  1. Call {{tool:searchTraces}} with \`traceFunctionKey: <key>\`, \`validated: true\`, and a generous \`limit\` (50 is the cap). Both \`labelResult: true\` and \`labelResult: false\` matter, failures are the hill-climbing signal, but passes anchor the regression boundary. If 50 isn't enough to cover the function's labeled history, run a second call with \`labelResult: false\` only to bias toward fails first, then a third with \`labelResult: true\`. De-dupe trace IDs across calls.
29404
- 2. Call {{tool:getTraceLabels}} on the resulting trace IDs so the labels + annotations are in working context. Don't re-label them, these are already validated. {{tool:getTraceLabels}} returns only label + annotation + approved (no span content) and takes up to 100 IDs per call, so the deduped set from step 1 is usually a single call; if it deduped more than 100 IDs, split them into chunks of 100 and call {{tool:getTraceLabels}} once per chunk (sequential is fine, the responses are small).
29420
+ 2. Call {{tool:getTraceLabels}} on the resulting trace IDs so the labels, annotations, and saved evidence are in working context. Don't re-label them, these are already validated. {{tool:getTraceLabels}} returns only label + annotation + evidence + approved (no span content) and takes up to 100 IDs per call, so the deduped set from step 1 is usually a single call; if it deduped more than 100 IDs, split them into chunks of 100 and call {{tool:getTraceLabels}} once per chunk (sequential is fine, the responses are small).
29405
29421
  3. Call {{tool:addTracesToDataset}} once with \`datasetId\` (the one picked in \`list-datasets\`) and the full deduped trace ID array. The call is idempotent, so re-attaching IDs already in the dataset is a safe no-op.
29406
29422
  4. Briefly summarize for the user: "Seeded the dataset with N reused labels (M fails, K passes). Want me to find more candidates to label, or is this set enough to move on?"
29407
29423
 
@@ -29596,9 +29612,9 @@ Then return to the await-event step. If the user wants more edits, they'll ask a
29596
29612
  toolCalls: ["getTraceLabels", "bash", "read"],
29597
29613
  commandCalls: ["readTracesBatched"],
29598
29614
  title: "Build the dataset",
29599
- body: `**Build the dataset**: You already know the trace IDs in this dataset (you attached them in earlier steps and tracked any add/remove from modify rounds). Load each trace's label + annotation into context. **Which tool depends on \`costRun\`:**
29615
+ body: `**Build the dataset**: You already know the trace IDs in this dataset (you attached them in earlier steps and tracked any add/remove from modify rounds). Load each trace's label + annotation + evidence into context. **Which tool depends on \`costRun\`:**
29600
29616
 
29601
- - **\`costRun\` is false (the common case):** call {{tool:getTraceLabels}} with all of them. It returns only the verdict fields (label + annotation + approved, no span content) and takes up to 100 IDs per call, so for almost every dataset this is a single call. Only if the dataset has more than 100 traces, split the IDs into chunks of 100 and call {{tool:getTraceLabels}} once per chunk; the responses are small, so plain sequential calls are fine.
29617
+ - **\`costRun\` is false (the common case):** call {{tool:getTraceLabels}} with all of them. It returns only the verdict fields (label + annotation + evidence + approved, no span content) and takes up to 100 IDs per call, so for almost every dataset this is a single call. Only if the dataset has more than 100 traces, split the IDs into chunks of 100 and call {{tool:getTraceLabels}} once per chunk; the responses are small, so plain sequential calls are fine.
29602
29618
  - **\`costRun\` is set:** run \`{{command:readTracesBatched}} <trace-id...> --scope full\` **once** with all the trace IDs instead, because the Phase 5 cost-delta step reads each original trace's recorded token usage from this load and {{tool:getTraceLabels}} does not carry it. The command fans the \`scope: "full"\` reads out in parallel batches of 10 and writes the combined result to a temp file; it prints \`{"status":"ok","outputFile":"..."}\` as JSON, so \`Read\` that \`outputFile\`. **Use this command here, not the \`get_traces\` MCP tool directly:** \`get_traces\` caps at 10 IDs, so calling it for the dataset would re-introduce the serial per-batch fan-out \`readTracesBatched\` exists to replace.
29603
29619
 
29604
29620
  **Re-read them fresh here even if you read them earlier in this phase:** the Bitfab labeling review persists human approvals and label/annotation edits to the DB, so cached context from the find / label steps can be stale. This is the working set for confirm + every Phase 5 experiment.`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bitfab-cli",
3
- "version": "0.2.363",
3
+ "version": "0.2.365",
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",