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 ThesisOf 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
run.json should know which fields carry information.Field survey — declared, never written
| Declaration | Location | What it is for | Evidence |
|---|---|---|---|
| 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
The project’s own checklist, checked
| Claimed component | State | Observation |
|---|---|---|
| TypeScript monorepo layout | built | apps/cli, packages/core, packages/mcp-server; relative imports, no workspaces field |
| CLI entrypoint | built | Commander, 10 commands, plus a 92-line Node shim |
| MCP server entrypoint | built | 11 tools over StdioServerTransport |
| Goal compiler | built | 24 lines; keyword classification, fixed lookups |
| Milestone generator | built | 4 hard-coded plans; a list, not the DAG the docs describe |
| Evaluator registry | built | 7 manifests, selection by domain and proof intersection |
| Evaluator pack manifests | present, unloaded | 6 JSON files; no code reads evaluator-packs/ |
| Score model | built | unweighted mean, threshold compare, 3-way decision |
| Run-state storage | built | one JSON document per run, with a path guard |
| Adapter registry | data only | 14 manifests; nothing detects or invokes a tool |
| Artifact archives (README.md:30) | not built | daedalus 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
$ 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.ts | 221 |
| packages/core/src/types.ts | 200 |
| packages/core/src/adapters.ts | 197 |
| packages/core/src/daedalus.ts | 194 |
| packages/core/src/evaluatorRegistry.ts | 192 |
| packages/core/src/domain.ts | 99 |
| apps/cli/src/index.ts | 95 |
| scripts/smoke.ts | 52 |
| packages/core/src/milestones.ts | 43 |
| packages/core/src/state.ts | 39 |
| packages/core/src/scoring.ts | 38 |
| packages/core/src/goalCompiler.ts | 29 |
| packages/core/src/index.ts | 9 |
Prose & manifests — 1,189 lines
| RESEARCH.md | 336 |
| docs/ARCHITECTURE.md | 119 |
| README.md | 109 |
| scripts/daedalus-runner.mjs | 92 |
| research/repos.json | 63 |
| docs/TESTING.md | 59 |
| docs/ADAPTERS.md | 51 |
| docs/MCP_USAGE.md | 47 |
| docs/RESEARCH_MATRIX.md | 32 |
| package.json | 32 |
| templates/ (4 files) | 78 |
| evaluator-packs/ (6 files) | 89 |
| shims, tsconfig, .gitignore, ps1 | 82 |
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
- 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.
- “Never assigned” means no assignment or
pushstatement exists in any.tsor.mjsfile in the repository — established by grepping each identifier and inspecting every hit. - Line counts are whole-file counts including blank lines and comments, matching what
wc -lreports. - No benchmark, adoption figure, performance measurement or comparison against another project appears anywhere in this drawing set, because the repository contains none.