| # @maka/headless |
| |
| The single headless entry point for driving a Maka agent without a UI. Its |
| evaluation mode can run a **Config × Task** grid, capture each trajectory, |
| score it with the task's own command, and compare. |
| |
| ``` |
| Config × Task → throwaway workspace → headless agent run → trajectory |
| ↓ |
| ResultRecord (JSONL) ← verification command |
| ``` |
| |
| ## CLI |
| |
| ```sh |
| maka eval run <spec.json> [--out <dir>] |
| maka eval compare <results.jsonl> |
| maka eval task-run run <spec.json> --task <id> --config <id> [--out <dir>] |
| maka eval task-run inspect <taskRunId> --store <out>/runs [--json] |
| maka eval task-run export <taskRunId> --store <out>/runs --out <dir> [--include-events] |
| maka eval task-run resume <taskRunId> --spec <spec.json> --out <dir> [--grant-file <json>] |
| maka eval task-run retry-failed <results.jsonl|out-dir> --spec <spec.json> --out <dir> |
| maka eval ahe export <taskRunId...> --store <out>/runs --repo <repo> --out <dir> |
| maka eval harbor run --instruction <text> --workdir <dir> --out <dir> --isolation harbor-local |
| ``` |
| |
| Try it with the bundled fake-backend demo (no API key needed): |
| |
| ```sh |
| maka eval run examples/demo.spec.json --out /tmp/maka-headless-demo |
| ``` |
| |
| ## Trust posture |
| |
| `eval` is **untrusted by construction**: the config under test is something you |
| are *measuring*, possibly weak or adversarial, so it must not reach the host. |
| Without OS-level isolation the only safe enforcement is to **fail closed by |
| default**: |
| |
| - The CLI still wires only the inert **`fake`** backend. A model-backed backend |
| in a JSON spec exits non-zero unless the caller uses the programmatic API to |
| provide backend wiring. |
| - Programmatic real-model eval must pass `realBackendIsolation` to |
| `runExperiment` plus a `registerBackends` factory. The isolation record is an |
| explicit assertion that tool execution is already outside the host credential |
| process (for example Harbor / Terminal-Bench or a Docker workspace executor). |
| - The standard runners project Maka's product-tool surface once and expose it |
| as `context.productToolSurface`: it contains `Bash` plus |
| `Read`/`Write`/`Edit`/`Glob`/`Grep`, all routed through the supplied isolation |
| boundary. Parent-facing Agent tools and child-session admission are disabled |
| by default. Set `Config.agentTools: true` to opt in. The Harbor and Pier task |
| runners project that config to the canonical cell setting |
| `MAKA_AGENT_TOOLS=true`; direct Harbor cell/CLI entrypoints accept the same |
| environment setting (`false` is the default). |
| Executors can implement native file-operation methods, or rely on the |
| command-backed fallback when the isolated workspace has `node` available. |
| The headless helper rejects absolute paths, `..` escapes, and absolute glob |
| patterns before dispatching file operations. |
| |
| (An *operational* mode — intentionally running a trusted agent that *may* touch |
| the host — can slot into this same entry later. That is a different, explicit |
| trust posture, never the eval default.) |
| |
| Programmatic sketch: |
| |
| ```ts |
| import { projectEffectiveProductToolSurface } from '@maka/runtime'; |
| import { |
| runExperiment, |
| type IsolatedToolExecutor, |
| } from '@maka/headless'; |
| |
| const executor: IsolatedToolExecutor = { |
| async exec(input) { |
| // Route to Harbor/Docker/etc. Do not inherit host env/secrets. |
| return { exitCode: 0, stdout: '', stderr: '' }; |
| }, |
| async readFile(input) { |
| // Optional: implement native external workspace file reads instead of the |
| // command-backed fallback. |
| return { content: '' }; |
| }, |
| }; |
| |
| await runExperiment(config, task, { |
| storageRoot: '/tmp/maka-headless-runs', |
| realBackendIsolation: { |
| kind: 'external', |
| label: 'Harbor task container', |
| toolExecutor: executor, |
| }, |
| registerBackends(registry, context) { |
| registry.register('ai-sdk', (ctx) => { |
| const rootProductToolSurface = context.productToolSurface!; |
| const productToolSurface = ctx.tools |
| ? projectEffectiveProductToolSurface({ |
| host: 'headless', |
| tools: ctx.tools, |
| policy: rootProductToolSurface.identity.policy, |
| }) |
| : rootProductToolSurface; |
| return createAiSdkBackend({ |
| ...ctx, |
| tools: [...productToolSurface.tools], |
| toolAvailability: productToolSurface.toolAvailability, |
| }); |
| }); |
| }, |
| }); |
| ``` |
| |
| ## Spec |
| |
| A spec is `configs × tasks`. Task `workspaceDir` paths resolve relative to the |
| spec file, so a spec travels with its fixtures. |
| |
| ```jsonc |
| { |
| "configs": [ |
| { "id": "fake", "backend": "fake", "llmConnectionSlug": "fake", "model": "fake-model" } |
| ], |
| "tasks": [ |
| { "id": "fix-bug", "instruction": "Make the failing test pass.", |
| "workspaceDir": "./fixtures/fix-bug", |
| "verification": { |
| "command": "npm test", |
| "timeoutMs": 120000, |
| // REQUIRED grading boundary (see Grading). Use [] when the |
| // verification reads nothing the agent could forge. |
| "protectedPaths": ["test/"] |
| } } |
| ] |
| } |
| ``` |
| |
| ## Grading |
| |
| Verification runs the task's `command` in the workspace; exit code 0 = pass. |
| A config must not be able to grade itself, so `verification.protectedPaths` is |
| **required**: list the test/grading files and they are restored from the |
| pristine fixture *after* the agent finishes and *before* the command runs — a |
| model that rewrote its own test to pass has that edit reverted. Declare `[]` |
| only when the verification reads nothing the agent can forge — as the bundled |
| `examples/demo` does, checking a fixture file the agent has no reason to touch. |
| |
| Tasks may also use typed benchmark verifiers. Terminal-Bench is the first |
| carrier, but it is an adapter hook rather than a runtime architecture: |
| |
| ```jsonc |
| { |
| "id": "terminal-bench-local", |
| "instruction": "Solve the task.", |
| "workspaceDir": "./fixtures/tb-task", |
| "verifier": { |
| "kind": "terminal_bench", |
| "adapter": "terminal-bench", |
| "instanceId": "local-task", |
| "datasetPath": "./terminal-bench", |
| "testCommand": "./run-tests.sh", |
| "protectedPaths": ["tests/", "run-tests.sh"] |
| } |
| } |
| ``` |
| |
| `testCommand` mode runs in Maka's disposable scoring workspace and needs no |
| Docker, Harbor, or `tb` binary; because it is still a local command verifier, |
| `protectedPaths` is required. Real Terminal-Bench harness execution is wired |
| programmatically through `benchmarkAdapters` and an explicit external isolation |
| record. |
| |
| `maka eval task-run run` writes append-only task-run JSONL under `<out>/runs/task-runs/`, |
| updates compatibility `results.jsonl`, and writes a canonical export under |
| `<out>/exports/<taskRunId>/`. Exports are projection-based: they include |
| trajectory/runtime refs, submitted snapshot metadata, verifier output, score, |
| budget, isolation, permission/inbox facts, taxonomy, and warnings. They do not |
| embed environment variables, credentials, or hidden harness configuration. |
| |
| ## Terminal-Bench smoke runner |
| |
| `harbor/run-terminal-bench-smoke.mjs` is the local structured smoke harness for the |
| `terminal-bench-sample` registry dataset. It reads the checked-in profile manifest |
| `harbor/terminal-bench-smoke-profiles.json`, generates a Harbor run config under |
| `harbor/smoke-generated-configs/`, and (unless `--dry-run`) invokes Harbor with the |
| adapter directory on `PYTHONPATH`. `HARBOR_BIN` overrides the Harbor executable |
| (default `harbor` on `PATH`). |
| |
| The `maka-*` profiles drive the single authoritative adapter `maka_agent:MakaAgent` |
| in task-run host-bridge mode (`MAKA_HARBOR_MODE=task-run`): Maka runs the full |
| task-run controller on the host and bridges tool execution into the task container, |
| while the container installs nothing. `maka-heavy` and `maka-heavy-prune` carry the |
| heavy-task and autonomous prior-attempt-replay experiments; `opencode` and `oracle` |
| provide comparison and cheap dataset smoke arms. |
| |
| ```sh |
| node packages/headless/harbor/run-terminal-bench-smoke.mjs --profile maka-heavy --dry-run |
| node packages/headless/harbor/run-terminal-bench-smoke.mjs --compare --task '*sqlite-with-gcov' |
| ``` |
| |
| ## Harness A/B comparison |
| |
| `harbor/run-harness-ab.mjs` compares Maka with one pinned CLI under the same model, reasoning effort, task instructions, task order, account/provider route, and benchmark verifier while each agent retains its native runtime policy. A run resolves three named axes before creating its run root: benchmark (`MAKA_HARNESS_AB_BENCHMARK`), runtime (`MAKA_HARNESS_AB_RUNTIME`), and competitor harness (`MAKA_HARNESS_AB_COMPETITOR`). Runtime profiles own provider, model, reasoning, route, authentication mode, billing, and pricing; harness profiles own only the pinned CLI and adapter configuration. Omitting the runtime preserves existing behavior: Kimi Code and OpenCode use Kimi K3 Max, while Codex uses `gpt-5.6-sol` with `xhigh` reasoning. The A/B task order is frozen independently of Oracle evidence. Maka keeps active and stale tool-result pruning enabled while semantic compact is explicitly disabled in both the manifest and runtime environment. |
| |
| The supported compositions are deliberately sparse: Terminal-Bench 2.1 supports Kimi with Kimi Code or OpenCode, GLM-5.2 with OpenCode, and Codex with Codex; DeepSWE 1.1 supports Kimi with Kimi Code and Codex with Codex. The default `terminal-bench-2.1` benchmark binds the frozen 89-task Terminal-Bench 2.1 source to Harbor. The runner consumes an existing task tree whose ids and canonical fingerprint match the pinned revision; it does not download or duplicate that source. `deep-swe-1.1` binds the frozen 30-task DeepSWE subset to Pier (`pier` on `PATH`; the resolved `pier --version` is frozen into the toolchain and resume identity and recorded in the manifest), reads tasks from `~/.maka/eval/task-sources/deep-swe-6db64a40/tasks` by default, and grades with each task's own verifier. `MAKA_HARNESS_AB_LIMIT=5` stays the operational canary for every benchmark; the full DeepSWE profile is `30`. |
| |
| Validate the frozen task source and preview the A/B plan without reading a key or starting Harbor: |
| |
| ```sh |
| MAKA_HARNESS_AB_OUT_DIR=/path/to/out \ |
| MAKA_HARNESS_AB_TASKS_ROOT=/path/to/terminal-bench-2.1-tasks \ |
| MAKA_HARNESS_AB_RUNTIME=zai-coding-plan-glm-5.2-max \ |
| MAKA_HARNESS_AB_COMPETITOR=opencode \ |
| MAKA_HARNESS_AB_LIMIT=5 \ |
| MAKA_HARNESS_AB_DRY_RUN=1 \ |
| node packages/headless/harbor/run-harness-ab.mjs |
| ``` |
| |
| For a live Kimi run, remove `MAKA_HARNESS_AB_DRY_RUN`; `MAKA_HARNESS_AB_KEY_FILE` overrides its historical default key-file path. A live GLM run instead requires `MAKA_HARNESS_AB_ZAI_KEY_FILE`. Each plan runtime ignores the other plan's key-file environment so a stale export cannot silently route the wrong credential. Both plan runtimes record account-plan billing with zero observed price and preserve token totals; any public list-price projection belongs in later analysis rather than the immutable run manifest. The Codex runtime instead resolves and refreshes Maka's `codex-subscription` OAuth record from the default desktop workspace before each upstream request; override that source with `MAKA_HARNESS_AB_WORKSPACE_ROOT` or `MAKA_HARNESS_AB_OAUTH_CONNECTION_SLUG`. The run manifest fingerprints the resolved account identity and rejects an account change while allowing token refreshes for the same account. The pinned Codex adapter uses the Responses HTTP transport because the host credential proxy does not relay WebSocket upgrades. Both arms receive only a per-cell host proxy capability, never an access token, refresh token, provider key, or credential-file path. The pinned competitor toolchain is downloaded once, verified against checked-in archive and file hashes, then mounted read-only into its task containers. `MAKA_HARNESS_AB_LIMIT=5` runs the operational canary; rerun the same run id with `89` to continue the same WAL through the complete frozen profile. Set `MAKA_HARNESS_AB_TASK_IDS` to a comma-separated set of frozen Terminal-Bench 2.1 task ids and an explicit `MAKA_HARNESS_AB_RUN_ID` to run a smaller resumable profile under one manifest. Execution policy is independent of the composition and defaults safely to one task pair with sequential arms. Set `MAKA_HARNESS_AB_PAIR_CONCURRENCY` from `1` through `4` and `MAKA_HARNESS_AB_ARM_EXECUTION` to `sequential` or `parallel` for a particular experiment; the immutable manifest freezes the effective values and rejects changes when resuming. Only missing cells run. |
| |
| Oracle evidence is advisory. To consume a CI-issued registry snapshot, set both `MAKA_HARNESS_AB_ORACLE_REGISTRY_URL` and `MAKA_HARNESS_AB_ORACLE_REGISTRY_FINGERPRINT`. The runner downloads the lightweight pinned snapshot, validates its content and per-task identities, and records `passed`, `failed`, `timed_out`, `infra_failed`, `stale`, or `missing` annotations in the manifest and report. Missing, stale, failed, unavailable, invalid, or unresolvable evidence emits warnings but never invokes Oracle, changes task selection, blocks new A/B execution, or changes statistical inclusion. A resumed run reuses the advisory snapshot frozen in its existing manifest instead of resolving current registry state again. Legacy manifests retain their historical Oracle-gated `qualification` metadata as read-only history; the current runner does not append new cells to a run created by the old qualification profile. |
| |
| The manual `.github/workflows/oracle-evidence-audit.yml` workflow is the only CI path that invokes Oracle. Its prepare job resolves task contents, the pinned Harbor verifier/execution policy, the compose override, Docker platform, and current `linux/amd64` base-image manifest digests into per-task qualification keys. Exact runner versions are recorded as execution provenance rather than key material. Each task runs from a temporary copy whose Dockerfile is pinned to the resolved digests. The workflow downloads the newest prior registry release by default, runs only missing or changed tasks in a bounded GitHub-hosted matrix, and publishes a new content-addressed prerelease containing `oracle-registry.json` and immutable per-task `oracle-evidence.jsonl`. Ordinary CI and A/B runs do not trigger this workflow. |
| |
| For an unattended run, invoke `node packages/headless/harbor/run-harness-ab-detached.mjs` with the same environment. It detaches the worker from the terminal and atomically journals `running`, `completed`, or `failed` in `background-run.json`; stdout and stderr go to `background-run.log`. |
| |
| Outputs are `harness-ab-report.json`, `.csv`, and `.md`. Report schema v3 records scheduled, attempted, model-scored, unscored (including the infrastructure-failed subset), and missing-final-usage cell coverage while keeping paired Pass@1 and token economy on separate denominators. Account-plan runs record zero cost and use real token totals as the economy measure. Evidence gaps finish as `completed_with_gaps` and fail the completion assertion; an unattempted suffix remains `incomplete`. Reports do not claim fixed-plan spend or publish results. |
| |
| ## Attention semantic-compaction A/B |
| |
| `harbor/run-runtime-policy-ab.mjs` includes a checked-in attention-first comparison over |
| `polyglot-rust-c`, `sqlite-db-truncate`, `reshard-c4-data`, `sanitize-git-repo`, and |
| `build-cython-ext`. The baseline disables semantic compaction; the candidate uses a |
| 16K provider context, 50% high-water mark, 4K completed-middle-span hysteresis, a |
| 4096-token generation budget, and a 768 estimated-token accepted projection budget. |
| The full phase runs three repetitions per task and arm (30 cells) after a one-repetition |
| operational pilot. Both arms keep the same model, prompt, tools, task budgets, and code |
| fingerprint. |
| |
| Validate the exact executable manifest without reading a credential: |
| |
| ```sh |
| MAKA_RUNTIME_AB_OUT_DIR=/path/to/out \ |
| MAKA_RUNTIME_AB_TASKS_ROOT=/path/to/frozen-five-task-export \ |
| MAKA_RUNTIME_AB_SPEC_PATH=packages/headless/harbor/runtime-policy-ab-specs/attention-semantic-compact.json \ |
| MAKA_RUNTIME_AB_PROFILE_PATH=packages/headless/harbor/runtime-policy-ab-profiles/glm-5.2.json \ |
| MAKA_RUNTIME_AB_RUN_ID=attention-semantic-compact-glm-5.2 \ |
| MAKA_RUNTIME_AB_DRY_RUN=1 \ |
| node packages/headless/harbor/run-runtime-policy-ab.mjs |
| ``` |
| |
| For a live run, remove `MAKA_RUNTIME_AB_DRY_RUN` and point |
| `MAKA_RUNTIME_AB_KEY_FILE` at a Z.ai credential file outside git. The lifecycle refuses |
| to advance past the pilot if either arm has an infrastructure/protocol failure, if the |
| candidate never activates compaction, or if coverage is incomplete. The final report's |
| primary decision uses official verifier Pass@1 with the checked-in 10 percentage-point |
| non-inferiority margin; token, cache, cost, latency, and compaction activation data remain |
| secondary diagnostics. |
| Use a frozen exported task root with exactly one version of each selected task; a mixed |
| Harbor cache containing two versions of a selected task is rejected instead of choosing |
| one silently. |
| |
| ## Exit code |
| |
| `maka eval run` exits non-zero on an **infrastructure** failure (invalid |
| spec, refused backend, a run that crashed before producing a result). A run |
| that completed and merely **failed its verification** is valid benchmark data |
| and exits 0. |
| |
| ## Legacy compatibility |
| |
| `maka-headless` remains a deprecated compatibility binary and prints a warning; |
| new documentation and automation must use `maka eval`. |