Skip to content

handoff: fold / TypeScript-as-Data workstream — orchestrator brief #1090

Description

@lex00

Cold handoff of the fold / TypeScript-as-Data workstream. Read this end to end before doing anything. It encodes decisions already made, traps already hit, and the verification discipline that this work has repeatedly proven necessary.

Your role: orchestrator, not implementer

You dispatch subagents, interrogate them, verify their claims independently, and merge. You do not implement the features yourself. The exceptions are small, surgical fixes (a one-line cast, a doc line) and — always — measurement, which you do yourself and never delegate.

The reason is not efficiency. Every serious defect in this workstream was caught by the orchestrator re-measuring, not by the implementing agent. Two agents shipped confident, well-written reports that were wrong on their central claim. So did the previous orchestrator, three times. Verification is the job.

Model selection

  • Sonnet by default. Every feature agent in this workstream ran on Sonnet and the engineering quality was consistently good — including one that correctly defended its result against a wrong orchestrator claim.
  • Opus when there is risk. Use it for: anything touching the fold subset or the sandbox boundary, security-relevant work, ambiguous root-cause hunts, and any task where a wrong answer would be expensive to detect. The intermittent-hang investigation is the archetype — it burned three agents and hours of wall clock because the failure was nondeterministic and every plausible theory was wrong.
  • Signal to escalate: the task requires falsifying a hypothesis rather than building to a spec.

Interrogate your agents

Do not accept a completion report at face value, and do not wait passively for one.

  • Mid-flight, ask: what is your current hypothesis, what have you measured, what have you ruled out and how? Ask for measurements, not reasoning. Explicitly tell them "still characterizing" is an acceptable answer — that permission is what stops an agent inventing a confident theory to fill silence.
  • Before dispatch, make them restate the acceptance criterion in their own words if the task is subtle. Two agents optimized a proxy metric because the real goal was one layer removed from what the issue said.
  • When a report contains a claim that shifts blame to pre-existing code, treat that as a flag. It happened twice; both times the claim was wrong and one cheap experiment falsified it. Ask for that experiment.
  • When an agent pushes back on you, take it seriously. One correctly corrected a stale baseline. Being challenged by a subagent is a signal to re-check your own numbers, not to reassert.

The goal

Fold becomes the default path for real chant applications, so that describing chant as statically folding TypeScript is simply true rather than aspirational.

Coverage percentage on the example corpus is a proxy and a weak one — the corpus is chant's own curated code, is expected to shrink, and can be moved by editing examples. That is metric-gaming; do not do it.

The real metric is loomster (/Users/alex/checkouts/intentius/loomster), a full application built on chant. Currently 13 of 55 files fold. The warden repos are secondary targets. Any decision about making fold default-on should be measured there.

Measurement traps — all five were hit, do not repeat them

  1. Never symlink node_modules between checkouts. It resolves lexicon plugins to the wrong tree and produces confidently wrong numbers. This cost a full review cycle and a false accusation against a correct PR.
  2. Never capture parallel output to one file. xargs -P 6 … > out.txt interleaves six builds and destroys entry boundaries. Write one file per entry. This produced a fabricated "16 file regressions" that did not exist.
  3. Verify a mutation applied before trusting the result. Three separate "the guard did not fire" conclusions came from perl/sed patterns that silently did not match. Always diff and confirm before running.
  4. One passing run proves nothing for anything intermittent. The hang reached CI because local runs passed. Require 5+ consecutive clean runs.
  5. Never run two full suites concurrently and then interpret a timeout. Contention looks exactly like a hang.

Two message wordings exist for the same fold rejection (function call as a value and call expression as a value), and reasons embed the entire multi-line source node — so line-based grepping of fold output silently miscounts. Parse whole blocks. Tracked as #1054.

Operational safety

This machine hard-crashed early in this work: a runaway test run exhausted 64GB, the kernel jettisoned ~300 daemons, and it cost a reboot. Since then:

  • Cap every run. A single test file past ~3 minutes is a bug, not slowness. Full suite baseline is ~45s local, ~7m CI.
  • A repeat-until-hang harness with process/CPU/fd diagnostics lives at scratchpad/hang-hunt2.sh in the session scratch dir — reuse the pattern.
  • vitest.config.ts now caps per-fork heap derived from host memory and core count, so a runaway fails as a test rather than killing the machine. Do not remove it.

Decisions already made — do not relitigate

State

Merged this session: #1038, #1039, #1042, #1043, #1045 (all 3 phases), #1047, #1051, #1020, #1062, #1067. Main is green.

In flight: PR #1081 (#1064, build-time parameters). CI pending at handoff. The agent self-caught a performance regression it introduced — reintroducing the cold bare-specifier resolution cost that #1020 had eliminated — and fixed it in c4707dd5. Verify with the repeat-run harness before merging; this exact regression class has bitten twice.

Loomster PR #156 and issue #155 exist for the params migration. Do not merge #156 until a chant release containing #1064 is published — its CI installs chant from npm and will fail otherwise. Releases are cut by pushing a chant-v* tag, which triggers .github/workflows/publish.yml. Current version 0.19.1. Publishing is irreversible and outward-facing: surface that decision to the maintainer rather than tagging unilaterally.

Open, in recommended order

  1. feat(core): chant's own authoring helpers (phase, output, Parameter) are unfoldable — caps real-app coverage #1082 — chant's own helpers (phase(), output()) and new Parameter("String", {...}) are unfoldable, capping any real app. This is what actually blocks loomster now, not feat(core): fold registered plain-call intrinsics (per-intrinsic opt-in) — DECIDED: yes #1044 or feat(core): fold cross-file references into lexicon package exports (Azure/GCP pseudo-params, action constants) #1063.
  2. feat(core): fold registered plain-call intrinsics (per-intrinsic opt-in) — DECIDED: yes #1044 — registered plain-call intrinsics. ~45 corpus entries, ~1 loomster file.
  3. feat(core): fold cross-file references into lexicon package exports (Azure/GCP pseudo-params, action constants) #1063 — cross-file references into lexicon package exports (Azure, GCP namespaces). ~25 corpus entries.
  4. bug(core): fold fallback reasons embed the whole source node, truncating the real error #1054 — fold diagnostics; small, and it removes a whole class of misreading.
  5. refactor(core): ResourceDeclarable sub-interface for props/attributes — DECIDED: option 2 #1049ResourceDeclarable; mechanical, wide.

Also open from the lexicon-contract sweep: #1068, #1070, #1071, #1072 — pre-existing per-lexicon debt, now visible and gated via KNOWN_FAILURES in scripts/check-lexicons.ts.

What "done" looks like

Not a corpus percentage. Loomster folding a large majority of its files, with the remainder being patterns that should never fold — process.env reads, arrow functions, user helper functions. At that point the question of making fold default-on becomes answerable on evidence, and the positioning becomes true.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:coreBuild pipeline, discovery, fold, components, CLIepicTracking epic with sub-issues

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions