Harness Architecture¶
Harness is a local-first middleware for objective challenge optimization runs. Agents do not talk directly to HighLoad, Tensara, CPU.mode, GitHub PR challenges, or future platforms. They talk to Harness. Harness owns credentials, submissions, result normalization, immutable evidence, logging, and reports.
The core rule is:
agents submit candidates; Harness owns the venue connection and the ledger
Repository Boundary¶
This repository contains the server side:
- HTTP daemon and web UI
- agent-facing CLI
- connector layer for challenge platforms
- SQLite ledger and immutable candidate bundles
- credential storage and scoped run tokens
- deterministic reports and dashboards
The agent instructions live separately in the Harness Agent skill repository:
https://github.com/josusanmartin/scorebench-skill
The skill should teach an agent how to use the Harness API and CLI. It should not contain connector secrets, server internals, or challenge platform API keys.
High-Level Shape¶
external challenge platforms
+----------------------------+
| HighLoad / Tensara / CPU |
| GitHub PR / Kaggle / ... |
+-------------+--------------+
^
|
connector layer
|
+-------------+ +---------------------+---------------------+
| Harness user | ----> | harness daemon / web UI |
| browser | | challenge_harness.daemon |
+-------------+ +---------------------+---------------------+
|
v
HarnessService
challenge_harness.service
|
+------------------------------+------------------------------+
| | |
v v v
SQLite ledger credential store report builder
challenge_harness.db secret env files / metadata challenge_harness.report
^
|
+------------+------------+
| solving agent workspace |
| harness CLI + run token |
+-------------------------+
GitHub can render the same system as a Mermaid diagram:
flowchart TB
Admin["Harness user browser"]
Agent["Solving agent workspace"]
CLI["harness CLI"]
Daemon["Harness daemon and web UI<br/>challenge_harness.daemon"]
Service["HarnessService<br/>challenge_harness.service"]
DB[("SQLite ledger<br/>harness.sqlite")]
Credentials["Credential store<br/>encrypted secret files and metadata"]
Bundles["Immutable candidate bundles"]
Reports["Reports and dashboards<br/>challenge_harness.report"]
Connectors["Connector layer<br/>challenge_harness/connectors"]
Platforms["External challenge platforms<br/>HighLoad / Tensara / CPU.mode / GitHub PR / ..."]
Admin --> Daemon
Agent --> CLI
CLI --> Daemon
Daemon --> Service
Service --> DB
Service --> Credentials
Service --> Bundles
Service --> Reports
Service --> Connectors
Connectors --> Platforms
Reports --> Daemon
There are two important security boundaries:
- Harness users manage their own credentials and create scoped exercise or run tokens.
- Agents receive only a scoped Harness token, never the underlying connector credential.
The public deployment can expose more than one product origin without running
multiple writers against the SQLite ledger. scorebench.dev serves the general
benchmark product, while paradigm.scorebench.dev serves the Paradigm Puzzles
agent workflow. The daemon derives the product surface from an exact hostname
allowlist, changes navigation and landing behavior, filters runs and credential
controls, and scopes generated report payloads to the matching connector. Both
origins still share the service layer, queue, credentials, and authoritative
ledger.
Main Components¶
Daemon And Web UI¶
challenge_harness.daemon runs the local or public HTTP service. It serves:
- user login
- credential management
- exercise/run token creation
- dashboards and reports
- agent API endpoints used by the
harnessCLI - static assets such as CSS, reports, and favicon
The daemon is intentionally thin. It parses HTTP requests, renders pages, and
delegates most business logic to HarnessService.
HarnessService¶
challenge_harness.service.HarnessService is the orchestration layer. It owns
the rules for:
- admin authentication and session behavior
- credential profile lookup
- exercise/run token validation
- run start, run current, run progress, run ping, and usage accounting
- run-scoped post-run trace artifact validation and retrieval
- candidate submission validation
- idempotency and duplicate-content checks
- connector execution
- pending result refresh
- report generation triggers
If the behavior affects correctness, security, or accounting, it belongs in the service layer rather than in HTML templates or connector-specific code.
SQLite Ledger¶
challenge_harness.db.HarnessStore is the durable ledger. The database lives in
the run directory as harness.sqlite.
The ledger records the facts that reports should trust:
- experiment and run metadata
- credential profile bindings
- scoped exercise/run tokens
- candidate sequence numbers
- content hashes
- immutable bundle locations
- submission timestamps
- connector status and raw response metadata
- normalized scores
- token snapshots and usage deltas
- run heartbeats and elapsed-time evidence
SQLite is used because the system is local-first, transactional, easy to back up, and simple to inspect when debugging.
Sanitized agent traces are intentionally not stored in SQLite. The skill
produces bounded gzip NDJSON only after a run; the service validates and stores
it under artifacts/run_traces/ using a hash-derived run scope and trace ID.
Trace upload/download is observational, never triggers report generation, and
does not affect run activity or candidate state.
Agent CLI¶
challenge_harness.cli provides the harness command used by solving agents.
It reads:
HARNESS_URLHARNESS_RUN_TOKEN
Then it calls the daemon for:
harness contextharness exerciseharness run startharness run currentharness run progressharness run pingharness run usageharness submitharness invalidateharness reinstateharness refreshharness bestharness historyharness solution
The CLI creates deterministic candidate bundles from files or directories and sends them to the server. It does not need platform credentials.
harness run progress is the stable supervisor-facing accounting contract. It
uses the same canonical timing and token normalization as reports, is restricted
to one run-token scope, and does not add a heartbeat when polled. Dashboard
markup and /best are presentation and best-candidate views, not progress
measurement APIs.
Connector Layer¶
Connectors live under challenge_harness/connectors/. A connector translates a
Harness candidate into a platform-specific action and normalizes the result.
Connectors can also expose scoped discovery data through the daemon, such as
HighLoad leaderboards, solution lists, challenge-page sections, and solve-form
defaults. HighLoad discovery includes language metadata and default filenames so
agents can choose CPP, GO, RUST, CSHARP, ZIG, or configured safe
language ids without receiving the underlying cookie.
Current connector shapes include:
highload: cookie-authenticated HighLoad submissions and status refreshlocal_tensara: Tensara CLI/API-key backed submissions to the private/local Tensara deploymentpublic_tensara: Tensara CLI/API-key backed submissions to public Tensaracpumode: CPU.mode credential and submission integrationgpumode: GPU Mode / Popcorn proxy submissionsvliw: credentialless, queued ScoreBench VLIW judging scored in cyclesgithub_pr: PR-based challenge transportfake: deterministic test connector
Connectors are deliberately small. They should know how to talk to a platform, but they should not decide experiment policy, token accounting, run ownership, or dashboard semantics.
Submission Flow¶
The normal flow is:
1. A Harness user logs in to the Harness UI.
2. The user saves one or more named credential profiles for a connector.
3. The user creates an exercise API key scoped to:
user + connector + credential profile + exercise.
4. The user gives the generated environment block to the agent.
5. Agent runs `harness context` and `harness exercise`.
6. Agent starts or resumes a named run with `harness run start`.
7. Agent submits candidates with `harness submit`.
8. Harness validates token scope, run name, exercise, idempotency, token usage,
and candidate metadata.
9. Harness writes the candidate bundle and ledger rows before connector work.
10. Connector submits or evaluates against the external platform.
11. Harness stores the normalized result and raw evidence.
12. If a candidate is later found invalid, the scoped agent can run
`harness invalidate` to mark it `invalidated` without deleting evidence.
13. If a contract review reverses that decision, `harness reinstate` appends a
linked audit event and restores the captured prior status.
14. Reports are generated from the ledger and immutable artifacts.
The same flow as a sequence diagram:
sequenceDiagram
participant User as Harness user UI
participant Agent as Solving agent
participant CLI as harness CLI
participant Daemon as Harness daemon
participant Service as HarnessService
participant Store as SQLite ledger
participant Connector as Connector
participant Platform as External challenge
participant Report as Report builder
User->>Daemon: Save connector credential profile
Daemon->>Service: create credential profile
Service->>Store: store profile metadata
Service-->>Daemon: credential saved
User->>Daemon: Create scoped exercise API key
Daemon->>Service: create run token scope
Service->>Store: store token record and scope
Service-->>Daemon: show token once
User-->>Agent: HARNESS_URL + HARNESS_RUN_TOKEN
Agent->>CLI: harness context / exercise
CLI->>Daemon: authenticated request
Daemon->>Service: validate token
Service->>Store: load token scope
Service-->>CLI: scoped connector + exercise context
Agent->>CLI: harness run start --id run001 --skills ... --model ... --coding-harness ... --effort ... --autonomy ...
CLI->>Daemon: start or resume run
Daemon->>Service: validate run name and policy
Service->>Store: record run metadata
Service-->>CLI: active run
Agent->>CLI: harness submit solution file
CLI->>Daemon: candidate bundle + metadata + token snapshot
Daemon->>Service: validate and allocate candidate
Service->>Store: write candidate row and evidence
Service->>Connector: submit/evaluate with server-held credential
Connector->>Platform: platform-specific request
Platform-->>Connector: raw result or pending status
Connector-->>Service: normalized result + raw evidence
Service->>Store: store score/status/evidence
Service->>Report: regenerate or mark reports stale
Service-->>CLI: authoritative submission response
This lets the agent focus on solving the problem. The agent should not need to know whether the backend is a form POST, a CLI command, a GitHub pull request, or a polling API.
Credential Model¶
Credentials are named profiles per connector. Examples:
connector: highload
profile: skill-research
secret: HIGHLOAD_COOKIE
connector: local_tensara
profile: no-skill
secret: TENSARA_API_KEY
connector: cpumode
profile: quant-agent
secret: CPUMODE_API_TOKEN
The web UI manages these profiles. Agents never receive these secrets.
The run token given to an agent is scoped to a specific user, connector, credential profile, and exercise. This keeps runs isolated:
agent token can submit to one exercise with one credential profile
agent token cannot list credentials
agent token cannot inspect sibling runs
agent token cannot switch to another connector
Run bearer tokens are shown only in the creation or rotation response. SQLite stores a SHA-256 token digest and prefix, not recoverable plaintext. Reissuing an active token creates a replacement with the same scope and immediately revokes the old token.
User passwords use salted PBKDF2-SHA256 hashes. A successful login against a legacy unsalted SHA-256 record upgrades that record in place; login and registration attempts are throttled per client.
Resource Boundaries¶
Run-scoped submission budgets are enforced under the candidate-allocation lock:
- candidate count per run
- cumulative compressed candidate-bundle bytes per run
- normalized working-token total per run
- distinct candidates per rolling time window
- repeated submissions of the same bundle per rolling time window
The defaults are conservative and can be overridden by the experiment's
submission_limits mapping. Submission windows are calculated from persisted
candidate timestamps and survive daemon restarts. Idempotent response recovery
happens before budget consumption, so replaying the original request key remains
safe even while a window is full. Post-run traces have independent per-upload, count, and aggregate
compressed-byte limits. HTTP request bodies are length-bounded and read with a
socket timeout; the request ceiling includes base64 expansion of the 64 MiB
candidate-bundle limit, and the threaded HTTP server has a fixed worker ceiling
plus a smaller semaphore for concurrently buffered bodies above 1 MiB.
Sensitive dynamic responses and trace downloads are marked Cache-Control:
no-store.
Cross-run code-similarity warnings combine an exact normalized-token digest,
64-bit simhash for structural edits, and a compact bottom-k shingle-containment
sketch for additive padding. Indexed simhash and containment anchors nominate a
small candidate set before scoring. Solutions with 16-79 normalized tokens get
exact-match coverage only; approximate checks start at 80 tokens to limit false
positives on short boilerplate. For exercises with a trusted public starter,
ScoreBench removes that starter's normalized shingles before comparison and
requires at least 32 residual shingles, including for exact matches. This keeps
tiny identical edits around the starter from becoming evidence of copied
solution code. Fuzzy checks additionally require at least 80 residual shingles
on both sides; the total token count cannot make a small customization look
substantial. Residual containment also uses a 0.90 minimum instead of the
raw-code 0.72 threshold and requires residual sizes to be within 2x. Exact and
SimHash matches keep their normal rules above the residual floor. The registry is
keyed by connector and
exercise, so only an explicit, versioned template can be discounted; learned
corpus-common code is never silently ignored. Existing raw fingerprints remain
compatible through residual containment, so enabling a template does not require
a database backfill for new submissions. Historical annotations can be rebuilt
from immutable, hash-verified bundles with
scripts/recalculate_code_similarity.py; the command is dry-run by default,
creates an online SQLite backup before applying, preserves unrelated warnings,
and is expected to produce a zero-change second dry-run. Production maintenance
uses --registered-template-scopes-only so unrelated binary challenge bundles
are not traversed. Similarity remains an audit warning, not an automatic
rejection.
The offline replay summary includes non-source metadata for every resulting flag: candidate and run IDs, score, match reason, distance, containment, and residual sizes. This makes threshold changes auditable before a guarded apply without exposing submitted code.
Connector Responsibilities¶
A connector should provide a narrow contract:
- declare its credential schema for the UI
- list or validate supported exercises when possible
- return an exercise statement or instructions
- submit or evaluate a candidate bundle
- refresh a pending result when the platform is asynchronous
- normalize score, status, direction, and remote IDs
- preserve useful raw response metadata for debugging
A connector should not:
- trust agent-provided scores
- read another credential profile
- decide A/B grouping
- mutate unrelated runs
- hide platform errors from the service layer
Conceptually, every connector sits behind the same boundary:
flowchart LR
Bundle["Candidate bundle<br/>source files + metadata"]
Scope["Validated token scope<br/>user + connector + credential + exercise + run"]
Service["HarnessService"]
Schema["Connector credential schema"]
Connector["Connector implementation"]
Credential["Server-held credential profile"]
Platform["Challenge platform"]
Result["Normalized AdapterResult<br/>status + score + direction + remote id + raw evidence"]
Store[("SQLite ledger")]
Bundle --> Service
Scope --> Service
Service --> Schema
Service --> Credential
Service --> Connector
Credential --> Connector
Connector --> Platform
Platform --> Connector
Connector --> Result
Result --> Service
Service --> Store
Database And Evidence Model¶
Harness stores both normalized data and evidence.
Normalized data is what the dashboard uses:
candidate_id
run_name
credential_profile
connector
exercise
status
score
score_unit
direction
tokens_total
tokens_delta
active_seconds
remote_submission_id
Evidence is what lets us debug and audit:
server_received_at
server_completed_at
request hash
bundle hash
source hash
raw connector response
connector logs
trace id
remote URL or submission id
refresh attempts
warnings
The dashboard should be reproducible from the ledger and immutable bundles. It should not depend on agent-written progress files as authoritative data.
The current database has implementation-specific details, but the core ledger relationship is:
erDiagram
USERS ||--o{ CREDENTIAL_PROFILES : owns
USERS ||--o{ RUN_TOKENS : receives
CREDENTIAL_PROFILES ||--o{ RUN_TOKENS : scopes
CONNECTORS ||--o{ CREDENTIAL_PROFILES : defines
CONNECTORS ||--o{ EXERCISES : provides
EXERCISES ||--o{ RUN_TOKENS : scopes
RUN_TOKENS ||--o{ RUNS : starts
RUNS ||--o{ CANDIDATES : contains
CANDIDATES ||--|| BUNDLES : stores
CANDIDATES ||--o{ SUBMISSION_RESULTS : records
CANDIDATES ||--o{ USAGE_SNAPSHOTS : accounts
CANDIDATES ||--o{ TRACE_EVENTS : explains
SUBMISSION_RESULTS ||--o{ RAW_EVIDENCE : preserves
USERS {
string username
string role
}
CONNECTORS {
string name
string credential_schema
}
CREDENTIAL_PROFILES {
string name
string connector
string owner_user
string encrypted_secret_ref
}
EXERCISES {
string connector
string exercise_id
string title
}
RUN_TOKENS {
string token_hash
string user
string connector
string credential_profile
string exercise_id
}
RUNS {
string run_name
string credential_profile
string exercise_id
}
CANDIDATES {
string candidate_id
string content_sha256
string status
}
SUBMISSION_RESULTS {
string remote_submission_id
float score
string status
string direction
}
Timing, Token, And Cost Accounting¶
Harness can trust server-observed facts:
- when the request arrived
- when the connector returned
- candidate sequence number
- bundle hash
- raw platform response
- normalized platform score
Harness cannot inherently know true model token usage unless the runner or provider reports it. For that reason token data is recorded with provenance.
Agents are required to submit token snapshots when using the Harness workflow. Harness stores totals and computes deltas server-side. If token data is missing, the service should reject or warn according to the current policy rather than silently producing empty token charts.
Provider aggregates are not universally comparable. In particular, Grok's aggregate includes cached reads, so the service requires a disjoint input/output/cache-read breakdown for Grok models and recomputes the working total server-side.
Run pings and usage snapshots give the dashboard a better view of active work than wall-clock timestamps alone. This matters when an agent session expires, idles, or is interrupted for unrelated reasons.
Active time is explicitly an estimate. Reports retain its source, raw wall value, and cumulative idle time removed for each candidate. Candidates where at least half of clock time was excluded receive a distinct chart marker and tooltip explanation. If submitted timestamps are unavailable, the fallback caps each inter-candidate gap independently instead of collapsing all later candidates to one timestamp.
Cost is a report-time derived field, not an authoritative provider invoice.
The report builder prices model token categories with the versioned hardcoded
table in challenge_harness.model_pricing; legacy aggregate-only runs receive a
visibly marked estimate. Unknown and composite models remain unpriced. See
API Cost Accounting.
Pending And Stale Results¶
Some platforms return a result immediately. Others take minutes and require polling.
The connector layer can return a pending status. Harness records that state and uses refresh paths to complete the result later:
submitted -> pending -> accepted
submitted -> pending -> rejected
submitted -> pending -> error
This is important for platforms such as HighLoad, where the challenge page may
show completed submissions later than the original submit request. A stale
refresh worker or explicit harness refresh should reconcile those results so
the ledger does not permanently undercount completed attempts.
Reports And Dashboard¶
challenge_harness.report builds deterministic report artifacts from the
SQLite ledger and candidate bundles.
Important outputs include:
- strategy comparison dashboard
- per-exercise report JSON
- run summaries
- TSV/CSV exports for analysis
- raw evidence links where available
The primary dashboard is the strategy comparison view. It compares runs by:
- connector
- exercise
- credential profile
- run name
- score trajectory
- active time
- wall time
- token spend
- API-equivalent model cost
- failures and rejected candidates
- promotions and best-so-far changes
Invalidated candidates are preserved for auditability but excluded from best, best-so-far curves, promotion decisions, and dashboard winner calculations.
The dashboard should answer:
Which strategy improved fastest under the same budget?
Which strategy reached the best final score?
Which strategy spent fewer tokens or less active time?
Which strategy reached a score under the lowest API-equivalent cost?
Which failures were platform errors versus rejected candidates?
The reporting pipeline is one-way: reports are derived from the ledger, not the other way around.
Report generation is isolated from the live submission path:
- writable service connections use SQLite WAL mode;
- report builders open every ledger with a true read-only, query-only connection and never run migrations;
- every output is written to a temporary file and atomically replaced;
.report-manifest.jsonrecords a source fingerprint for each artifact, so a targeted refresh cannot make unrelated stale pages appear fresh;- concurrent refresh requests are coalesced, and requests that arrive during a render are handled by a bounded catch-up loop;
- if the source changes while a report is rendering, the generated artifact remains stale and is rendered again;
- a normal stale page is served immediately while its replacement renders in the background.
Full generation still writes the compatibility JSON, CSV, TSV, SVG, compare, and export artifacts. A stale exercise page uses incremental generation: exercise topology and run-count summaries come from the manifest, only the requested exercise data is rebuilt, and only the requested compare/data or export artifacts are atomically replaced.
Interactive compare pages contain the application shell rather than the full
candidate history. The shell fetches compact
strategy-compare-<connector>-<exercise>.json; a deterministic .json.gz
sidecar is retained as an artifact, while the daemon caches viewer-scoped gzip
responses so privacy filtering does not require repeated parsing or compression.
Dashboard query filters can be applied before JSON transfer. Export pages stay
self-contained so downloaded presentations work offline.
Generated comparison payloads retain all runs. The HTTP layer scopes each JSON response at request time: authenticated owners receive their locally visible runs, while anonymous and Public runs views receive only runs explicitly published by their owners. Local hide state therefore cannot remove a run for another viewer or accidentally make a private run public.
The admin web keeps chart viewing and report management on separate routes:
/ui/reports/redirects to/ui/reports/strategy-compare.html, the interactive chart dashboard./ui/runsis the personal Runs index: searchable run history, isolated dashboard links, local hide/show, explicit public publication, and permanent deletion. Publication is an allowlist: a run without a publication row is private./ui/keyscreates and manages scoped exercise API keys under Account./ui/docs/serves the generated MkDocs site and its search index from the run directory.
flowchart LR
DB[("SQLite ledger")]
Bundles["Immutable bundles"]
Raw["Raw connector evidence"]
Builder["Report builder<br/>challenge_harness.report"]
JSON["report.json<br/>exercise-report.json<br/>compact dashboard JSON + gzip"]
TSV["TSV / CSV exports"]
HTML["strategy-compare.html<br/>application shell"]
Manifest[".report-manifest.json<br/>freshness + summaries + timings"]
UI["Web UI report pages"]
DB --> Builder
Bundles --> Builder
Raw --> Builder
Builder --> JSON
Builder --> TSV
Builder --> HTML
Builder --> Manifest
JSON --> UI
HTML --> UI
Logging And Tracing¶
Harness should log enough to debug connector issues without exposing secrets.
Useful log layers are:
- request log: HTTP method, path, status, duration, trace id
- service log: run token scope, candidate id, validation decisions
- connector log: platform request attempts, remote IDs, status transitions
- trace log: structured per-submission timeline
- error log: exceptions, connector failures, refresh failures
Secrets must be redacted from logs. The right debugging handle is the trace id, candidate id, remote submission id, and credential profile name, not the underlying cookie or API key.
GET /health includes a reports object with the active worker state, queued
scope, and last generation metrics. reports.generate.completed trace events
include total time, per-phase time, selected scopes, candidate and artifact
counts, payload sizes, and whether the source changed during generation.
Adding A New Connector¶
To add a connector:
- Create
challenge_harness/connectors/<connector_name>.py. - Define the credential schema used by the web UI.
- Register the connector in
challenge_harness/connectors/__init__.py. - Implement exercise lookup or validation.
- Implement submit/evaluate.
- Implement refresh if results are asynchronous.
- Normalize status, score, direction, and remote submission ID.
- Preserve raw response metadata for debugging.
- Add tests with fake HTTP responses or a fake CLI.
- Update the Harness Agent skill only if the agent-facing workflow changes.
The target is a connector that is boring and auditable. Platform-specific quirks should stay inside the connector, while run policy and experiment accounting stay in the Harness service and ledger.
Operational Modes¶
Harness can run locally or behind a public HTTPS reverse proxy.
Local mode is useful for private experiments:
browser -> http://127.0.0.1:<port>/ui
agent -> http://127.0.0.1:<port>
Public mode is useful when multiple users need access:
browser -> HTTPS host -> reverse proxy -> harness daemon
agent -> HTTPS host -> reverse proxy -> harness daemon
In public mode, per-user credential isolation matters. A signed-in user should only see and manage their own credential profiles unless explicit admin tooling is added for cross-user operations.
Design Principles¶
- Keep agents lightweight: one run token, simple CLI commands, no platform keys.
- Keep the ledger authoritative: reports come from SQLite and immutable bundles.
- Keep connectors narrow: submit, refresh, normalize, preserve evidence.
- Keep credentials server-side: agents never receive cookies or API keys.
- Keep reports deterministic: fixed ordering, stable schemas, reproducible HTML.
- Keep failures visible: connector errors should be recorded and returned.
- Keep experiments isolated: one credential profile and one run scope per token.