diff --git a/profile/README.md b/profile/README.md index d02234c..0674428 100644 --- a/profile/README.md +++ b/profile/README.md @@ -36,7 +36,7 @@ Your data stays on your infrastructure. Fine-tuned weights stay on your infrastr | | | |---|---| | **[model-zoo](https://github.com/tracebloc/model-zoo)** | Pre-built models for vision, NLP, tabular, time series — ready to train | -| **[start-training](https://github.com/tracebloc/start-training)** | Jupyter notebook to launch training in minutes | +| **[quickstart](https://github.com/tracebloc/quickstart)** | Jupyter notebook to launch training in minutes | | **[data-ingestors](https://github.com/tracebloc/data-ingestors)** | Pipelines to validate, prepare, and ingest your datasets | | **[client](https://github.com/tracebloc/client)** | Deploy the tracebloc workspace on your Kubernetes cluster | diff --git a/scripts/tests/bugbot-gate-mutations.py b/scripts/tests/bugbot-gate-mutations.py index e63827c..4e3fe80 100644 --- a/scripts/tests/bugbot-gate-mutations.py +++ b/scripts/tests/bugbot-gate-mutations.py @@ -81,6 +81,15 @@ ("a repeating cursor is followed for ever instead of refused", ' if not cursor or cursor in seen_cursors or pages_left <= 0:', ' if not cursor:'), + # The regression the staging-hop Bugbot named on #464: the pageInfo self-check + # going blind for ONE connection. The selftest's stripper loop used to `break` + # after `checkSuites`, and its `reviewThreads` branch pasted a fixed indentation + # that matched the checkSuites line first -- so this row was UNCAUGHT until + # the loop was made to visit every member (measured before the fix landed). + ("the pageInfo self-check walks only the first connection, so reviewThreads' " + "cursor can be dropped from the query unnoticed", + ' for name in PAGED_TOPLEVEL:\n match = re.search(name + r"\\(first:', + ' for name in list(PAGED_TOPLEVEL)[:1]:\n match = re.search(name + r"\\(first:'), # --- (A) the load-bearing claim: a TERMINAL verdict on THIS head -------- ("a missing Bugbot verdict reports PASS instead of UNCLAIMED", diff --git a/scripts/tests/bugbot-gate-selftest.py b/scripts/tests/bugbot-gate-selftest.py index 32107d0..056f525 100644 --- a/scripts/tests/bugbot-gate-selftest.py +++ b/scripts/tests/bugbot-gate-selftest.py @@ -911,15 +911,54 @@ def _threads(n, start=0): # The query must keep asking for pageInfo, or none of the above ever runs live. check("the real QUERY asks both top-level connections for pageInfo", gate.connections_missing_pageinfo() == [], "missing=%r" % gate.connections_missing_pageinfo()) + +# EVERY CONNECTION, AND THE RIGHT ONE. The first version of this loop ended in a +# `break`, so only the first member of PAGED_TOPLEVEL (`checkSuites`) was ever +# exercised, and its `reviewThreads` branch pasted a fixed 6-space indentation +# into `str.replace` -- a needle that is a substring of the 14-space-indented +# `checkSuites` line and so, had it ever run, would have stripped checkSuites' +# pageInfo a second time and let the detector "pass" by naming the wrong +# connection (measured: `connections_missing_pageinfo` answered +# `['checkSuites']` for the reviewThreads branch). A self-check that went blind +# for `reviewThreads` alone passed this suite. Same shape as the totalCount +# stripper above, with three things pinned: +# 1. the members are ALSO written down as literals, because a loop over the +# module's own dict cannot see a member being removed from it; +# 2. the stripper is anchored on the connection's own name and is indentation- +# agnostic, and its substitution count is asserted, so it cannot hit the +# neighbour or silently strip nothing; +# 3. the detector must name EXACTLY the connection stripped -- the other one, +# or both, is a wrong answer, not a pass; +# and the loop's visit list is compared to the literals afterwards, so a `break` +# (or a `continue` past the asserts) reddens the suite instead of shrinking it. +PAGED_TOPLEVEL_LITERALS = ("checkSuites", "reviewThreads") +for name in PAGED_TOPLEVEL_LITERALS: + check( + "%r is declared a paged top-level connection" % name, + name in gate.PAGED_TOPLEVEL, + "PAGED_TOPLEVEL = %r" % (list(gate.PAGED_TOPLEVEL),), + ) +pageinfo_visited = [] for name in gate.PAGED_TOPLEVEL: - stripped = re.sub(r"pageInfo \{ hasNextPage endCursor \}\n", "", gate.QUERY, count=1) \ - if name == "checkSuites" else gate.QUERY.replace(" pageInfo { hasNextPage endCursor }\n", "", 1) - # Whichever occurrence the stripper removed, the guard must name AT LEAST one - # connection -- the assertion is that the stripper applied and was seen. - check("the pageInfo stripper actually applied", stripped != gate.QUERY) - check("dropping pageInfo from the query is detected", - gate.connections_missing_pageinfo(stripped) != [], "guard stayed silent for %r" % name) - break + stripped, applied = re.subn( + r"(" + name + r"\(first:\s*\d+[^)]*\)\s*\{[^{]*?)pageInfo\s*\{[^}]*\}\s*", r"\1", gate.QUERY + ) + check( + "the pageInfo stripper actually applied to %r" % name, + applied == 1, + "%d substitution(s) -- the anchor no longer matches the query" % applied, + ) + check( + "dropping pageInfo from %r is detected, and %r alone is named" % (name, name), + gate.connections_missing_pageinfo(stripped) == [name], + "detector said %r" % (gate.connections_missing_pageinfo(stripped),), + ) + pageinfo_visited.append(name) +check( + "the pageInfo stripper loop visited every paged top-level connection", + sorted(pageinfo_visited) == sorted(PAGED_TOPLEVEL_LITERALS), + "visited %r, expected %r" % (pageinfo_visited, list(PAGED_TOPLEVEL_LITERALS)), +) # 7. severity_of, directly. # -------------------------------------------------------------------------- diff --git a/scripts/tests/extract-advanced-prs-selftest.sh b/scripts/tests/extract-advanced-prs-selftest.sh index 02e3ec0..6138228 100755 --- a/scripts/tests/extract-advanced-prs-selftest.sh +++ b/scripts/tests/extract-advanced-prs-selftest.sh @@ -26,6 +26,19 @@ no() { printf ' FAIL %s\n %s\n' "$1" "$2"; fail=$((fail + 1)); } assert_out() { if grep -qF -- "$2" <<<"$3"; then ok "$1"; else no "$1" "expected: $2 -- got: $3"; fi; } assert_not_out() { if grep -qF -- "$2" <<<"$3"; then no "$1" "must NOT contain: $2 -- got: $3"; else ok "$1"; fi; } +# result_line -> ONLY the script's "Found PRs: ..." line, the attribution +# itself. The "is NOT attributed" checks below must grep THIS, never the whole +# output: the script also prints `::warning::commit <40-hex sha>: ...`, and the +# fixture commits are minted at run time (random content + the wall clock), so +# their shas are random hex. A negative grep for "901" over the whole output +# therefore fails whenever the sha happens to contain "901" -- which is what +# reddened `selftests` on main at eb89c1e5 (sha e57d5bafc191901afac...) with the +# extractor itself correct. ~1% of runs per three-digit needle: a coin the +# suite tossed on every push. An absent result line is returned as-is (empty), +# so a negative assertion on it still passes only when the positive +# "Found PRs" assertion next to it is what carries the check. +result_line() { grep -- '^Found PRs:' <<<"$1" || true; } + # A `gh` stub. `gh api repos//commits//pulls --jq `: # * $STUB_DIR/.fail present -> exit 1 (a FAILED read, e.g. a 403) # * else apply with real jq over $STUB_DIR/.json (empty array if none) @@ -93,7 +106,7 @@ a="$(commit "$root" 'fix(tests): bound the k3d cleanup in all seven e2e EXIT tra printf '[{"number":985,"merged_at":"2026-09-07T08:22:52Z","base":{"ref":"develop"},"head":{"ref":"fix/979-k3d-cleanup"}}]\n' >"$STUB_DIR/${a}.json" out="$(run_extract "$root" "$base" "$a" "$bin")" assert_out "client#985: the develop-based feature PR is attributed on a staging hop" "Found PRs: 985" "$out" -assert_not_out "client#985: the subject issue is NOT used" "979" "$out" +assert_not_out "client#985: the subject issue is NOT used" "979" "$(result_line "$out")" # --------------------------------------------------------------------------- # FIXTURE 2: tracebloc-engine#914 — subject names ticket backend#3013 in the @@ -106,7 +119,7 @@ b="$(commit "$root" 'sec(deps): torch 2.13.0 + torchvision 0.28.0 on the cu129 i printf '[{"number":914,"merged_at":"2026-09-07T00:00:00Z","base":{"ref":"develop"},"head":{"ref":"sec/3013-torch"}}]\n' >"$STUB_DIR/${b}.json" out="$(run_extract "$root" "$base" "$b" "$bin")" assert_out "engine#914: the develop-based feature PR is attributed on a staging hop" "Found PRs: 914" "$out" -assert_not_out "engine#914: the subject ticket is NOT used" "3013" "$out" +assert_not_out "engine#914: the subject ticket is NOT used" "3013" "$(result_line "$out")" # --------------------------------------------------------------------------- # PROMOTION PR EXCLUDED: a commit whose /pulls names a merged release-train/* @@ -118,7 +131,7 @@ base="$(make_repo "$root")" p="$(commit "$root" 'chore(promote): develop -> staging (#900)')" printf '[{"number":901,"merged_at":"2026-09-07T00:00:00Z","base":{"ref":"staging"},"head":{"ref":"release-train/develop-to-staging"}}]\n' >"$STUB_DIR/${p}.json" out="$(run_extract "$root" "$base" "$p" "$bin")" -assert_not_out "promotion: the release-train PR is not attributed" "901" "$out" +assert_not_out "promotion: the release-train PR is not attributed" "901" "$(result_line "$out")" assert_out "promotion: it falls through to the subject" "Found PRs: 900" "$out" # ---------------------------------------------------------------------------