bitfab-cli 0.2.517 → 0.2.519

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 +17 -10
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -28956,7 +28956,6 @@ var spanFieldSchema = external_exports.enum([
28956
28956
  ]);
28957
28957
  var GET_TRACE_ASSERTIONS_MAX_IDS = 100;
28958
28958
  var MAX_ASSERTIONS_PER_REQUEST = 50;
28959
- var MAX_CODE_DRAFTS_PER_SAVE = 10;
28960
28959
  var MAX_ASSIGNEE_EMAIL_LENGTH = 320;
28961
28960
  var GET_GRADER_VERDICTS_MAX_IDS = 100;
28962
28961
  var DEFAULT_GRADER_VERDICT_LIMIT = 50;
@@ -29200,11 +29199,10 @@ var assertionTargetShape = external_exports.discriminatedUnion("kind", [
29200
29199
  ]).optional().describe('Which call to check when the trace runs that span more than once, e.g. a retry loop. "first", "last" (the default), or a 0-based index. Leave it off unless the repetition matters.')
29201
29200
  }).describe("Check one span by name rather than the whole trace, e.g. that a particular tool call was made with the right arguments.")
29202
29201
  ]).describe('SCOPE: what part of the trace under evaluation this assertion is checked against. OMIT IT for the whole trace, which is the common case and the right default when unsure. On an edit, omitting it keeps the current scope, and passing null returns the assertion to the whole trace. Pass { "kind": "output" } to check only the final output, or { "kind": "span", "name": "..." } to check one span. Scoping narrows what a judge looks at, so a wrong scope hides real failures. A target naming something the evaluated trace does not contain makes the check ERRORED, never passed, because a check that could not run must never look like a check that succeeded.');
29203
- var assertionKindShape = external_exports.enum(["judge", "code", "hybrid"]).describe(`KIND: who decides this assertion on a replay. "judge" (the default): the LLM judge reads the run. "code": the code below decides every replay by itself, and never returns "defer". "hybrid": the code decides what a program can read and returns "defer" to hand the rest to the LLM judge. Send "code" or "hybrid" with code to write the code yourself. To have Bitfab write it, send "code" or "hybrid" with no code, on a new assertion or one that has no code yet: before this call returns, Bitfab checks the wording against the writing rules (unless guidedRewrite is false), writes code of the kind you asked for, and runs it on this trace. The response says whether it wrote working code; when it could not, the assertion is saved without code and the LLM judge decides it. At most ${MAX_CODE_DRAFTS_PER_SAVE} assertions per call can ask Bitfab for code. On an edit, omit it to keep the current kind, and pass "judge" to remove the code.`);
29204
29202
  var assertionCodeShape = external_exports.object({
29205
- source: external_exports.string().trim().min(1).max(2e4).describe('Body of an async TypeScript function (plain JavaScript also works) called with `spans` (every span of the run in start order, each { name, index, hasData } without its data), `input`, and `output` (the run\'s root input and output). Read span data with `await named("span name")`, which returns the spans with that name with { name, index, input, output, metadata }, or `await span.data()`. Count or order spans from `spans` without loading data. It returns "pass", "fail", or "defer", or { result, reason } with a short reason. Only a hybrid assertion returns "defer": when the part the code can read holds and the rest needs reading what text means, so the LLM judge decides it. Copy ids, recipients, and times from the trace as literals, never match the wording of prose, and guard every read so it never throws on a missing field. It runs in a sandbox with no network, files, or timers, gets one second of compute, and may load the data of at most 50 spans within ten seconds.'),
29203
+ source: external_exports.string().trim().min(1).max(2e4).describe('Body of an async TypeScript function (plain JavaScript also works) called with `spans` (every span of the run in start order, each { name, index, hasData } without its data), `input`, and `output` (the run\'s root input and output). Read span data with `await named("span name")`, which returns the spans with that name with { name, index, input, output, metadata }, or `await span.data()`. Count or order spans from `spans` without loading data. It returns "pass", "fail", or "defer", or { result, reason } with a short reason. Return "pass" or "fail" when the facts the code read settle the assertion, and "defer" to hand the run to the LLM judge, for example when the part the code can read holds and the rest needs reading what text means. A defer may carry data, { result: "defer", reason, data }, with the values the code found that the judge needs to decide, such as the sent email\'s subject and body; the judge reads the reason and data alongside the run. A thrown error counts as "defer" with no data. Copy ids, recipients, and times from the trace as literals, never match the wording of prose, and guard every read so it never throws on a missing field. It runs in a sandbox with no network, files, or timers, gets one second of compute, and may load the data of at most 50 spans within ten seconds.'),
29206
29204
  spanNames: external_exports.array(external_exports.string().min(1)).max(50).describe("Every span name the code expects a correct run to produce. Leave out names it only checks did not run. When one of these is missing from a replay and from the other replays sampled for the same function, the code is reported as broken rather than failing the replay.")
29207
- }).describe(`CODE: decides this assertion's verdict from the trace's spans instead of the LLM judge, so replays it decides cost no judge call and give the same verdict every time. Write it only when facts a program reads settle the claim, or a necessary part of it: which spans ran and how often, argument and output values, ordering, or an exact literal in a message. Leave it off when deciding needs reading meaning. Bitfab may draft it itself after saving. The code is run on this trace before it is saved, and refused with the reason when it throws, times out, returns anything else, or returns "defer" for a "code" assertion. On an edit, omit it to keep the current code.`);
29205
+ }).describe(`CODE: optional. Passes or fails this assertion from the trace's spans where it can, and defers the rest to the LLM judge, so replays it decides cost no judge call and give the same verdict every time. Write it only when facts a program reads settle the claim, or a necessary part of it: which spans ran and how often, argument and output values, ordering, or an exact literal in a message. Leave it off when deciding needs reading meaning throughout. Bitfab decides whether an assertion should have code, and drafts it, after saving one without code. The code is run on this trace before it is saved, and refused with the reason when it throws, times out, or returns anything other than "pass", "fail", or "defer". On an edit, omit it to keep the current code, and pass null to remove it.`);
29208
29206
  var justificationShape = external_exports.preprocess(parseJsonString, external_exports.array(external_exports.object({
29209
29207
  spanId: external_exports.uuid().describe("The span this reason comes from, taken from the `[ID: ...]` shown for that span in get_traces output."),
29210
29208
  text: external_exports.string().trim().min(1).max(1e4).describe("What that span shows, in one or two sentences.")
@@ -29272,10 +29270,19 @@ var generateTraceAssertions = {
29272
29270
  regenerate: external_exports.preprocess(parseJsonString, external_exports.boolean()).optional().describe("Set true to rerun generation and replace prior generated drafts. Omit or set false to reuse the existing generation result.")
29273
29271
  }
29274
29272
  };
29273
+ var regenerateAssertion = {
29274
+ name: "regenerate_assertion",
29275
+ title: "Regenerate Assertion",
29276
+ description: "Have Bitfab write one existing assertion again, and save the new wording in place of the old. Call this when the user names one assertion that is wrong, vague, or checks the wrong thing and wants Bitfab to write it again, optionally saying how with guidance. Pass only the assertion's id: Bitfab finds the trace it belongs to, reads that trace's input, what the recorded run did, the spans the assertion's justification cites, and the trace's other assertions, then writes a new claim with its pass and fail criteria. The assertion keeps its id, trace, category, assignee, human note, and justification. Everything else is saved as if it were a new assertion: the wording and criteria are replaced, and it is saved without code, so any code it had is dropped, along with the span it was limited to and every verdict given on the old wording. It always goes back to awaiting review, even when it was approved or rejected, so it is not checked on replays until a person approves it again, in Bitfab or with save_trace_assertions `approvalState`. After this call returns, Bitfab decides whether code can check the new wording and writes that code, the same as for any new assertion. The response names the trace and gives the new assertion and criteria, the old wording, and what changed. To replace every generated draft on a trace, use generate_trace_assertions with regenerate. To write the new wording yourself, use save_trace_assertions. An archived assertion is refused.",
29277
+ inputSchema: {
29278
+ assertionId: external_exports.uuid().describe("The assertion to write again, from get_trace_assertions or list_trace_assertions. It must be an active assertion in this organization."),
29279
+ guidance: external_exports.string().trim().min(1).max(1e4).optional().describe("Optional instruction for the new wording, such as what the current assertion gets wrong, what it should check instead, or a root cause analysis of why the trace went wrong. Omit to have Bitfab check the same behavior and write it better.")
29280
+ }
29281
+ };
29275
29282
  var saveTraceAssertions = {
29276
29283
  name: "save_trace_assertions",
29277
29284
  title: "Save Trace Assertions",
29278
- description: `Record what SHOULD happen when this trace is replayed. Bitfab stores two kinds of record on a trace. A VERDICT says how a run that already happened turned out, and that is save_agent_verdicts / save_human_verdicts. An ASSERTION, which is what this tool writes, says what a correct run looks like for THIS specific input, carries no pass/fail of its own, and is checked against a later replay once a reviewer approves it. A trace holds any number of assertions, and each verdict is recorded on one of them. Call it when the user describes the right answer for a particular case, for example "this booking should have picked the 6am flight, not the 9am". This is not a verdict on a run that already happened, which is save_agent_verdicts, and it is not a check that applies to every trace of a function, which is save_grader. Pass \`assertion\` plus optional \`passCriteria\` / \`failCriteria\`, the same trio save_grader takes, so an assertion that proves out across many traces can later be promoted into a grader with no rewriting. \`humanNote\` stores people-only context on the assertion; preserve and return it, but never use it to judge whether a replay passed. \`assigneeEmail\` names the member who should review it, which routes the assertion to that person without deciding anything, so it never changes the approval state. Pass an entry's \`id\` to edit an existing assertion, or omit it to add a new one, so two callers adding different assertions to one trace never overwrite each other. What this tool writes is saved awaiting review, so nothing checks it yet; a reviewer approves it, in Bitfab or with \`approvalState\` on a later call here, and from then on every replay of the trace is judged against it. \`approvalState\` decides an assertion that already exists, so deciding one is \`{ id, approvalState }\` with nothing else: an omitted \`assertion\` keeps the current wording. It is refused on a new assertion, so the call that invents a claim is never the call that puts it into force. One decision covers the assertion and the category it is filed under, so set \`category_id\` and \`approvalState\` in the same entry when you are deciding both; recategorizing on a later call without deciding returns it to not reviewed, since the approval covered the old category. What it gates is whether replays check the assertion at all, so decide from the assertion and the spans it cites rather than from memory of having written it. Rewording an assertion, or changing its criteria, target, or category, returns it to not reviewed unless the same call says otherwise. Call get_trace_assertions first to find the assertion to edit and to avoid creating a duplicate, and read them back before judging a replay, where it lists the approved ones by default. Pass it \`approvalStates: ["pending"]\` to read back drafts awaiting review, including the ones you just wrote. Each assertion with new text is checked against the writing rules and rewritten when it breaks one, unless \`guidedRewrite\` is false, so read the response for what was saved and for any claim to save separately. To make an assertion a code assertion without writing the code, send \`kind\` "code" or "hybrid" with no \`code\`: Bitfab rewrites the wording and writes and runs the code before this call returns, keeping the kind you asked for, and says in the response when it could not write working code. Up to ${MAX_ASSERTIONS_PER_REQUEST} per call.`,
29285
+ description: `Record what SHOULD happen when this trace is replayed. Bitfab stores two kinds of record on a trace. A VERDICT says how a run that already happened turned out, and that is save_agent_verdicts / save_human_verdicts. An ASSERTION, which is what this tool writes, says what a correct run looks like for THIS specific input, carries no pass/fail of its own, and is checked against a later replay once a reviewer approves it. A trace holds any number of assertions, and each verdict is recorded on one of them. Call it when the user describes the right answer for a particular case, for example "this booking should have picked the 6am flight, not the 9am". This is not a verdict on a run that already happened, which is save_agent_verdicts, and it is not a check that applies to every trace of a function, which is save_grader. Pass \`assertion\` plus optional \`passCriteria\` / \`failCriteria\`, the same trio save_grader takes, so an assertion that proves out across many traces can later be promoted into a grader with no rewriting. \`humanNote\` stores people-only context on the assertion; preserve and return it, but never use it to judge whether a replay passed. \`assigneeEmail\` names the member who should review it, which routes the assertion to that person without deciding anything, so it never changes the approval state. Pass an entry's \`id\` to edit an existing assertion, or omit it to add a new one, so two callers adding different assertions to one trace never overwrite each other. What this tool writes is saved awaiting review, so nothing checks it yet; a reviewer approves it, in Bitfab or with \`approvalState\` on a later call here, and from then on every replay of the trace is judged against it. \`approvalState\` decides an assertion that already exists, so deciding one is \`{ id, approvalState }\` with nothing else: an omitted \`assertion\` keeps the current wording. It is refused on a new assertion, so the call that invents a claim is never the call that puts it into force. One decision covers the assertion and the category it is filed under, so set \`category_id\` and \`approvalState\` in the same entry when you are deciding both; recategorizing on a later call without deciding returns it to not reviewed, since the approval covered the old category. What it gates is whether replays check the assertion at all, so decide from the assertion and the spans it cites rather than from memory of having written it. Rewording an assertion, or changing its criteria, target, or category, returns it to not reviewed unless the same call says otherwise. Call get_trace_assertions first to find the assertion to edit and to avoid creating a duplicate, and read them back before judging a replay, where it lists the approved ones by default. Pass it \`approvalStates: ["pending"]\` to read back drafts awaiting review, including the ones you just wrote. Each assertion with new text is checked against the writing rules and rewritten when it breaks one, unless \`guidedRewrite\` is false, so read the response for what was saved and for any claim to save separately. Up to ${MAX_ASSERTIONS_PER_REQUEST} per call.`,
29279
29286
  inputSchema: {
29280
29287
  traceId: external_exports.uuid().describe("The ORIGINAL trace to attach assertions to. A replay trace id is refused, and the error names the original to retry with, because a replay reads its original's assertions automatically."),
29281
29288
  assertions: external_exports.preprocess(parseJsonString, external_exports.array(external_exports.object({
@@ -29287,7 +29294,6 @@ var saveTraceAssertions = {
29287
29294
  passCriteria: external_exports.string().optional().describe("How a judge should recognise a pass, when the assertion alone leaves room to argue, e.g. 'arrival timestamp is strictly before 09:00 in the destination timezone'. Optional, and only worth writing when it removes real ambiguity. Same field save_grader takes, so an assertion that proves out across many traces is promoted into a grader by copying it. On an edit, omit to keep the current value and pass an empty string to clear it."),
29288
29295
  failCriteria: external_exports.string().optional().describe("How a judge should recognise a failure, for cases the pass criteria do not obviously exclude, e.g. 'any leg departing after 09:00, including connections'. Optional. On an edit, omit to keep the current value and pass an empty string to clear it."),
29289
29296
  targetOnEvaluatedTrace: assertionTargetShape.nullish(),
29290
- kind: assertionKindShape.nullish(),
29291
29297
  code: assertionCodeShape.nullish(),
29292
29298
  justification: justificationShape.nullish().describe("Why this assertion is right for THIS trace, cited span by span: the spans that show what the run actually did, each with its own reason. Omit on an edit to preserve it, or pass null to remove it. It is the evidence behind `approvalState`, so an assertion with no justification is one a reviewer has to reconstruct from scratch. Cite spans on this trace only."),
29293
29299
  categoryJustification: justificationShape.nullish().describe("Why `category_id` is the right category for this assertion, cited span by span. Omit on an edit to preserve it, or pass null to remove it. Changing the category clears it, since it justified the old one. Cite spans on this trace only."),
@@ -29739,6 +29745,7 @@ var ALL_TOOL_CONTRACTS = [
29739
29745
  getAssertionCategory,
29740
29746
  deleteAssertionCategory,
29741
29747
  generateTraceAssertions,
29748
+ regenerateAssertion,
29742
29749
  saveTraceAssertions,
29743
29750
  getTraceAssertions,
29744
29751
  listTraceAssertions,
@@ -31135,10 +31142,10 @@ var semver2 = __toESM(require_semver2(), 1);
31135
31142
 
31136
31143
  // ../bitfab-plugin-lib/dist/bakedSdkVersions.js
31137
31144
  var BAKED_SDK_VERSIONS = {
31138
- typescript: "0.76.3",
31139
- python: "0.76.2",
31140
- ruby: "0.75.2",
31141
- go: "0.75.2"
31145
+ typescript: "0.76.4",
31146
+ python: "0.76.3",
31147
+ ruby: "0.75.3",
31148
+ go: "0.75.3"
31142
31149
  };
31143
31150
 
31144
31151
  // ../bitfab-plugin-lib/dist/installedSdk.js
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bitfab-cli",
3
- "version": "0.2.517",
3
+ "version": "0.2.519",
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",