bitfab 0.64.23 → 0.65.0
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.
- checksums.yaml +4 -4
- data/lib/bitfab/assertions.rb +53 -2
- data/lib/bitfab/{assertion_categories.rb → categories.rb} +6 -2
- data/lib/bitfab/client.rb +8 -2
- data/lib/bitfab/cloudReplay.py +3 -5
- data/lib/bitfab/labels.rb +12 -1
- data/lib/bitfab/scenarios.rb +8 -2
- data/lib/bitfab/version.rb +1 -1
- data/lib/bitfab.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: aa27d322488c12e530f14a5f85a7f9978208edf332ab91f7bf156f4ccb7b0b25
|
|
4
|
+
data.tar.gz: f8cadf7e8693aa155c254b7866b41f1781d5de4493dad8b0aad6643d285469a6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b274fec88de7c05f84977a60cc146290e89e2e8778fec9a498967304cc2c46a7cb65efa27f65210ec76ba1a2b58dbd3738e4f969d6ac126a9c3a87b25f80c30c
|
|
7
|
+
data.tar.gz: 8ddf0c559dc1dd33139497e18acf48a065017a59ea05b81e708ee9d3aa4a8eae1b202fb1b5243e7027131b27bcaedd5a2c3065df2fa964793c388609f199e3ad
|
data/lib/bitfab/assertions.rb
CHANGED
|
@@ -4,22 +4,39 @@ require "uri"
|
|
|
4
4
|
|
|
5
5
|
module Bitfab
|
|
6
6
|
class Traces
|
|
7
|
+
CATEGORY_ID_KEYS = ["category_id", :category_id].freeze
|
|
8
|
+
DEPRECATED_CATEGORY_ID_KEYS = ["category_assertion_id", :category_assertion_id].freeze
|
|
9
|
+
private_constant :CATEGORY_ID_KEYS, :DEPRECATED_CATEGORY_ID_KEYS
|
|
10
|
+
|
|
7
11
|
def initialize(http_client)
|
|
8
12
|
@http_client = http_client
|
|
9
13
|
end
|
|
10
14
|
|
|
15
|
+
# Each returned assertion carries "category_id" and, with the same value,
|
|
16
|
+
# the deprecated "category_assertion_id".
|
|
11
17
|
def get_assertions(trace_id)
|
|
12
|
-
@http_client.get(assertions_path(trace_id))
|
|
18
|
+
response = @http_client.get(assertions_path(trace_id))
|
|
19
|
+
return response unless response.is_a?(Hash) && response["assertions"].is_a?(Array)
|
|
20
|
+
|
|
21
|
+
response.merge("assertions" => response["assertions"].map { |assertion| with_both_category_keys(assertion) })
|
|
13
22
|
end
|
|
14
23
|
|
|
24
|
+
# Assertion hashes take "category_id": omit it to keep the assignment, or
|
|
25
|
+
# pass nil to clear it. The deprecated "category_assertion_id" is still
|
|
26
|
+
# accepted and sent as "category_id"; "category_id" wins when both are set.
|
|
15
27
|
def save_assertions(trace_id, assertions, source: "agent")
|
|
16
28
|
save_assertions_all([{"traceId" => trace_id, "assertions" => assertions}], source:)
|
|
17
29
|
end
|
|
18
30
|
|
|
31
|
+
# Same assertion hash keys as {#save_assertions}, for several traces at once.
|
|
19
32
|
def save_assertions_all(updates, source: "agent")
|
|
20
33
|
return [] if updates.empty?
|
|
21
34
|
|
|
22
|
-
@http_client.request(
|
|
35
|
+
saved = @http_client.request(
|
|
36
|
+
"/api/sdk/traces/assertions",
|
|
37
|
+
{"updates" => updates.map { |update| with_new_category_key(update) }, "source" => source}
|
|
38
|
+
)["assertions"]
|
|
39
|
+
saved.is_a?(Array) ? saved.map { |assertion| with_both_category_keys(assertion) } : saved
|
|
23
40
|
end
|
|
24
41
|
|
|
25
42
|
def archive_assertions(trace_id, assertion_ids)
|
|
@@ -31,5 +48,39 @@ module Bitfab
|
|
|
31
48
|
def assertions_path(trace_id, suffix = "")
|
|
32
49
|
"/api/sdk/traces/#{URI.encode_www_form_component(trace_id).gsub("+", "%20")}/assertions#{suffix}"
|
|
33
50
|
end
|
|
51
|
+
|
|
52
|
+
def with_new_category_key(update)
|
|
53
|
+
return update unless update.is_a?(Hash)
|
|
54
|
+
|
|
55
|
+
key = ["assertions", :assertions].find { |candidate| update[candidate].is_a?(Array) }
|
|
56
|
+
return update if key.nil?
|
|
57
|
+
|
|
58
|
+
update.merge(key => update[key].map { |assertion| rename_category_key(assertion) })
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def rename_category_key(assertion)
|
|
62
|
+
return assertion unless assertion.is_a?(Hash)
|
|
63
|
+
|
|
64
|
+
old_key = DEPRECATED_CATEGORY_ID_KEYS.find { |candidate| assertion.key?(candidate) }
|
|
65
|
+
return assertion if old_key.nil?
|
|
66
|
+
|
|
67
|
+
Bitfab.warn_once("category-assertion-id-deprecated",
|
|
68
|
+
"category_assertion_id is deprecated; use category_id instead.")
|
|
69
|
+
renamed = assertion.except(*DEPRECATED_CATEGORY_ID_KEYS)
|
|
70
|
+
renamed["category_id"] = assertion[old_key] unless CATEGORY_ID_KEYS.any? { |candidate| assertion.key?(candidate) }
|
|
71
|
+
renamed
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def with_both_category_keys(assertion)
|
|
75
|
+
return assertion unless assertion.is_a?(Hash)
|
|
76
|
+
|
|
77
|
+
if assertion.key?("category_id")
|
|
78
|
+
assertion.key?("category_assertion_id") ? assertion : assertion.merge("category_assertion_id" => assertion["category_id"])
|
|
79
|
+
elsif assertion.key?("category_assertion_id")
|
|
80
|
+
assertion.merge("category_id" => assertion["category_assertion_id"])
|
|
81
|
+
else
|
|
82
|
+
assertion
|
|
83
|
+
end
|
|
84
|
+
end
|
|
34
85
|
end
|
|
35
86
|
end
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
require "uri"
|
|
4
4
|
|
|
5
5
|
module Bitfab
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
# The organization's categories, which group assertions and scenarios.
|
|
7
|
+
class Categories
|
|
8
|
+
PATH = "/api/sdk/categories"
|
|
8
9
|
private_constant :PATH
|
|
9
10
|
|
|
10
11
|
def initialize(http_client)
|
|
@@ -36,4 +37,7 @@ module Bitfab
|
|
|
36
37
|
URI.encode_www_form_component(value).gsub("+", "%20")
|
|
37
38
|
end
|
|
38
39
|
end
|
|
40
|
+
|
|
41
|
+
# @deprecated Use {Categories}.
|
|
42
|
+
AssertionCategories = Categories
|
|
39
43
|
end
|
data/lib/bitfab/client.rb
CHANGED
|
@@ -37,7 +37,13 @@ module Bitfab
|
|
|
37
37
|
|
|
38
38
|
attr_reader :service_url
|
|
39
39
|
|
|
40
|
-
attr_reader :datasets, :
|
|
40
|
+
attr_reader :datasets, :categories, :organization_members, :traces, :spans, :labels, :graders, :experiments
|
|
41
|
+
|
|
42
|
+
# @deprecated Use {#categories}. Returns the same object.
|
|
43
|
+
def assertion_categories
|
|
44
|
+
Bitfab.warn_once("assertion-categories-deprecated", "assertion_categories is deprecated; use categories instead.")
|
|
45
|
+
@categories
|
|
46
|
+
end
|
|
41
47
|
|
|
42
48
|
def initialize(api_key: nil, service_url: nil, capture_enabled: nil, enabled: nil, strict: false, simulation_plan: true, timeout: 120, trace_across_threads: nil, env_vars: nil, baml_client: nil, db_snapshot: nil)
|
|
43
49
|
@db_snapshot = DbSnapshot.normalize_config(db_snapshot)
|
|
@@ -54,7 +60,7 @@ module Bitfab
|
|
|
54
60
|
@http_client = HttpClient.new(api_key: -> { resolve_api_key }, service_url: @service_url, timeout:)
|
|
55
61
|
@http_client.configure_simulation_plan(enabled: simulation_plan, start: !api_key_resolved_lazily?)
|
|
56
62
|
@datasets = Datasets.new(@http_client)
|
|
57
|
-
@
|
|
63
|
+
@categories = Categories.new(@http_client)
|
|
58
64
|
@organization_members = OrganizationMembers.new(@http_client)
|
|
59
65
|
@traces = Traces.new(@http_client)
|
|
60
66
|
@spans = Spans.new(@http_client)
|
data/lib/bitfab/cloudReplay.py
CHANGED
|
@@ -1896,7 +1896,7 @@ def check_out_snapshot_base(root, commit, branch):
|
|
|
1896
1896
|
base = git(root, "rev-parse", "--verify", "-q", f"{commit}^")
|
|
1897
1897
|
except CommandError:
|
|
1898
1898
|
print(
|
|
1899
|
-
"This checkout does not include the commit the snapshot was taken on, so the experiment records no code change; set fetch-depth: 2 on the workflow's
|
|
1899
|
+
"This checkout does not include the commit the snapshot was taken on, so the experiment records no code change and the snapshot commit instead of your branch; set fetch-depth: 2 on the workflow's checkout step, or run bitfab-replay --cloud-update",
|
|
1900
1900
|
flush=True,
|
|
1901
1901
|
)
|
|
1902
1902
|
return None
|
|
@@ -2900,7 +2900,7 @@ def raise_checkout_depth(lines, start, end):
|
|
|
2900
2900
|
def add_checkout_depth(lines):
|
|
2901
2901
|
for index, line in enumerate(lines):
|
|
2902
2902
|
match = re.match(
|
|
2903
|
-
r'([ \t]*)(- +)?"?uses"?[ \t]*:[ \t]*"?
|
|
2903
|
+
r'([ \t]*)(- +)?"?uses"?[ \t]*:[ \t]*"?[\w.-]+/checkout@',
|
|
2904
2904
|
without_yaml_comment(line),
|
|
2905
2905
|
)
|
|
2906
2906
|
if not match:
|
|
@@ -3063,9 +3063,7 @@ def update_workflow(root, path, *, remove_old_key_secrets=False):
|
|
|
3063
3063
|
"Checked out the commit each snapshot is taken on, so experiments record the code change"
|
|
3064
3064
|
)
|
|
3065
3065
|
elif depth == "by hand":
|
|
3066
|
-
by_hand.append(
|
|
3067
|
-
f"fetch-depth: {CHECKOUT_DEPTH} in the actions/checkout step's with"
|
|
3068
|
-
)
|
|
3066
|
+
by_hand.append(f"fetch-depth: {CHECKOUT_DEPTH} in the checkout step's with")
|
|
3069
3067
|
if updated:
|
|
3070
3068
|
target.write_text("\n".join(lines))
|
|
3071
3069
|
steps = []
|
data/lib/bitfab/labels.rb
CHANGED
|
@@ -44,6 +44,17 @@ module Bitfab
|
|
|
44
44
|
save_all([update], experiment_id:).first
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
+
# Records that the evidence does not show the part of the run this assertion checks, so there was
|
|
48
|
+
# nothing to judge. Counted as a fail in every pass rate, but stored and read back as an abstention,
|
|
49
|
+
# apart from a fail. +annotation:+ says what the evidence would have had to show.
|
|
50
|
+
def abstain(assertion_id:, trace_id: nil, original_trace_id: nil, attempt: nil, experiment_id: nil,
|
|
51
|
+
test_run_id: nil, annotation: nil)
|
|
52
|
+
experiment_id = Bitfab.resolve_experiment_id(experiment_id, test_run_id)
|
|
53
|
+
update = label_target(trace_id:, original_trace_id:, attempt:, assertion_id:).merge("abstain" => true)
|
|
54
|
+
update["annotation"] = annotation unless annotation.nil?
|
|
55
|
+
save_all([update], experiment_id:).first
|
|
56
|
+
end
|
|
57
|
+
|
|
47
58
|
def archive(trace_id: nil, original_trace_id: nil, attempt: nil, experiment_id: nil, assertion_id: nil, test_run_id: nil)
|
|
48
59
|
experiment_id = Bitfab.resolve_experiment_id(experiment_id, test_run_id)
|
|
49
60
|
update = label_target(trace_id:, original_trace_id:, attempt:, assertion_id:)
|
|
@@ -91,7 +102,7 @@ module Bitfab
|
|
|
91
102
|
|
|
92
103
|
targets = unscoped.map { |entry| entry_value(entry, "traceId") || entry_value(entry, "originalTraceId") }
|
|
93
104
|
raise ArgumentError, "Agent verdicts must name an assertion: #{targets.join(", ")}. " \
|
|
94
|
-
"Pass the assertion_id of the assertion each verdict scores to labels.save, save_all, and
|
|
105
|
+
"Pass the assertion_id of the assertion each verdict scores to labels.save, save_all, skip, and abstain. " \
|
|
95
106
|
"Only archive may omit it, to clear an old whole-trace verdict."
|
|
96
107
|
end
|
|
97
108
|
|
data/lib/bitfab/scenarios.rb
CHANGED
|
@@ -21,8 +21,13 @@ module Bitfab
|
|
|
21
21
|
# {"summary" => String, "actions" => [{"name", "details", "result", "failed", "at"}], "source" => Hash or nil}
|
|
22
22
|
# and replaces the saved value whole. Passing nil clears it. Leaving it out keeps it.
|
|
23
23
|
#
|
|
24
|
+
# category_ids: files the scenario under those categories and replaces its whole set of categories.
|
|
25
|
+
# Leave it out to keep the current set, and pass an empty array to clear it. The returned hash lists the
|
|
26
|
+
# scenario's categories under "categories", each {"id", "title", "description"}, sorted by title.
|
|
27
|
+
#
|
|
24
28
|
# Raises ArgumentError before any request when nothing is passed, or when data: and append_data: are both passed.
|
|
25
|
-
def save_scenario(trace_id, name: nil, description: nil, trigger: nil, data: nil, append_data: nil, actual_outcome: UNSET
|
|
29
|
+
def save_scenario(trace_id, name: nil, description: nil, trigger: nil, data: nil, append_data: nil, actual_outcome: UNSET,
|
|
30
|
+
category_ids: nil)
|
|
26
31
|
if !data.nil? && !append_data.nil?
|
|
27
32
|
raise ArgumentError, "Pass data or append_data, not both: data replaces the saved data whole."
|
|
28
33
|
end
|
|
@@ -34,8 +39,9 @@ module Bitfab
|
|
|
34
39
|
payload["data"] = data unless data.nil?
|
|
35
40
|
payload["appendData"] = append_data unless append_data.nil?
|
|
36
41
|
payload["actualOutcome"] = actual_outcome unless actual_outcome.equal?(UNSET)
|
|
42
|
+
payload["categoryIds"] = category_ids.to_a unless category_ids.nil?
|
|
37
43
|
if payload.empty?
|
|
38
|
-
raise ArgumentError, "Pass at least one of name, description, trigger, data, append_data, or
|
|
44
|
+
raise ArgumentError, "Pass at least one of name, description, trigger, data, append_data, actual_outcome, or category_ids: there is nothing to save otherwise."
|
|
39
45
|
end
|
|
40
46
|
|
|
41
47
|
@http_client.request(scenario_path(trace_id), payload)["scenario"]
|
data/lib/bitfab/version.rb
CHANGED
data/lib/bitfab.rb
CHANGED
|
@@ -15,7 +15,7 @@ require_relative "bitfab/git_state"
|
|
|
15
15
|
require_relative "bitfab/span_context"
|
|
16
16
|
require_relative "bitfab/http_client"
|
|
17
17
|
require_relative "bitfab/datasets"
|
|
18
|
-
require_relative "bitfab/
|
|
18
|
+
require_relative "bitfab/categories"
|
|
19
19
|
require_relative "bitfab/organization_members"
|
|
20
20
|
require_relative "bitfab/traces"
|
|
21
21
|
require_relative "bitfab/spans"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bitfab
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.65.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Harvest Team
|
|
@@ -155,9 +155,9 @@ files:
|
|
|
155
155
|
- exe/bitfab-replay
|
|
156
156
|
- exe/bitfab-seed
|
|
157
157
|
- lib/bitfab.rb
|
|
158
|
-
- lib/bitfab/assertion_categories.rb
|
|
159
158
|
- lib/bitfab/assertions.rb
|
|
160
159
|
- lib/bitfab/baml.rb
|
|
160
|
+
- lib/bitfab/categories.rb
|
|
161
161
|
- lib/bitfab/client.rb
|
|
162
162
|
- lib/bitfab/cloudReplay.py
|
|
163
163
|
- lib/bitfab/cloud_replay_cli.rb
|