Skip to content

Bradley/stackbench test - #5766

Draft
bradleyshep wants to merge 115 commits into
masterfrom
bradley/stackbench-test
Draft

Bradley/stackbench test#5766
bradleyshep wants to merge 115 commits into
masterfrom
bradley/stackbench-test

Conversation

@bradleyshep

Copy link
Copy Markdown
Contributor

Description of Changes

This PR adds Stack Bench, a reproducible benchmark for coding agents building applications against SpacetimeDB, PostgreSQL, and MongoDB.

Benchmark definitions and grading

  • Adds versioned tracks, levels, feature packs, specification packs, recipes, prompts, checks, and dependency declarations.
  • Supports selecting complete recipes, individual packs, or individual checks.
  • Separates what the agent is asked to build from what the finished application is evaluated against.
  • Adds typed scenario actions for browser interaction, authenticated server calls, concurrent operations, direct database writes, reconnects, reloads, and service lifecycle operations.
  • Records each check as passed, failed, inconclusive, or harness_failure.
  • Keeps the declared score denominator fixed when evidence is missing or inconclusive.
  • Adds reference, mutation, and null-control qualification:
    • reference applications for all three stacks;
    • source-bound mutation manifests;
    • exact mutation-target and collateral-failure validation;
    • blank-application controls;
    • versioned calibrations and promotion catalogs.
  • Adds immutable identities for recipes, prompts, fixtures, mutations, checks, runtime images, adapters, and evidence.

Ecommerce benchmark

  • Adds ecommerce L1 coverage for accounts, sessions, storefronts, carts, checkout, purchases, warehouses, reviews, authorization, accounting, concurrency, live updates, persistence, reconnects, and direct database writes.
  • Adds ecommerce L2 coverage for fulfilment, shipping, warehouse transfers, cancellations, returns, historical pricing, operational views, recommendations, authorization, stock conservation, and refund accounting.
  • Adds complete ecommerce reference applications for MongoDB, PostgreSQL, and SpacetimeDB.
  • Promotes qualified ecommerce L1 modular 2.4.
  • Keeps ecommerce L2 1.4 as the promoted L2 release.
  • Adds L2 1.5 as a draft cumulative successor based on L1 2.4:
    • 76 checks;
    • 117 available points;
    • static mutation coverage for all 74 scored checks on every supported stack;
    • candidate reference fixtures, mutation manifests, and calibration;
    • live qualification still required before promotion.

Runs, repairs, and campaigns

  • Adds bounded correction rounds with rollback when a repair loses previously established evidence.
  • Stops cumulative execution when a lower level remains incomplete.
  • Adds source checkpoints and operator-granted continuation rounds without rewriting the original result.
  • Adds campaign manifests containing exact stacks, repetitions, parallelism, recipes, models, pricing, prompt treatments, and correction budgets.
  • Supports concurrent attempts of the same or different stacks using isolated ports, databases, modules, containers, work directories, leases, and result directories.
  • Adds durable campaign scheduling, retries, locking, interruption recovery, reconciliation, and cleanup.
  • Preserves invalid and interrupted attempts instead of presenting them as comparison data.
  • Adds reproducible JSON and HTML reports with scores, coverage, cost, tokens, elapsed time, correction rounds, raw evidence, screenshots, videos, traces, and prompts.

CLI, dashboard, and appliance

  • Adds Stack Bench CLI commands for runs, campaigns, preflight, qualification, composition, repair continuations, recovery, release verification, and reporting.
  • Adds a Dockerized local dashboard that reads and controls the same durable campaign state as the CLI.
  • Adds a Linux/amd64 Docker appliance with pinned controller and build images, preflight checks, resource leases, reference qualification, release identity verification, and recovery tooling.
  • Adds model-free reference adapters and campaign trials for testing orchestration without provider spend.
  • Adds retained grader stdout/stderr and structured browser-initialization evidence.
  • Hardens process cleanup, destructive filesystem operations, campaign locks, recovery authority, credential redaction, and failed teardown handling.
  • Prevents local notes, generated reports, media, runtime state, and mutation scratch files from entering controller image builds.

SpacetimeDB TypeScript SDK

  • Changes exported TableRef from an anonymous readonly type alias to a readonly interface with the same members.
  • Produces shorter, named TypeScript diagnostics when a TableRef is used incorrectly.
  • Changes automatic ConnectionManager reconnects to reuse the identity token previously issued by the server.
  • Keeps explicit connection rebuilds bound to the token supplied by the caller.
  • Adds unit tests for reconnect token reuse and TableRef diagnostics.
  • Adds an opt-in live-host reconnect identity test.

SpacetimeDB CLI

  • Changes spacetime dev to retain configuration changes made during direct-login publishing.
  • Reuses that authenticated configuration for log streaming and subsequent rebuilds.

SpacetimeDB skills

  • Expands the TypeScript, Rust, and C# server skills with examples and guidance for client visibility filters, procedures, HTTP endpoints, indexes, and uniqueness constraints.
  • Updates the TypeScript client skill’s authentication and reconnect guidance.

API and ABI breaking changes

This PR changes the public Rust signature of:

spacetimedb_cli::publish::exec_from_entry

The function now accepts &mut Config instead of taking Config by value. External Rust callers must pass a mutable reference. The API-breaking label should be applied unless the previous entry point is preserved through a compatibility wrapper.

The exported TypeScript TableRef declaration changes from a type alias to an interface while retaining the same readonly member contract.

Automatic TypeScript client reconnection also changes behavior by presenting the identity token from the previous successful connection.

Expected complexity level and risk

3 / 5

Most of the implementation is isolated under tools/stack-bench. The principal risks are benchmark correctness, evidence integrity, concurrent resource isolation, interrupted-run recovery, Docker cleanup, and credential handling.

The TypeScript reconnect change and spacetimedb-cli helper signature are the only changes outside the benchmark and skill directories.

Testing

  • Stack Bench host suite: 602 tests, 599 passed, 0 failed, 3 Windows-specific skips.
  • Composition validation: 51 packs, 13 recipes, and 677 selected checks.
  • All calibration manifests compile.
  • All registered reference fixtures pass source and registry validation.
  • Scenario validation completes with 0 errors.
  • All 27 prompt snapshots match.
  • All 4 definition goldens match.
  • TypeScript reconnect and TableRef regression tests: 4/4 passed.
  • cargo check -p spacetimedb-cli.
  • Ecommerce L1 2.4 null control: 0/58.
  • Ecommerce L1 2.4 references: 58/58 on MongoDB, PostgreSQL, and SpacetimeDB.
  • Ecommerce L1 2.4 mutation qualification:
    • MongoDB: 44/44 defects caught;
    • PostgreSQL: 45/45 defects caught;
    • SpacetimeDB: 46/46 defects caught.
  • Controller build-context regression coverage.
  • Review whether to preserve the previous exec_from_entry Rust signature.
  • Run the appliance preflight and smoke test on Linux/amd64.
  • Run live Docker qualification for ecommerce L2 1.5 before promotion.
  • Run the opt-in TypeScript reconnect test against a disposable live host.

@github-advanced-security github-advanced-security AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

CodeQL found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.

@bradleyshep
bradleyshep force-pushed the bradley/stackbench-test branch from 6a1eb7d to dc1a416 Compare August 31, 2026 17:38
The overview carried plans, operations and every campaign's attempts in one
body, and the client polled it every five seconds. Give each view its own
route: the overview returns summaries, plans move to /api/plans, a campaign
returns its sheet, and an attempt's checks, evidence package and log bytes
are fetched per tab, with the log answering from a byte offset. Add
/api/campaigns/:key/progression, the catalog subgraph plus one node-status
snapshot per progression event replayed through the engine, cached per
progression-state write.

Add /api/events, a change stream fed by a recursive watch per campaign
directory with a five second fingerprint poll where the platform has no
recursive watch, so the client subscribes instead of polling, and serve the
client paths from the same shell.
A completed repair whose grade did not finish is still charged, but its
source is now kept beside the run and graded on resume instead of being
discarded and replaced by another paid session. The engine no longer
changes feature status on an inconclusive result, so a grader failure
cannot finalize a feature or open its children.

Exhaustion reasons name the limit that ran out (feature, depth, total)
or the stall detector. The stall detector seeds on the first observation
of a failure again and counts only completed repairs. Features whose
shared budget ran out are finalized after any conclusive result rather
than being offered a repair with nothing left. Sequential and dependency
runs share one repair allowance. The initial grade retries once on a
grader failure. The dashboard parses feature repair markers, inspection
counts charged repairs from events, and the appliance guide documents
every budget field.

Dependency mode 4.1.0, mode schema 6. Tests restored for result coverage,
definition validators, replay equality, the total cap, carry false, and
rolled-back repairs; stale tests from the budget refactor fixed.
Compiled node order is dependency depth, then the order the catalog
declares its features, instead of depth then alphabetical id. Within a
depth the next repair goes to the first failed feature in that order, so
the priority is authored, part of the catalog identity every campaign
binds, and identical for every stack. The engine sorts by compiled index
and no longer compares ids. The appliance guide states the rule.
A campaign's repair plan takes an order: declared, the catalog's own
order, or shuffled, a permutation within each dependency depth drawn
from the campaign's ordering seed when the plan compiles. The permutation
is frozen in the dependency policy as nodeOrder and used by every stack
in the campaign, so no stack sees a different queue and the order is
part of the plan's identity. The feature catalog and its qualification
are unchanged; the policy identity carries the order. A declared plan
must repeat the catalog order; sequential mode rejects shuffled.

Dependency mode 4.2.0. The runtime definition and the policy compiler
order nodes from the policy and re-derive questline membership.
The dashboard test moves to its own tier under tests/dashboard, writes
its fixture evidence once, and compiles each campaign plan once; the
unit tier no longer carries it. Lease tests that spawn a second
controller and hold lock files move to the integration tier. The two
one-assertion command tests merge into cli-entrypoints.

Nine per-pack contract files that restated pack ids, points, paths and
hook names become one contract that loops over every feature pack the
graph references and asserts only rules: one whole request and interface
that composes as an upgrade, unique paths, neutral request text,
criteria that exist, distinct products across shopping criteria, one
authorization owner, declared actors on every replay, a wire or server
proof on privacy checks, and datetime-local promotion values. The two
graph-shape files merge into the progression contract. A duplicate
governance-text test is deleted and the reference campaign compiles once
per file.

The preflight capacity test derives its floors from the product
configuration and the run-suite promotion rig qualifies the recipe's
fixture and packs with the recipe, so the eight stale failures are gone.
Unit runs in about 19 seconds instead of 246; contracts in 77 instead of
97; the dashboard tier in 153 on its own.
The campaign report and dashboard read the dependency-mode final score as
passed points over every selected point, the same scale as the first
build, and carry the questline average as a secondary metric. First-try
history uses the same scale.

Dispersion is reported only from three completed attempts, and every
centre value prints its sample size. The cost line is labelled as
API-equivalent usage with tokens beside it, and reported duration
excludes recorded provider throttle waits. Session metadata records the
model ids the provider actually served.

LEVELS.md states the scoring rule, prompting.md states the repair-report
disclosure symmetry, and the grader README asks for a points rationale
in each criterion's note.
Each stack adapter now declares the grader capabilities it provides and
whether named application actions travel as HTTP routes or reducer calls.
The action registry accepts only the closed capability list. The campaign
compiler walks every selected check's setup and criterion steps for every
selected stack, requires each action's capabilities, requires the binding
the stack's transport can issue, and refuses a campaign while a stack
could not measure a selected check. A parity contract compiles the
reference graph per stack and checks identical checks, points, and
questline denominators.

The grader decodes SpacetimeDB's frame compression envelope before
searching received transport text, so message-delivery checks measure on
that stack. The two replay checks that re-issued a captured HTTP write
now carry named actions; the automatic-reorder contract names the
saveReorderRule action and requires an entity id on each rule row.
A stored check outcome is now pass, fail, or null. An application abort
leaves non-current checks at their prior value, and a check that was
never graded stays null and counts as ungraded, so a score has passed,
failed, blocked, and ungraded points only. The needs-work rule prompts a
working node only for a repairable failure.

The accepted-source regrade in the runner keeps its role for re-prompted
nodes whose checks are already graded, under the stop reason
accepted-source-regrade. Dependency mode is 4.3.0 with state schema 7;
the reference campaign and fixtures pin the new values.
Coding containers share the runner's network until the cross-run
isolation test passes. Campaign admission now refuses a plan whose
parallelism is above 1 and refuses to start while any running container
carries the Stack Bench creation label, so one attempt is active on the
runner from its first build through its final grade. Campaigns that start
no coding container are exempt. The reference campaign runs one attempt
at a time.

The leak audit extracts every URL and raw socket target from shell
commands. A local target outside the run's own web, database, and
SpacetimeDB ports contaminates the build; a blocked one is recorded as
refused; internet targets are recorded. The runner passes its own ports
to the audit.
…acts

The contamination audit now reports a harness failure when it examined no
session transcript, so a pruned or unmounted transcript store invalidates
the attempt instead of passing as clean. Adapters that run no provider
session are not audited.

Runner facts record the hostname and the number of running containers on
the Docker daemon, and preflight warns when containers that are not part
of Stack Bench share the runner. Qualification evidence keeps its
existing required observations.
An executor no longer fails with a sentence. It fails with a finding from
a closed catalog: a kind and typed fields, where a field is a contract
control name, an action id, an actor label, a number, a count, or an HTTP
status. The rendered sentence is the error message, so every reader shows
the same text. The browser boundary classifies a Playwright error into a
kind, and raw text travels only as a detail no template reads. Action and
check evidence carry the finding; the grader records each criterion's
authored sentence.

The repair report is assembled from three sources only: the sentence the
agent was already given for the behavior, the rendered finding, and the
application's console errors. The prose humaniser, the vague metric, the
quality artifact, and the scenario-value withholding are gone. The repair
policy is scored-only 1.1.0, which declares that scenario values are
withheld. An assertion whose action never ran is now inconclusive.
Other systems write the stock tables directly, and the grader's direct
write depends on their names, so the names are an interface, not a
production expectation. The warehouse-administration contract now names
the item, warehouse, and stock tables and their columns; the withheld
specification keeps only the convergence behavior. The draft
external-data-sync pack reads its own copy of the specification text so
the qualified pack is unchanged.

A direct write that cannot find the stock interface is now graded as the
application failing that interface on every stack, with the writer's
diagnostic kept as detail, instead of an inconclusive check. A contract
test walks every scored check in the reference graph and fails if a
control, attribute, route, reducer, or table it needs is absent from the
text the coding agent receives.
…app server after each criterion

An estimated request is one the credential broker charged its cost
ceiling because the provider response carried no complete usage, broke
off, or never arrived. It makes the session cost an upper bound, not
unknown, so the receipt now records exact=false with the estimated
count and reasons instead of invalidating a completed session. The
ledger names each estimate's reason; the cost ledger carries exactness
through to the run.

A criterion that stops the application server now has it started
again before the next criterion, whatever the outcome. A restore the
harness cannot complete is recorded as a cleanup failure, the feature's
remaining criteria are harness failures rather than application
failures, and a later readiness abort is attributed to the harness.
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.

2 participants