Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
194 commits
Select commit Hold shift + click to select a range
c1a365a
feat(prompts): move backend + HTML-dashboard contracts into built-in …
SailingSF Jul 9, 2026
0af6687
fix(skills): address review — shadow fallback, recall idempotence, on…
SailingSF Jul 11, 2026
c5db078
fix(skills): stub must not satisfy the already-recalled check
SailingSF Jul 14, 2026
fd372ed
feat(publish): add access modes (password/restricted) to /publish and…
StpMax Jul 15, 2026
18cf596
fix(scratchpad): force UTF-8 so non-UTF-8 host locales don't crash th…
alecantu7 Jul 16, 2026
0dc7261
fix(scratchpad): drop PYTHONIOENCODING, keep only PYTHONUTF8 (self-re…
alecantu7 Jul 16, 2026
a4ba80a
fix(scratchpad): give the pip/uv install subprocess UTF-8 mode too (s…
alecantu7 Jul 16, 2026
16c83fc
Merge branch 'staging' into feat/ENG-727
StpMax Jul 17, 2026
0a0bb91
fix(publish): clear local .published.json on /unpublish so re-publish…
StpMax Jul 17, 2026
8b00144
fix(publish): publish_or_preview resolves artifact target from metada…
StpMax Jul 17, 2026
2ef9614
feat(publish): ask for access mode in chat when the user didn't speci…
StpMax Jul 17, 2026
a0814f2
fiix
StpMax Jul 17, 2026
b898bfc
fix web_search
ea-rus Jul 17, 2026
fda8510
Sync main back into staging after release
mindsdb-release-train[bot] Jul 20, 2026
7726302
Merge pull request #258 from mindsdb/fix/eng847-web_search-returns-empty
ea-rus Jul 20, 2026
e0584cd
fix(prompts): reference created artifact in final message
StpMax Jul 20, 2026
94a34ec
fix(cli): flush per-round preambles separately instead of concatenating
StpMax Jul 20, 2026
d9406ce
fix(scratchpad): UTF-8 the _parent_venv.pth write + pin the boot-scri…
alecantu7 Jul 20, 2026
1fc202f
test(scratchpad): pin the _parent_venv.pth write encoding (self-revie…
alecantu7 Jul 20, 2026
86b5d13
Merge pull request #253 from mindsdb/alejandrocantu/eng-824-scratchpa…
ZoranPandovski Jul 21, 2026
cbf474c
Merge pull request #244 from mindsdb/feat/prompt-skills-slim
SailingSF Jul 21, 2026
966a261
Merge pull request #251 from mindsdb/feat/ENG-727
StpMax Jul 21, 2026
e0720ff
count turns without tools
ea-rus Jul 21, 2026
dff7076
fix(llm): back off + retry mid-stream provider failures; typed transi…
alecantu7 Jul 21, 2026
83da2f8
public-data-sources skill
ea-rus Jul 22, 2026
58c75c9
use router model for summarization
ea-rus Jul 22, 2026
8675e4b
thalamus gate
ea-rus Jul 22, 2026
9382bac
Merge pull request #262 from mindsdb/feat/eng-742-save-tool-calls
ea-rus Jul 22, 2026
0775df6
ENG-940: explicit encoding="utf-8" on scratchpad/chat reads (launcher…
alecantu7 Jul 22, 2026
043a017
fix: preload skill alreadyin history
ea-rus Jul 22, 2026
84e3160
ENG-981: heal lone surrogates before compile() in the scratchpad (#268)
alecantu7 Jul 22, 2026
e1cca88
Merge pull request #260 from mindsdb/fix/ENG-900
StpMax Jul 23, 2026
167db92
count gate tokens
ea-rus Jul 23, 2026
3f93768
Merge pull request #264 from mindsdb/feat/eng-648-reduce-token-usage
ea-rus Jul 23, 2026
369b808
Merge pull request #265 from mindsdb/feat/eng-648-summary-model
ea-rus Jul 23, 2026
25d7355
max_chars works also for messages of the same role which go subsequently
ea-rus Jul 23, 2026
31a2082
Merge branch 'staging' into feat/eng-648-thalamus
ea-rus Jul 23, 2026
bd87572
fix for eng-845
martyna-mindsdb Jul 23, 2026
d014d05
Merge pull request #261 from mindsdb/fix/ENG-901
StpMax Jul 23, 2026
60b822f
Merge pull request #269 from mindsdb/fix-eng-845
martyna-mindsdb Jul 23, 2026
d61470f
fix: pillow vulnerability
martyna-mindsdb Jul 23, 2026
31f8eb0
fix: npm packages vulnerability
martyna-mindsdb Jul 23, 2026
eeb2632
Merge pull request #266 from mindsdb/feat/eng-648-thalamus
ea-rus Jul 23, 2026
39a4586
Merge pull request #271 from mindsdb/fix-upgrade-npm-packages
martyna-mindsdb Jul 24, 2026
180ac00
Merge pull request #270 from mindsdb/fix-upgrade-pillow
martyna-mindsdb Jul 24, 2026
ecbbe11
ci(ENG-1008): merge-to-main + staging panic and recovery alerts (#274)
lucas-koontz Jul 25, 2026
3b659c2
ci(ENG-1008): consolidate notify jobs for consistent pipeline alerts …
lucas-koontz Jul 25, 2026
cc0fb7b
chore(ENG-1053): introduce pipeline watchdog for startup failures ale…
lucas-koontz Jul 26, 2026
5ca45bd
ci: specify permissions for notify-main-failure workflow
lucas-koontz Jul 27, 2026
ea80797
Sync main back into staging after release
mindsdb-release-train[bot] Jul 27, 2026
7008232
fix(prompts): cap RESILIENCE_NUDGE with an honesty floor (ENG-838) (#…
alecantu7 Jul 27, 2026
fc832d5
HOTFIX ENG-1081: give the completion verifier room to answer (silent …
alecantu7 Jul 27, 2026
cda0a79
Catch insuficient quota error (#284)
ZoranPandovski Jul 29, 2026
2840f51
ENG-1124: persist the scratchpad namespace so state survives a turn (…
alecantu7 Jul 29, 2026
bc7cb1a
fix(session): completion verifier fails toward a real message, not si…
torrmal Jul 29, 2026
02f79a5
ENG-1084: memory & extraction subsystems silently did nothing on narr…
alecantu7 Jul 29, 2026
cff09f2
feat(llm): capture Claude/OpenAI reasoning as a real subtype:reasonin…
torrmal Jul 30, 2026
7b661bd
ENG-1042: revive main-loop truncation recovery — silent turns at the …
alecantu7 Jul 30, 2026
5cf7d7d
fix(llm): unwrap array-shaped provider errors; 404 → model-unavailabl…
pnewsam Jul 30, 2026
b25afad
fix(session): keep publish/datasource tools on resumed + rebuilt sess…
alecantu7 Jul 30, 2026
0f4c9a5
fix(security): pin brace-expansion to ^5.0.8 in docs (Dependabot #62)…
martyna-mindsdb Jul 31, 2026
eb8c748
ENG-1169: Map M3 wallet denials (402/429) to TokenLimitExceeded so th…
alecantu7 Jul 31, 2026
7eaae9b
Merge branch 'main' into staging
hamishfagg Aug 2, 2026
df08b07
Sync main back into staging after release
mindsdb-release-train[bot] Aug 2, 2026
292cbd6
chore(deps): bump postcss from 8.5.15 to 8.5.25 in /docs (#293)
dependabot[bot] Aug 3, 2026
032a7dd
ENG-847: fail loud on empty 200 in non-streaming complete (follow up…
ea-rus Aug 4, 2026
7bd26aa
ENG-664: expose compaction result for host persistence + skip low-yie…
ea-rus Aug 4, 2026
8d59d67
ENG-1155: hand-back diagnoses persist as streamed; latch dead verifie…
alecantu7 Aug 4, 2026
701a91f
ENG-836: verifier detects environment walls — tail-biased truncation …
alecantu7 Aug 4, 2026
578b33c
ENG-1211: behavioural eval for the completion verifier's verdict qual…
alecantu7 Aug 5, 2026
c77dd88
ENG-1276: explicit tool-failure outcomes drive the error streak, not …
alecantu7 Aug 5, 2026
cdc8b1a
ci: add sync from main to staging workflow and improve concurrency
lucas-koontz Aug 5, 2026
4e068d2
ci: clarify rationale behind excluding run-tree-ok in sync workflow
lucas-koontz Aug 5, 2026
c5551fa
ci(deps): add dependabot config + scope guard for dependency PRs (ENG…
alecantu7 Aug 6, 2026
560d29e
feat(cloud_turn): static buffered turn entrypoint (#281)
hamishfagg Aug 6, 2026
0535d52
[ENG-578] Watchdog and liveness heartbeat (#312)
tino097 Aug 6, 2026
7271efc
[ENG-578] Scratchpad discovery on startup (#315)
tino097 Aug 6, 2026
2ec14b0
feat(tracing): report anton's own version on every MindsHub trace (EN…
alecantu7 Aug 6, 2026
0bee8bc
ENG-1140: resolve MindsHub setup models from the live catalogue, surf…
alecantu7 Aug 6, 2026
2a836e2
ENG-1288: per-turn token cost counter — log line + turn_completed ana…
alecantu7 Aug 6, 2026
637a08c
ENG-1274: Fix: compaction fail can clear history for anton (#310)
ea-rus Aug 7, 2026
aae099c
ENG-972 Add stable, human-readable labels to saved connections (#300)
StpMax Aug 7, 2026
5d9b717
Fix duplicated wording in Anthropic/OpenAI 404 error messages (ENG-11…
StpMax Aug 7, 2026
c08904e
feat: let the agent ask a multiple-choice question mid-turn (#292)
StpMax Aug 7, 2026
1f63459
feat(ENG-763): stream ToolProgress markers for generic tools, with a …
StpMax Aug 7, 2026
6fb85b9
Sync main into staging
mindsdb-release-train[bot] Aug 9, 2026
801b2c1
Check uv.lock matches pyproject.toml in CI (#301)
hamishfagg Aug 10, 2026
981f192
ENG-697 fix webfetch retry (#303)
ea-rus Aug 10, 2026
9862d84
ENG-1092: move current date/time out of the cached system prefix (#295)
ea-rus Aug 10, 2026
5f3f2f7
Feature/cloud memory (#320)
ZoranPandovski Aug 10, 2026
b121dc3
ENG-1366: load scratchpad snapshots that hold agent-authored modules …
alecantu7 Aug 10, 2026
7a7d9dd
ENG-1390: make the hidden rule-retrieval LLM call countable and its o…
alecantu7 Aug 10, 2026
cdb05d7
ENG-1334: stop the verifier eval reporting green without running (#328)
alecantu7 Aug 11, 2026
c7cae4c
Feature/cloud skills (#326)
ZoranPandovski Aug 11, 2026
d70e880
ENG-764: defer tool schemas behind recalled skills (unlock_skill) (#318)
ea-rus Aug 11, 2026
70b51ce
docs(truncation): gateway reports "length" at the cap, not "stop" (#338)
alecantu7 Aug 11, 2026
85c496f
[ENG-1310] Unable to authenticate against the llm model invalid api k…
tino097 Aug 11, 2026
5919578
ci: publish Anton staging release candidates (ENG-1159) (#298)
pnewsam Aug 11, 2026
e117aa0
ENG-1359: don't register a web_search fallback with no usable creden…
ea-rus Aug 12, 2026
6b0c4ce
ENG-1357: stop advertising a picker that cannot render (#331)
alecantu7 Aug 12, 2026
8c9a3ef
[ENG-1275] Scratchpad auto install is killed by the watchdog it runs …
tino097 Aug 12, 2026
2b15fdb
ENG-1453: Stop the anton test suite from opening real browser windows…
alecantu7 Aug 12, 2026
f4c7ae3
Pin local dev to Python 3.12 (matches CI/prod); ignore .superpowers/ …
tino097 Aug 12, 2026
3f74f06
ENG 696: structured result contract for side-effecting tools (#319)
ea-rus Aug 13, 2026
2aae3db
ENG-1286: bound a turn's token spend and ask the user before continui…
alecantu7 Aug 13, 2026
f673c19
[12484] scratchpad uv discovery (#347)
tino097 Aug 13, 2026
122ceed
docs(readme): point the desktop download links at downloads.mindshub.…
lucas-koontz Aug 14, 2026
37b422e
Send events (#350)
ZoranPandovski Aug 14, 2026
741802f
chore(ci): move release-train alerts into the shared reusables (ENG-1…
lucas-koontz Aug 14, 2026
5eb775e
ENG-1495: send turn_completed and rule_retrieval straight to PostHog …
alecantu7 Aug 14, 2026
a3f6f47
ENG-1492: classify tool failures into a comparable root-cause key (#348)
alecantu7 Aug 14, 2026
b7221ab
ENG-1273: Scratchpad resume — recover a killed pad without losing its…
tino097 Aug 14, 2026
d681d4a
ENG-1324: surface the liveness heartbeat and pin the total-budget sto…
tino097 Aug 14, 2026
f05a7bf
ENG-1537: wait out a velocity rate-limit instead of retrying into it …
alecantu7 Aug 14, 2026
26d232b
ENG-1632: a deterministic verifier denial latches silently on first o…
alecantu7 Aug 15, 2026
2c21505
ENG-1632 hotfix: silent verifier latch on deterministic denial (main)…
alecantu7 Aug 15, 2026
a8ad6bc
Record main as merged — content already in staging via #360
pnewsam Aug 15, 2026
6be5d34
Sync main into staging
mindsdb-release-train[bot] Aug 16, 2026
be259c4
ENG-695 Recover truncated tool call (#342)
ea-rus Aug 17, 2026
67ef976
ENG-1617: flush in-flight analytics sends at exit so short-lived host…
Dav1dF Aug 18, 2026
5980392
Feat/efs shared storage (#365)
hamishfagg Aug 18, 2026
ba805bd
ENG-1693: only OUR gateway may select a billing verdict (#363)
alecantu7 Aug 18, 2026
3a11f72
Sync main into staging
mindsdb-release-train[bot] Aug 18, 2026
5e817f0
ENG-1693: contain both raising httpx properties so the billing-origin…
alecantu7 Aug 18, 2026
d59d8a7
Fix memory compaction: use indexes instead of strings (#346)
ea-rus Aug 18, 2026
a170723
Feat/cloud attachment delivery (#368)
ZoranPandovski Aug 19, 2026
a06e80f
ENG-1679: Fix create skill from chat (#361)
ea-rus Aug 19, 2026
322a3b4
fix(scratchpad): never persist file handles in namespace snapshots (E…
StpMax Aug 19, 2026
d6b99a7
feat(artifacts): put the artifact id in the folder slug (ENG-1680) (#…
StpMax Aug 20, 2026
9eebb0b
Fix trun failure (#380)
ZoranPandovski Aug 20, 2026
775b5c8
Sync main into staging
mindsdb-release-train[bot] Aug 20, 2026
6d8409e
fix(cli): name the endpoint that actually serves requests (ENG-1634) …
SailingSF Aug 20, 2026
6232a53
Sync main into staging
mindsdb-release-train[bot] Aug 20, 2026
96108af
Sync main into staging
mindsdb-release-train[bot] Aug 20, 2026
a7bb999
ENG-1692: don't report script traffic as turns (#379)
alecantu7 Aug 21, 2026
ee202a0
chore(deps): bump undici from 7.28.0 to 7.29.0 in /docs (#376)
martyna-mindsdb Aug 21, 2026
aa10255
fix(docker): install image deps from uv.lock, not a fresh resolve (#385)
hamishfagg Aug 21, 2026
96bba2d
fix(cloud): don't create anton.md from template in cloud turns (ENG-1…
StpMax Aug 21, 2026
06675ef
ENG-1808: emit a cloud turn's tool block-rows for cowork to persist (…
StpMax Aug 21, 2026
1420bef
ENG-1689: stamp endpoint_class and error_type on turn_completed (#381)
alecantu7 Aug 21, 2026
2021720
ENG-1689: record that the install-id format is depended on cross-repo…
alecantu7 Aug 21, 2026
695dcee
ENG-1459: declare which surface a turn came from, on every path (#373)
alecantu7 Aug 21, 2026
df7d0f6
ENG-1852: require user confirmation for a model-supplied single selec…
alecantu7 Aug 21, 2026
b727a41
[ENG-1635] scratchpad auto install any module (#371)
tino097 Aug 22, 2026
2a3ad8e
ENG-1486: emit a per-tool-call tool_completed analytics event (#390)
alecantu7 Aug 22, 2026
5b311dd
Sync main into staging
mindsdb-release-train[bot] Aug 23, 2026
826d4fb
ENG-1100: fix build-html-dashboard/build-fullstack-backend SKILL.md g…
StpMax Aug 24, 2026
4778662
fix(artifacts): use POSIX separators for artifact-relative paths (#356)
MohammedAlkindi Aug 24, 2026
1a85650
ENG-1291: budget the history summariser off the model's window (#375)
ea-rus Aug 24, 2026
dd5861d
use truststore for OS-native TLS verification in minds_request (#389)
tino097 Aug 24, 2026
17dc5b5
ENG-1769: explicit owner-only publish access (#378)
StpMax Aug 25, 2026
6b28b2b
feat: anton_state SDK + artifact lifecycle integration for stateful a…
StpMax Aug 26, 2026
539b08d
ENG-1945: stamp surface on turn_completed and tool_completed (#397)
alecantu7 Aug 26, 2026
1fd30c6
Record which artifacts a turn touched, as the tools touch them (#399)
torrmal Aug 26, 2026
4bc01b0
Sync main into staging
mindsdb-release-train[bot] Aug 26, 2026
1b6cfbf
Scope scratchpad subprocess env to the current data vault (#401)
tino097 Aug 26, 2026
840325b
feat(tracing): `harness` names which agent ran, not where (ENG-1694) …
alecantu7 Aug 26, 2026
323b535
fix(vision): stop guessing Anthropic image blocks by gateway hostname…
torrmal Aug 26, 2026
627f2fc
feat(llm): detect a permanent content-shaped provider rejection (ENG-…
torrmal Aug 26, 2026
47fc554
ENG-1796: the pod image reports the version it was built from (#404)
alecantu7 Aug 27, 2026
e74ea83
Shape the no-terminal-event turn_failed message for classification (#…
tino097 Aug 27, 2026
deb7993
ENG-1849: fix connect from chat (#398)
ea-rus Aug 27, 2026
9e9e7d3
feat(anton): Turn-Key Data Vault for cloud OAuth connectors (#400)
martyna-mindsdb Aug 27, 2026
0c49082
ENG-1796: comments must not be able to satisfy the build guards (#408)
alecantu7 Aug 27, 2026
92e9bfb
ENG-1858: Record why the completion verifier produced no verdict on t…
alecantu7 Aug 27, 2026
8791894
chore(cla): point the agreement link at the canonical repository (ENG…
lucas-koontz Aug 28, 2026
b2f3114
ENG-1638: Answer "which model are you" from the served model, never f…
alecantu7 Aug 28, 2026
ff0993b
fix(ci): gate the scratchpad build on the pull request being first-pa…
lucas-koontz Aug 28, 2026
1ac77dd
[ENG-208] Oauth hardening followups (#413)
tino097 Aug 28, 2026
61ec5db
feat: preserve artifact identity through publishing (#407)
StpMax Aug 28, 2026
0d713ed
fix(ci): refuse non-pull-request events at the gate before checking t…
lucas-koontz Aug 28, 2026
c664e83
ENG-2055: stop the test suite sending real analytics to production (#…
alecantu7 Aug 29, 2026
c3ab9f4
[ENG-1893] Agent stops mid session (#395)
tino097 Aug 29, 2026
7fe97bd
Sync main into staging
mindsdb-release-train[bot] Aug 31, 2026
3ada620
Sync main into staging
mindsdb-release-train[bot] Aug 31, 2026
bcfd12a
ci(scratchpad): run both pod entrypoints before the image can be push…
lucas-koontz Aug 31, 2026
8a555f3
fix(datasources): stop naming Picker-granted Drive files in anton's p…
alecantu7 Sep 1, 2026
fa8f853
Add yolo mode: edit artifact files with a diff (ENG-2186) (#422)
torrmal Sep 1, 2026
8b9271c
[ENG-2193] Tell the user the work finished when only the completion c…
tino097 Sep 1, 2026
a7d7e44
ENG-1957 FIX: Reusing a vaulted password for a second connection (#415)
ea-rus Sep 2, 2026
611f41c
Run eval in PRs (CI) (#388)
ea-rus Sep 2, 2026
0164706
Sync main into staging
mindsdb-release-train[bot] Sep 2, 2026
ca24955
[ENG-2193] Count an exhausted verdict ladder toward the completion-ve…
tino097 Sep 2, 2026
c79131d
ENG-2247: stamp the root-cause tier and class on tool_completed (#432)
alecantu7 Sep 3, 2026
5404355
Migrate to httpx2 (#428)
ZoranPandovski Sep 3, 2026
cc49e15
[ENG-1382] Keep datasource credentials out of the shared process envi…
tino097 Sep 3, 2026
6695b80
fix(data_vault): remove TurnKeyDataVault's dead base_url override (#436)
martyna-mindsdb Sep 3, 2026
0b8241c
Fix vulnerabilities (#437)
ZoranPandovski Sep 3, 2026
07fea5a
Bugfix/rmv aiohttp (#438)
ZoranPandovski Sep 3, 2026
f3bfa6a
Fix the typo in datasource (#440)
ZoranPandovski Sep 3, 2026
cbe0e97
ENG-2243: stamp a per-attempt turn id so the tool→turn join is exact …
alecantu7 Sep 3, 2026
1933d81
ENG-1687: pin the verifier eval's served model so an alias repoint ca…
alecantu7 Sep 3, 2026
59a543b
ENG-1361: Card a provider failure instead of telling the user to reph…
alecantu7 Sep 3, 2026
4c677f6
ENG-2248: declare explicit ok/reason verdicts on six anton tool handl…
alecantu7 Sep 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
258 changes: 258 additions & 0 deletions .github/workflows/evals.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
name: Anton evals

# Behavioural baseline for the Anton harness: runs the `dialog_context` dataset
# through a cowork-server built from this PR's anton sha, then posts accuracy,
# tokens and latency as a PR comment.
#
# This reports numbers; it does not gate. Agent runs vary between passes, and a
# red check on noise trains people to click "re-run" without reading. The job
# fails only when it could not measure anything at all.
#
# Required repository secrets:
# MINDSHUB_API_KEY prod gateway key — also seeded into the built cowork-server.
# LANGFUSE_HOST / LANGFUSE_PUBLIC_KEY / LANGFUSE_SECRET_KEY
# the project the PROD gateway writes to. A dev-project key
# here yields empty token/cost columns, not an error.
# GH_EVALS_READ_TOKEN
# read access to mindsdb/cowork-server + mindsdb/cowork_evals.
# The automatic GITHUB_TOKEN is scoped to this repository
# alone — same-org membership does not extend it.
#
# Credentials come from secrets ONLY. This repository is public, and
# workflow_dispatch inputs are recorded on the run for anyone to read, so a key
# typed into the launch form would be published. The inputs below are all
# non-sensitive by design.

permissions:
contents: read
pull-requests: write # the report is posted as a PR comment

on:
# `labeled` fires once, when the label is added — later pushes to the PR do not
# re-trigger it. Re-running is "remove the label, add it again", which is the
# explicit opt-in a paid run should have.
pull_request:
types: [labeled]
workflow_dispatch:
inputs:
anton_ref:
description: "anton ref to build (default: this branch)"
required: false
cowork_ref:
description: "cowork-server ref to build"
default: staging
baseline_ref:
description: "anton ref to compare against"
default: staging
evals_ref:
description: "cowork_evals ref providing the run config and the report"
default: main
repeats:
description: "replicate passes per task"
default: "3"

concurrency:
group: evals-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
evals:
if: github.event_name == 'workflow_dispatch' || github.event.label.name == 'run-evals'
runs-on: ubuntu-latest
# Two builds and two passes over the dataset: ~6 minutes of agent time each,
# plus a `uv sync` per harness build. Anything past this is hung rather than
# slow, and the GitHub default of 360 would hold a runner for six hours to
# establish that.
timeout-minutes: 120
env:
COWORK_REF: ${{ inputs.cowork_ref || 'staging' }}
BASELINE_REF: ${{ inputs.baseline_ref || 'staging' }}
EVALS_REF: ${{ inputs.evals_ref || 'main' }}
REPEATS: ${{ inputs.repeats || '3' }}
ANTON_SHA: ${{ github.event.pull_request.head.sha || inputs.anton_ref || github.sha }}
REPO_TOKEN: ${{ secrets.GH_EVALS_READ_TOKEN }}
LANGFUSE_HOST: ${{ secrets.LANGFUSE_HOST }}
LANGFUSE_PUBLIC_KEY: ${{ secrets.LANGFUSE_PUBLIC_KEY }}
LANGFUSE_SECRET_KEY: ${{ secrets.LANGFUSE_SECRET_KEY }}
steps:
# `pull_request` withholds secrets from forks by design, so a fork PR cannot
# run this and must not be failed for it — but it must not look measured
# either.
- name: Skip fork PRs
id: fork
if: github.event_name == 'pull_request'
&& github.event.pull_request.head.repo.full_name != github.repository
run: |
echo "skip=1" >> "$GITHUB_OUTPUT"
{
echo "### Evals skipped — fork PR"
echo ""
echo "\`pull_request\` withholds repository secrets from forks, so no"
echo "numbers were measured for this change. Re-run the eval from a"
echo "first-party branch before merging."
} >> "$GITHUB_STEP_SUMMARY"

# Checked before the checkouts so a missing credential reads as "nobody
# provisioned this" rather than a confusing 404 on a repository that does
# exist.
- name: Fail loudly on a missing credential
if: steps.fork.outputs.skip != '1'
env:
MINDS_API_KEY: ${{ secrets.MINDSHUB_API_KEY }}
run: |
set -euo pipefail
: "${MINDS_API_KEY:?MINDSHUB_API_KEY secret is not set}"
: "${REPO_TOKEN:?no read token — set the GH_EVALS_READ_TOKEN secret or pass repo_token}"
# All three or none — a partial Langfuse config silently drops to empty
# token/cost columns downstream instead of the clear error this step
# exists to give.
: "${LANGFUSE_HOST:?no Langfuse host — token and cost columns would be empty}"
: "${LANGFUSE_PUBLIC_KEY:?no Langfuse public key — token and cost columns would be empty}"
: "${LANGFUSE_SECRET_KEY:?no Langfuse secret key — token and cost columns would be empty}"

- name: Check out anton
if: steps.fork.outputs.skip != '1'
uses: actions/checkout@v4
with:
path: anton
ref: ${{ env.ANTON_SHA }}
# The eval builds its harness with `git worktree add <sha>`, which needs
# the object present locally — a shallow clone does not have it.
fetch-depth: 0

# Pinned to a commit, not a branch name, for two reasons:
# - the eval compares the two refs to decide whether the baseline build is
# a duplicate, and "staging" never equals a sha, so the check would never
# fire on a PR that IS staging;
# - a branch that moves mid-run would make the two halves of the comparison
# disagree about what "baseline" meant.
# `pull_request` runs already give ANTON_SHA as a sha; a manual `workflow_dispatch`
# with `anton_ref: staging` does not — resolve it from the checkout above so
# cowork_evals' duplicate-variant check (a raw string compare of the two refs)
# sees the same sha on both sides when anton_ref and BASELINE_REF are the same
# commit, instead of "staging" vs a resolved sha never matching.
- name: Resolve the anton commit
if: steps.fork.outputs.skip != '1'
working-directory: anton
run: |
set -euo pipefail
echo "ANTON_SHA=$(git rev-parse HEAD)" >> "$GITHUB_ENV"

- name: Resolve the baseline commit
id: baseline
if: steps.fork.outputs.skip != '1'
working-directory: anton
run: |
set -euo pipefail
git fetch --no-tags --quiet origin "$BASELINE_REF"
sha=$(git rev-parse --verify FETCH_HEAD^{commit})
echo "resolved $BASELINE_REF -> $sha"
echo "sha=$sha" >> "$GITHUB_OUTPUT"

- name: Check out cowork-server
if: steps.fork.outputs.skip != '1'
uses: actions/checkout@v4
with:
repository: mindsdb/cowork-server
ref: ${{ env.COWORK_REF }}
token: ${{ env.REPO_TOKEN }}
path: cowork-server
fetch-depth: 0

- name: Check out cowork_evals
if: steps.fork.outputs.skip != '1'
uses: actions/checkout@v4
with:
repository: mindsdb/cowork_evals
ref: ${{ env.EVALS_REF }}
token: ${{ env.REPO_TOKEN }}
path: cowork_evals

- name: Install uv
if: steps.fork.outputs.skip != '1'
uses: astral-sh/setup-uv@v5
with:
# The managed build runs `uv sync` in a fresh cowork-server worktree on
# every new anton sha, so the build dir itself is never reused. uv's
# package cache is the part that carries over.
enable-cache: true
cache-dependency-glob: "**/uv.lock"

- name: Run the eval
id: eval
if: steps.fork.outputs.skip != '1'
working-directory: cowork_evals
env:
MINDS_URL: https://api.mindshub.ai/v1
MINDS_API_KEY: ${{ secrets.MINDSHUB_API_KEY }}
CI_ANTON_REPO: ${{ github.workspace }}/anton
CI_COWORK_REPO: ${{ github.workspace }}/cowork-server
CI_ANTON_REF: ${{ env.ANTON_SHA }}
CI_COWORK_REF: ${{ env.COWORK_REF }}
# The build to compare against. When it is the same commit as
# CI_ANTON_REF the eval drops the duplicate and reports a single row.
CI_BASELINE_REF: ${{ steps.baseline.outputs.sha }}
run: |
set -euo pipefail
uv run eval run \
--config runs/templates/ci-dialog-context.yaml \
--repeats "$REPEATS" | tee run.log
# `eval run` ends with "done: <run_id> (...)"; that id names the results
# directory everything downstream reads.
run_id=$(sed -n 's/^done: \([^ ]*\).*/\1/p' run.log | tail -1)
[ -n "$run_id" ] || { echo "::error::eval run printed no run id"; exit 1; }
echo "run_id=$run_id" >> "$GITHUB_OUTPUT"

- name: Render the report
id: report
if: steps.fork.outputs.skip != '1'
working-directory: cowork_evals
run: |
set -euo pipefail
# Derived, not hardcoded: adding a task to the dataset must not silently
# lower the bar for what counts as a complete run.
tasks=$(grep -c . datasets/dialog_context.jsonl)
expected=$(( tasks * REPEATS ))
uv run eval report --run "${{ steps.eval.outputs.run_id }}" \
--fmt pr --expect "$expected" > report.md
cat report.md >> "$GITHUB_STEP_SUMMARY"

- name: Comment on the PR
if: steps.fork.outputs.skip != '1' && github.event_name == 'pull_request'
working-directory: cowork_evals
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR: ${{ github.event.pull_request.number }}
SHA: ${{ env.ANTON_SHA }}
run: |
set -euo pipefail
marker='<!-- anton-evals -->'
{
echo "$marker"
cat report.md
echo ""
echo "<sub>anton \`${SHA:0:8}\` · cowork-server \`$COWORK_REF\` · $REPEATS replicates</sub>"
} > comment.md
# One comment per PR, edited in place: a fresh comment per run buries the
# conversation under near-identical tables. --paginate covers PRs past the
# 30-comment first page; --jq runs per page, but an empty page contributes
# no output, so the concatenated result is still just the one matching id.
id=$(gh api --paginate "repos/$GITHUB_REPOSITORY/issues/$PR/comments" \
--jq "[.[] | select(.body | startswith(\"$marker\")) | .id] | first // empty")
if [ -n "$id" ]; then
gh api -X PATCH "repos/$GITHUB_REPOSITORY/issues/comments/$id" -F body=@comment.md
else
gh api -X POST "repos/$GITHUB_REPOSITORY/issues/$PR/comments" -F body=@comment.md
fi

# Kept even when the run fails: a broken run's logs and partial results are
# the only way to tell a harness bug from a gateway outage.
- name: Upload run artifacts
if: always() && steps.fork.outputs.skip != '1'
uses: actions/upload-artifact@v4
with:
name: eval-run-${{ steps.eval.outputs.run_id || github.run_id }}
path: |
cowork_evals/run.log
cowork_evals/runs/
retention-days: 90
51 changes: 23 additions & 28 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: Auto-release and publish to PyPI

# Stable release stream: on every push to main, validate, cut a CalVer release,
# publish it to PyPI, and run live release e2e. Staging pre-releases (rc) live in
# verify the built wheel, then publish it to PyPI. Staging pre-releases (rc) live in
# publish-staging.yml so each stream keeps its own run tree, permissions,
# notifications, and publishing identity.
#
Expand Down Expand Up @@ -42,54 +42,49 @@ jobs:
calver-major: "2"
runs-on: ubuntu-latest

verify-wheel:
needs: auto-release
permissions:
contents: read
uses: ./.github/workflows/tests_e2e_release.yml
with:
tag: ${{ needs.auto-release.outputs.tag }}
version: ${{ needs.auto-release.outputs.version }}
secrets: inherit

publish:
name: Publish to PyPI
needs: auto-release
# Gated on verify-wheel: a PyPI upload cannot be withdrawn.
needs: [auto-release, verify-wheel]
runs-on: ubuntu-latest
environment: pypi
permissions:
contents: read
id-token: write # required for trusted publisher (OIDC)
steps:
- uses: actions/checkout@v4
# Publish the bytes verify-wheel actually tested, not a rebuild of the
# same source — a second build verifies equivalence, not the artifact.
- name: Download the verified distributions
uses: actions/download-artifact@v4
with:
ref: ${{ needs.auto-release.outputs.tag }}
fetch-depth: 0 # hatch-vcs needs tags to derive version
name: verified-dist
path: dist

- name: Setup uv
uses: astral-sh/setup-uv@v5
with:
python-version: "3.12"

- name: Build package
env:
# A re-run or re-dispatch on an already-tagged head leaves two CalVer
# tags on one commit and `git describe` resolves the older one; build
# exactly the version the release job minted.
SETUPTOOLS_SCM_PRETEND_VERSION: ${{ needs.auto-release.outputs.version }}
run: uv build
- name: Show what is being published
run: ls -l dist

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
# Trusted publisher (OIDC) — release.yml must be registered at the
# anton-agent PyPI project's publishing settings (environment: pypi).

e2e:
needs: auto-release
permissions:
contents: read
uses: ./.github/workflows/tests_e2e_release.yml
with:
tag: ${{ needs.auto-release.outputs.tag }}
secrets: inherit

notify:
# Alert the eng channel if ANY job in the release pipeline fails (tests, tag,
# PyPI publish, or release e2e).
# wheel verification, or PyPI publish).
# One job covers both outcomes: a `uses:` job cannot branch on status, so
# the aggregate result picks the failed or recovered message, and a
# cancelled run stays silent.
needs: [unit-tests, auto-release, publish, e2e]
needs: [unit-tests, auto-release, verify-wheel, publish]
if: ${{ github.ref == 'refs/heads/main' && !cancelled() && !contains(needs.*.result, 'cancelled') }}
permissions:
contents: read
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/scratchpad-dev-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ name: Scratchpad image - Dev build on PR
# rebuilds. The scratchpad-controller references the resulting tag via
# SCRATCHPAD_CONTROLLER__SCRATCHPAD_IMAGE; there is no Helm chart for this image, so this
# workflow only builds and scans (no deploy job).
#
# The image is smoke-tested inside the build, not here: the Dockerfile's last layer runs
# docker/image_smoke.py as UID 1000, which executes both entrypoints the controller execs.
# It sits in the build rather than in a step below it so a failure blocks the PUSH — an
# image no pod can serve a turn with never reaches ECR to be pinned by mistake.

on:
pull_request:
Expand Down
Loading
Loading