Sheet 07As-built surveyScale: NTS

What is drawn and what is built

In drafting practice, as-built drawings record what was actually constructed rather than what was specified. This sheet is that: a field survey of every place where the Daedalus type system, its documentation, or its manifests describe behaviour the implementation does not yet perform. The gap is large, it is legible, and the repository does not hide it.

Daedalus describes itself as a scaffold. README.md:42 is headed “v0.1 scope” and lists eleven components; RESEARCH.md:265 is headed “What We Built” and ends with nine numbered “Next Real Milestones”. Reading the source against those lists is the fairest way to assess it, and the result is consistent: the compile-and-record half of the system is complete and works, and the measure-and-act half does not exist.

“The best general system is not the most recursive agent. It is: strict local control plane + brutal artifact-level evals + replaceable coding agents + git/worktree rollback + frozen evaluator snapshots… That is what Daedalus is intended to become.”

RESEARCH.md, lines 322–335 — Final Thesis

Of the six clauses in that thesis, two are built. The strict local control plane exists and is genuinely strict — closed unions, path validation, a persisted ledger. Frozen evaluator snapshots exist, at manifest-identifier granularity. Artifact-level evals, replaceable coding agents and git worktree rollback are declared in types and documented in prose, with no executing code behind any of them.

Fig. 7.1 Coverage survey — declared against assigned

Survey comparing how many values each declared type or field set actually receives Nine paired measures. For each, an outlined bar shows the number of states or behaviours the type declares and a filled bar shows the number the implementation assigns or enforces. RunPhase declares thirteen values and six are assigned. AttemptRecord status declares seven and four are assigned. Milestone status declares four and two are assigned. RunState status declares four and three are assigned. RunBudget declares five limits and none are enforced. EvalValidationRecord is one interface with zero instances created. Adapter manifests declare seven runnable commands and zero are invoked. Evaluator manifests declare seven scoreWeight values and none are read; and the same manifests declare zero commands against a field that exists for them. MCP tools are eleven declared and eleven implemented — the only measure that is complete. declared in the type system assigned / enforced by code MEASURE 0 → 14 values 0 4 8 12 RunPhase types.ts:116–129 6 of 13 reachable AttemptRecord.status types.ts:177 4 of 7 Milestone.status types.ts:52 2 of 4 — "pending" and "passed" RunState.status types.ts:197 3 of 4 RunBudget limits enforced types.ts:131–137 0 of 5 — no comparison site anywhere EvalValidationRecord written types.ts:149–159 0 instances — the array is initialised empty and never appended Adapter commands invoked adapters.ts, 7 command strings 0 of 7 — no spawn, exec or child_process import in packages/ Evaluator scoreWeight read evaluatorRegistry.ts, 7 values 0 of 7 — scoring.ts takes an unweighted mean MCP tools implemented mcp-server/index.ts 11 of 11 CLI commands wired apps/cli/src/index.ts 10 of 10 Counts are of distinct union members or manifest fields, established by grepping the TypeScript sources for assignment sites.
Fig. 7.1 — The two bars at the bottom are the shape of the working system: the interfaces are complete. Everything above them measures the distance between a type that describes an autonomous build loop and an implementation that records one. Neither number is a criticism on its own — declaring the target state machine before building it is a defensible way to work — but a reader of run.json should know which fields carry information.

Field survey — declared, never written

Types with no assignment site in the repository
DeclarationLocationWhat it is forEvidence
AttemptRecord.worktreePath
.baseRef · .headRef
types.ts:178–180 git worktree isolation and revert of an attempt only occurrence of each identifier in the repo is the declaration
FrozenEvalSnapshot.hiddenManifestHash types.ts:143 separate hash for hidden tests, so the builder cannot see them freezeEvals() sets publicManifestHash only
EvalValidationRecord types.ts:149–159 the eval-critic’s record that an evaluator catches breakage evalValidationRecords: [] at daedalus.ts:52; no push
RunBudget (all 5 fields) types.ts:131–137 attempt, wall-clock, delta and stagnation limits constructed at daedalus.ts:45; never compared
Milestone.weight types.ts:51 weighted milestone contribution to a run score 3 occurrences total, all in milestones.ts construction
EvaluatorManifest.scoreWeight types.ts:69 weighted evaluator contribution set on all 7 manifests; read by nothing
EvaluatorManifest.command types.ts:62 the command that runs the evaluator not set on any of the 7 manifests
GoalContract.doneWhen
.requiredGatesPass · .noRegressions
types.ts:40–41 contract-level gate flags hard-coded true; scoring.ts reads only minScore
RunPhase — 7 members types.ts:118–129 evals_proposed, evals_validated, agent_running, eval_running, rolled_back, promoted, blocked 3 run.phase = statements exist, covering 6 values total
AdapterManifest.integrationType
value "mcp"
types.ts:84 adapters that are themselves MCP servers no entry in adapterRegistry uses it

Three further directories are inert in the same way. evaluator-packs/ (6 JSON files), templates/ (4 files, two of them YAML), and research/repos.json are read by no TypeScript source. The last is consumed by scripts/clone-research-repos.ps1, so it is at least wired to something; the other two are documentation stored in machine-readable formats.

Fig. 7.2 Critical path to a working loop

Dependency drawing of the nine outstanding milestones the project sets itself The nine next milestones listed at the end of RESEARCH.md drawn as a dependency graph rather than a list. Item one, running doctor and fixing build errors, is the entry point. Item two, implementing real evaluator execution instead of scoring by submitted proof scores, is drawn as the keystone: five other items depend on it. Item three, Playwright evaluator templates, and item four, artifact report generation, feed into it. Item five, worktree isolation and real keep and revert operations, unlocks the AttemptRecord fields that are currently unwritten. Items six and seven, the Codex and OpenCode executor adapters, depend on the worktree work. Item eight, OpenTelemetry trace export, gates item nine's AgentEvals integration. A dimension line marks the span from item two to item five as the minimum work required before any metric optimizer adapter becomes meaningful. RESEARCH.md:308–319 — “Next Real Milestones”, redrawn as dependencies 1 · doctor passes npm run typecheck strict tsc, no emit 2 · run_evals execution “instead of scoring by submitted proof scores” KEYSTONE — 5 items depend on it 3 · Playwright eval templates browser-game domain first 4 · artifact report generation screenshots · logs · traces 5 · worktree isolation real keep / revert operations unlocks worktreePath, baseRef, headRef and phase rolled_back 6 · Codex CLI executor adapter first real adapter invocation 7 · OpenCode executor adapter open-source executor path 8 · OTel trace export prerequisite 9 · AgentEvals integration diagnostic only 9 · security / web / API evaluator packs before adding more self-evolution closes the one uncovered proof in the default matrix — infra requiring security_baseline minimum span before any optimizer adapter is meaningful WHAT UNLOCKS WHEN ITEM 2 LANDS phase eval_running becomes assignable EvaluatorManifest.command becomes meaningful RunBudget wall time and attempt caps have something to bound scoreWeight gets a scale to weight autoloop · pi-autoresearch a stable scalar metric exists, which both adapters require status supported / optional becomes actionable the anti-cheat model mutationTests and hidden seeds become enforceable rather than advisory Every dependency shown is stated or directly implied by the source; the ordering is the project's own, from RESEARCH.md.
Fig. 7.2 — Item 2 is not one task among nine. It is the load-bearing member: budgets, evaluator weights, the phase machine’s middle section, the anti-cheat manifests and four of the fourteen adapters all become live the moment Daedalus can run an evaluator and read a number back rather than being handed one.

The project’s own checklist, checked

README.md:44–56 “v0.1 scope” against the source, plus one claim from README.md:30
Claimed componentStateObservation
TypeScript monorepo layoutbuiltapps/cli, packages/core, packages/mcp-server; relative imports, no workspaces field
CLI entrypointbuiltCommander, 10 commands, plus a 92-line Node shim
MCP server entrypointbuilt11 tools over StdioServerTransport
Goal compilerbuilt24 lines; keyword classification, fixed lookups
Milestone generatorbuilt4 hard-coded plans; a list, not the DAG the docs describe
Evaluator registrybuilt7 manifests, selection by domain and proof intersection
Evaluator pack manifestspresent, unloaded6 JSON files; no code reads evaluator-packs/
Score modelbuiltunweighted mean, threshold compare, 3-way decision
Run-state storagebuiltone JSON document per run, with a path guard
Adapter registrydata only14 manifests; nothing detects or invokes a tool
Artifact archives (README.md:30)not builtdaedalus init creates artifacts/; nothing writes to it

All ten v0.1 scope claims hold to the letter, though two hold narrowly: the evaluator pack manifests exist as files that nothing loads, and the adapter registry exists as data that nothing invokes. The claim that fails is the eleventh row, which is not from that list — “artifact archives”, listed under what Daedalus owns at README.md:30. The directory is created by init and no code path ever puts a file in it. Given that docs/ARCHITECTURE.md:114–119 makes artifact evidence the basis of acceptance, that empty directory is the single largest gap in the system.

What runs today

scripts/daedalus-runner.mjs:70–77 — doctor
$ daedalus doctor
Daedalus root: /home/me/daedalus
DAEDALUS_HOME: /home/me/daedalus
# ensureDependencies(): looks for node_modules/.bin/tsx
Daedalus first run: installing dependencies...
# npm install  (only on first run)
# npm run typecheck  ->  tsc -p tsconfig.json --noEmit
Daedalus doctor passed.

$ daedalus build
# npm run build  ->  tsc -p tsconfig.json   ->  dist/

$ daedalus research:clone
# powershell -ExecutionPolicy Bypass -File scripts/clone-research-repos.ps1
# shallow-clones the 12 entries in research/repos.json into research/repos/
#   PowerShell-only; the runner forwards it on every platform

Two of the seven package.json scripts shell out to powershell -ExecutionPolicy Bypass: install-command and research:clone. The runner detects Windows for the npm and npx binary names (daedalus-runner.mjs:10–11) but forwards research:clone unconditionally, so it fails on a machine without PowerShell. docs/TESTING.md is written entirely in PowerShell code fences. The core library itself is platform-neutral — node:path, node:fs/promises, no shell — so the Windows coupling is confined to the installer and the research script.

Repository inventory

Line counts for every tracked file, so the scale is not in doubt.

TypeScript — 1,408 lines

packages/mcp-server/src/index.ts221
packages/core/src/types.ts200
packages/core/src/adapters.ts197
packages/core/src/daedalus.ts194
packages/core/src/evaluatorRegistry.ts192
packages/core/src/domain.ts99
apps/cli/src/index.ts95
scripts/smoke.ts52
packages/core/src/milestones.ts43
packages/core/src/state.ts39
packages/core/src/scoring.ts38
packages/core/src/goalCompiler.ts29
packages/core/src/index.ts9

Prose & manifests — 1,189 lines

RESEARCH.md336
docs/ARCHITECTURE.md119
README.md109
scripts/daedalus-runner.mjs92
research/repos.json63
docs/TESTING.md59
docs/ADAPTERS.md51
docs/MCP_USAGE.md47
docs/RESEARCH_MATRIX.md32
package.json32
templates/ (4 files)78
evaluator-packs/ (6 files)89
shims, tsconfig, .gitignore, ps182

A large share of the TypeScript is declaration and data rather than behaviour: types.ts emits nothing at runtime, and adapters.ts plus the first 110 lines of evaluatorRegistry.ts are object literals. That is not padding — the registries are the product in a control plane whose job is to hold judgements — but it does mean the executing logic is closer to 800 lines than 1,400.

The verification budget is one file. scripts/smoke.ts is 52 lines of node:assert/strict covering a single happy path through the browser_game domain, plus one negative check on run-id validation. There is no test for classifyDomain on any other domain, none for scoreAttempt’s decision branches, none for selectEvaluators’ uncovered-proof path, and no CI workflow to run even this one.

Assessment

Daedalus is a well-argued scaffold. Its strongest asset is not code but the position it takes and records: that the durable part of an autonomous build system is the goal, proof and scoring vocabulary, and that everything which edits files should be replaceable. The proof union, the evaluator manifests with their mutation tests and anti-cheat notes, the deliberately split Autoloop entries, and the adapter failureModes lists all read like the output of someone who has watched agents fake progress and wants a schema that makes faking visible.

What exists is a compiler and a ledger. Given a sentence it produces a contract, a milestone list, an evaluator selection and a frozen hash, and it will faithfully record scores an agent hands it. What does not exist is anything that measures. The scoring input is a caller-supplied record of numbers; no evaluator is executed, no adapter is spawned, no artifact is captured, and no budget is enforced. The repository says as much — item 2 of its own outstanding list is precisely this — and the type system already has the shape waiting for it.

Judged as a v0.1 scaffold, which is how it labels itself, that is a coherent place to be. The danger it names in RESEARCH.md:63–66 — a loop that optimises a weak evaluator — is the danger it is currently exposed to, and it has written the schema for the fix before writing the fix.

Survey method

  1. Every claim on this sheet was established by reading the file named beside it. Line references are to the repository as surveyed and will drift if the source changes.
  2. “Never assigned” means no assignment or push statement exists in any .ts or .mjs file in the repository — established by grepping each identifier and inspecting every hit.
  3. Line counts are whole-file counts including blank lines and comments, matching what wc -l reports.
  4. No benchmark, adoption figure, performance measurement or comparison against another project appears anywhere in this drawing set, because the repository contains none.