Skip to content

Remove paid benchmark CI and repair CI gates - #1131

Merged
aviggiano merged 3 commits into
mainfrom
codex/1129-retire-paid-ci
Sep 22, 2026
Merged

aviggiano merged 3 commits into
mainfrom
codex/1129-retire-paid-ci

Conversation

@aviggiano

@aviggiano aviggiano commented Sep 22, 2026 •

Copy link
Copy Markdown
Collaborator

Paid benchmark Actions could consume provider and Modal credits, while the automatic history publisher held a write-capable App credential. Remove the producer, recovery, and publisher workflows and their unused orchestration helpers. Keep ordinary credential-free CI and the manual benchmark launch, validation, collection, and termination tools, with updated instructions and a regression guard against reintroducing paid workflow wiring.

Fix two runtime CI failures without weakening their assertions: replace a live OpenRouter diagnostic probe with an offline transport in the isolated test dependency, and move expensive controller snapshot coverage to the Node lane while keeping generated-child credential isolation checks in Bun. The retry test verifies session resume and actual child-process cleanup.

The dependency advisory gate also found GHSA-7q85-xj36-vmfc in the pinned ZIP reader. Update adm-zip to 0.6.1 and accept its earlier duplicate-entry rejection in the existing archive test.

Validation: full workspace build; 673 Modal tests; 102 CI-script tests; 17 focused adapter/credential tests; the Node controller forwarding regression; 17 archive-security/benchmark-analysis tests; the dependency advisory gate (zero High/Critical advisories, zero exceptions); formatting, changed-code strict lint, TypeScript, docs checks, and Knip. Changes received independent review. No paid inference or cloud benchmark was launched.

Repository operations are already complete: all three paid workflows are disabled, eight repository Actions secrets and the publisher App client-ID variable have been deleted. Operational evidence and account-owner follow-up records the stale queued Actions entry and the remaining provider-side revocation, Modal inventory, and publisher App/bypass checks that require account access.

Fixes #1129

RetriggerConfidence Score: 5/5

The PR appears safe to merge; the remaining documentation omissions are non-blocking but still leave parts of the manual benchmark runbook incomplete.

Fix All in Claude CodeFindings

  1. P2 Incomplete collection command ▶
  2. P2 Missing cleanup commands ▶
Fix with agent prompt
### Issue 1
docs/how-to/run-evals-on-modal.md:258-260
The manual instructions describe collection as `collect --public-results --config <path>`, but the retained CLI also requires `--state`; without it, the command exits before collecting anything. `unpack-public` likewise requires both `--bundle` and `--output`. Since this is now the only documented path for obtaining publishable results after paid compute completes, please include complete collection and extraction commands using the pair's preserved state and output paths.

### Issue 2
docs/how-to/run-evals-on-modal.md:252-256
This section names the missing-state cleanup helpers but does not show their required arguments or explain how to generate the pair list before termination. A launcher failure is exactly when an operator may have only the preserved plan, so the sole remaining orphan-cleanup runbook is not directly executable during a costly incident. Please include concrete preparation and termination commands using the previously defined candidate, generation, control directory, and checkout.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

This PR removes the automated paid benchmark, recovery, and history-publication workflows while retaining manual benchmark operations and credential-free CI coverage. It also stabilizes runtime tests by replacing a live provider diagnostic with an offline transport and redistributing expensive coverage between Node and Bun.

  • Deletes write-capable and paid-compute workflow wiring plus orchestration helpers used only by those workflows.
  • Updates evaluation documentation and regression tests for the retained manual benchmark lifecycle.
  • Keeps runtime retry, session-resume, child-process cleanup, and credential-isolation assertions without requiring live provider access.
  • Updates adm-zip to 0.6.1 so duplicate ZIP entries are rejected by the dependency as well as the surrounding archive validation.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Operator[Operator] --> Plan[Prepare benchmark plan]
  Plan --> Validate[Validate launch guardrails]
  Validate --> Launch[Manual paid Modal launch]
  Launch --> Status[Monitor retained state]
  Status --> Collect[Collect validated public bundles]
  Collect --> Review[Review results locally]
  Review --> PR[Publish history through normal PR]
  Launch --> Terminate[Explicit termination and cleanup]
  AutomaticCI[Credential-free CI] -. no paid launch .-> Validate
Loading

Reviews (2) · Last reviewed commit: "Update adm-zip to patched release and re..."

@aviggiano
aviggiano requested a review from a team as a code owner September 22, 2026 19:28
Comment on lines +258 to +260
After a pair completes, collect its validated public bundle with `collect
--public-results --config <path>` and extract it with `unpack-public`. Preserve
all scored rows and candidate/target lineage. A complete generation can then

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Incomplete collection command

The manual instructions describe collection as collect --public-results --config <path>, but the retained CLI also requires --state; without it, the command exits before collecting anything. unpack-public likewise requires both --bundle and --output. Since this is now the only documented path for obtaining publishable results after paid compute completes, please include complete collection and extraction commands using the pair's preserved state and output paths.

Knowledge Base Used: Modal worker integration

Prompt To Fix With AI
This is a comment left during a code review.
Path: docs/how-to/run-evals-on-modal.md
Line: 258-260

Comment:
**Incomplete collection command**

The manual instructions describe collection as `collect --public-results --config <path>`, but the retained CLI also requires `--state`; without it, the command exits before collecting anything. `unpack-public` likewise requires both `--bundle` and `--output`. Since this is now the only documented path for obtaining publishable results after paid compute completes, please include complete collection and extraction commands using the pair's preserved state and output paths.

**Knowledge Base Used:** [Modal worker integration](https://app.greptile.com/monad-foudnation/-/custom-context/knowledge-base/monad-developers/ultrafuzz/-/docs/modal-worker-integration.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Claude Code

Comment on lines +252 to +256
If a launch did not persist its state, the retained
`prepare-modal-benchmark-cleanup.mjs` and `terminate-modal-benchmark.sh` helpers
can validate a preserved plan and terminate its exact build and pair scopes.
Use trusted tooling and confirm uncertain remote cleanup before retiring
credentials. Keep cleanup access available until the detached work is stopped.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Missing cleanup commands

This section names the missing-state cleanup helpers but does not show their required arguments or explain how to generate the pair list before termination. A launcher failure is exactly when an operator may have only the preserved plan, so the sole remaining orphan-cleanup runbook is not directly executable during a costly incident. Please include concrete preparation and termination commands using the previously defined candidate, generation, control directory, and checkout.

Knowledge Base Used:

Prompt To Fix With AI
This is a comment left during a code review.
Path: docs/how-to/run-evals-on-modal.md
Line: 252-256

Comment:
**Missing cleanup commands**

This section names the missing-state cleanup helpers but does not show their required arguments or explain how to generate the pair list before termination. A launcher failure is exactly when an operator may have only the preserved plan, so the sole remaining orphan-cleanup runbook is not directly executable during a costly incident. Please include concrete preparation and termination commands using the previously defined candidate, generation, control directory, and checkout.

**Knowledge Base Used:**
- [Execution runtime](https://app.greptile.com/monad-foudnation/-/custom-context/knowledge-base/monad-developers/ultrafuzz/-/docs/execution-runtime.md)
- [Modal worker integration](https://app.greptile.com/monad-foudnation/-/custom-context/knowledge-base/monad-developers/ultrafuzz/-/docs/modal-worker-integration.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Claude Code

@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedadm-zip@​0.6.0 ⏵ 0.6.1100 +1100 +1898 +187 -1100

View full report

@aviggiano aviggiano changed the title Remove paid benchmark CI and stabilize offline runtime tests Remove paid benchmark CI and repair CI gates Sep 22, 2026
@aviggiano
aviggiano merged commit a49a626 into main Sep 22, 2026
13 checks passed
@aviggiano
aviggiano deleted the codex/1129-retire-paid-ci branch September 22, 2026 20:36
aviggiano added a commit that referenced this pull request Sep 29, 2026
…idence

Drop getPrompt, which this change no longer deletes. Name the actual
callers of the two CI scripts (eval-benchmarks.yml and the
watch-modal-benchmark.sh it ran, both deleted in #1131) instead of "the
workflows #1131 deleted": the other two workflows #1131 removed never
invoked either script. Stop describing the config prompt-metadata layer as
code no production path calls: resolveConfig ran it on every resolution,
only ever with an empty layer. Mention the run-tests.mjs selectors and the
docs/config.md change, and add the [runtime] and [docs] tags for them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
aviggiano added a commit that referenced this pull request Sep 29, 2026
…ication leftovers (#1174)

* refactor(evals): delete the zero-reporter telemetry pump and reporter interface

runEvalSuite always built an empty reporter list and resolveEvalProvider
accepts only "none", so NodeTelemetryPump translated and "delivered"
journal events to nobody. It still had to succeed on every poll: a drain
that threw aborted the whole suite before run-summary.json was written.
One schema-valid trigger is a node-synced transition without
payload.attempt, which the event contract allows and sync emits when the
runner reported no attempt; the pump rejected it with
EVAL_TELEMETRY_EVENT_UNUSABLE.

watchEvalRow is now: sync, read state.json, sleep. Deleted with the pump:
EvalReporter and its graph/row types, guardReporter,
reporterForReliableDelivery, the telemetry cursor (reader/writer, schema
and common-schema definition), the eval telemetry/ directory, the
graph.json read the reporter needed, the proper-lockfile dependency, and
utils helpers only the pump used. boundedResponseText moves into
scoring.ts next to the LLM judge, its only caller.

The execution-policy fingerprint inputs are unchanged, so published
history stays comparable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(evals): delete the automatic eval-history publication leftovers

#1131 deleted the eval-benchmarks and eval-history-publication workflows,
and docs/how-to/run-evals.md already says there is no automatic history
publisher. Their producer and handoff checks stayed behind:
history-publication.ts, its plan and generation schemas and semantic
gates, and the `automatic` / `plan-rows` / `policy` commands of
scripts/ci/prepare-eval-history-publication.mjs. Nothing runs them.

The script keeps only the exports that validate-modal-benchmark-launch.mjs
and prepare-modal-benchmark-cleanup.mjs import (manifest, pair-config and
policy-checkout validation) and the helpers they reach; its CLI entry, the
bundle-summary and plan-row code, and the TypeScript source-constant
parser go. Tests of the deleted paths go with them; the strict-manifest
reader test now targets readBenchmarkControlManifest, which still uses
that reader.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(evals,cli): delete `eval history --max-age-days`

The flag and assertEvalHistoryRecency existed for the scheduled
benchmark-history freshness monitor, which #1112 removed. No workflow,
script or doc passes the flag any more.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(evals): stop rendering the six per-metric eval-history charts

README.md embeds only the three overview charts (quality,
latest-summary, performance-cost). The precision, recall, F1,
cumulative-true-positive, wall-clock and cost SVGs were still generated
and byte-checked by `eval history --check`, but nothing links to them.
Their renderer and assets go. The three kept charts render
byte-identically: `eval history --check` passes against the checked-in
SVGs.

Tests that used a per-metric chart to observe supersession or
completeness now read the same commit links and completeness attributes
from the overview charts; the tests of per-metric layout details go.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(evals,evmbench): delete exports nothing calls

- read/write/parseEvalPublicationState, the publication-state schema and
  its common-schema definitions, and the EvalPublicationState types: left
  over from the retired `eval publish`; only tests used them. The CLI
  `json validate` eval-schema test now uses the ground-truth schema.
- assertEvalReportAuthorityRemainedCurrent, isEvalNodeStatus,
  EVAL_EXPANSION_SOURCE_NODE_KEY and evmbenchSchemaPath: no caller in
  any package or script.
- validateBenchmarkControlManifest and the testReportingPolicy test
  helper are only used inside their own modules, so they are no longer
  exported.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(changelog): record the eval dead-code removals

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(evals): re-read run state after the watch loop before classifying a row

Deleting the telemetry pump also deleted the state.json re-read that
followed the final drain. When the watch deadline passed during the last
poll sleep, the row was then classified from the state read before that
sleep. The watch is not the only writer of state.json: `ultrafuzz status`,
`inspect` and the dashboard synchronize the run too. A run one of them
made terminal during that sleep was recorded as timed-out, with an
EVAL_ROW_WATCH_TIMEOUT diagnostic and a `running` workflow lifecycle,
and counted as incomplete. origin/main recorded its real terminal status.

Restore the single read, as origin/main had it.

The new watchEvalRow test polls once with a 1 s deadline and a 1.5 s
sleep, and a timer writes the terminal run 300 ms after that poll. It
passes on origin/main (test ported with `reporters: []`), fails on the
previous branch head with final_status "timed-out", and passes with this
change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(evals): stop describing eval runs as keeping telemetry

With the pump gone, eval runs write no telemetry, and the suite's
`reporting.artifacts` policy has no reporter to stream to. Two docs
still said eval runs retain telemetry, and the EvalArtifactPolicy and
EvalTarget.sensitivity comments still described payload streaming and
manifest-only artifact reporting.

The docs and the default suite comment also said "nothing reads" the
artifacts policy. That overstated it: normalizeReporting still computes
it, and `eval plan --json` and the Modal worker still carry it. They now
say no eval behaviour depends on it. The `sensitivity` comment now names
what `private` does enforce: ground truth bound to the target's repo and
ref, and ULTRAFUZZ_EVAL_JUDGE_ALLOW_PRIVATE_DATA before an LLM judge
receives the data.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
aviggiano added a commit that referenced this pull request Sep 29, 2026
…rphaned by #1131 (#1175)

* refactor(prompts): delete the unused prompt rename feature and duplicate template resolver

renamePromptId, renameConcreteNodeId and rewriteArtifactPathForPromptId
(rename.ts), their render.ts helpers (renamePromptArtifactReferences and
three private rewriters) and the frontmatter round-trip support they
needed (serializePromptDocument, diffPromptIdentity, the
allowUnknownFields option, unknownFrontmatter/rawFrontmatter and the
invalid-rename error code) had no caller outside their own tests. getPrompt
had no caller at all. TemplateOccurrence.rawName existed only so rename
could preserve whitespace.

Output-contract templates had their own three-candidate resolver whose
middle candidate, dist/prompts, is the layout the build stopped producing
in #796. They now resolve through builtInPromptRoot(), the packaged-first
lookup the agent preamble templates already use, so both kinds of prompt
asset follow one rule. The packaged-layout render test, which copies the
real dist below a directory with no repository above it, still covers the
sealed-snapshot case; the installed-layout test that rebuilt the old
dist/prompts layout is removed and its content assertions are folded into
the packaged-layout test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(config): delete the prompt-metadata layer and helpers with no production caller

- The prompt-metadata layer: resolveConfig applied
  createDefaultPromptMetadataLayer(), which always returned {}, and an
  input.promptMetadata that only one test supplied. PromptMetadataLayer,
  ResolveConfigInput.promptMetadata and the "prompt-metadata" diagnostic
  source go with it.
- restoreRedactedConfig and assertNoRedactionPlaceholders: nothing in
  runtime, cli, modal or evals calls them. Runs launch from the unredacted
  resolved config; the redacted copy and its manifest are written for
  readers of the run directory, and no command restores values from them.
  docs/config.md no longer describes a restore step or launch guard that
  does not exist. The "redaction" diagnostic source goes with them.
- applyDefaultProfileOverrides: a one-line wrapper only tests called.
  Its test now drives applyModelProfileOverrides, which validate.ts and
  plan-run.ts use.
- assertResolvedConfigZod and resolvedConfigSchemaEntry: no callers.
- resolvedConfigValidatorsAgree: moved into the schema test, its only
  user.

redactResolvedConfig and serializeRedactedResolvedConfigToml, which
plan-run.ts and init.ts use, are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ci: delete benchmark CI scripts orphaned by #1131

#1131 deleted eval-benchmarks.yml, the only workflow that invoked
scripts/ci/modal-benchmark-control-window.mjs (create/deadline) and
scripts/ci/validate-threat-model-benchmark-gate.mjs. Since then the
control-window script was kept alive only by a knip entry and a block of
ci-config.test.ts that exercised it, and the threat-model gate only by its
own test, which still ran in every PR's test:ci-scripts step.

Delete both scripts, the gate's test, the knip entry, and the
control-window block of the EVMBench full-mode manifest test; the
manifest assertions around it stay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(modal): delete unreferenced exports and move test-only helpers into tests

Deleted, no reference anywhere: MAX_MODAL_DOCUMENT_BYTES,
MODAL_SMOKE_STOP_PATH (smoke-worker.ts builds its own stop path) and
DEFAULT_NODE_TIMEOUT_SECONDS.

Deleted with the tests that only exercised them:
- createTrackedSourceArchive; production archives the exact candidate
  with createExactCandidateSourceArchive.
- persistentWorkspaceRoot.
- locateModalResumeWorkspace, documented as "retained for tests"; worker.ts
  uses findModalResumeWorkspace, and the removed "locates one exact linked
  durable run" test duplicated the existing tolerant-lookup test. The two
  finalize tests unwrap findModalResumeWorkspace through a local helper.

Moved into tests, their only users:
- DEFAULT_BENCHMARK_MODELS, a stale model list no production code reads,
  is now test/model-spec-fixtures.ts, typed as a const tuple so indexed
  fixtures need no non-null assertion.
- modalBenchmarkConfigValidatorsAgree, WORKER_RESULT_ALLOWED_KEYS (the
  test now states the expected persisted key set), and
  publicEvalFailureDiagnosticLogPayload, which composed the same two calls
  runCommand already makes inline.
- PUBLIC_BENCHMARK_MAX_PARALLEL_EVAL_ROWS and its full-lane twin, aliases
  of the evals lane limits that only a test imported.

Un-exported, used only inside their own module: five public-worker
constants and WORKER_STDERR_TAIL_BYTES. The source-constant reader in
prepare-eval-history-publication.mjs matches top-level const
declarations with or without export, and its test against the real
public-worker.ts still passes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(dashboard): drop the always-false command capabilities

commandCapabilities() returned restartWholeRun, doctor, triage, merge,
restartFromNode, rerunSelectedNode and arbitraryShell as the constant
false. The frontend only declared them in its CommandCapabilities type:
capabilityForCommand never maps a command to any of them, so nothing read
them.

Remove them from the server, the dashboard HTTP schema's
commandCapabilities definition, and the frontend type. The schema edit
is required because that definition is closed (required plus
additionalProperties: false). The dashboard schema feeds neither the
validator build identity, which hashes only the artifacts validator
modules and the ajv versions, nor the artifact schema bundle digest that
planned outputs and the trusted CLI identity bind to.

The flow test's two assertions that doctor and merge are false are
removed. Every dashboard HTTP response in the tests is still validated
against the schema, so a server that emitted one of these keys again
would fail the flow test with "must NOT have additional properties"
(checked by re-adding doctor: false to the compiled server).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore(runtime): drop the unused run-tests selectors

packages/runtime/package.json calls scripts/run-tests.mjs with no
selector or with "supporting"; nothing passes "materialize", "clean" or
"smithers". A single test file can still be selected by name through the
existing fallback.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(changelog): record the dead-code deletions

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(prompts): leave getPrompt to the catalog work item

getPrompt still has no caller, but #1164 adds
projectPromptsDifferingFromBuiltIns directly above it in catalog.ts, so
deleting it here made the two PRs conflict textually
(git merge-tree reported CONFLICT (content) in catalog.ts). catalog.ts is
outside this change's files, so restore it to origin/main and leave the
deletion for a follow-up once #1164 lands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(changelog): state the dead-code entry only as strongly as the evidence

Drop getPrompt, which this change no longer deletes. Name the actual
callers of the two CI scripts (eval-benchmarks.yml and the
watch-modal-benchmark.sh it ran, both deleted in #1131) instead of "the
workflows #1131 deleted": the other two workflows #1131 removed never
invoked either script. Stop describing the config prompt-metadata layer as
code no production path calls: resolveConfig ran it on every resolution,
only ever with an empty layer. Mention the run-tests.mjs selectors and the
docs/config.md change, and add the [runtime] and [docs] tags for them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remove paid benchmark CI and retire API credentials; stabilize offline CI

1 participant