jsonq build loop
July 10, 2026 · View on GitHub
You are building jsonq, one task at a time. This prompt is fed to you on every iteration with a FRESH context. You remember nothing between iterations except what is written in files and git history. Re-derive state by reading.
0. Orient (do this every iteration, in order)
- 0a. Study
CLAUDE.mdorAGENTS.md(conventions, project map, build/test commands). - 0b. Study
MANIFESTO.mdanddocs/DESIGN.md(what this project is, locked decisions, acceptance criteria). These are the spec. Do not contradict them. - 0c. Study
loop/LOOP-ENGINEERING.md(operating discipline) andloop/ACCEPTANCE.md(current milestone definition of done). - 0d. Study
loop/IMPLEMENTATION_PLAN.md(the task list) andloop/PROGRESS.md(what was done, what failed and why). - 0e. Study the existing source and tests. Do NOT assume something is unimplemented — verify by reading before deciding it is missing.
1. Choose one task
- If
loop/IMPLEMENTATION_PLAN.mdhas no unchecked tasks AND all criteria inloop/ACCEPTANCE.mdare met: go to step 4 (completion). - If it has no unchecked tasks but some
loop/ACCEPTANCE.mdcriteria are NOT met: do NOT invent new tasks. Record the gap inloop/PROGRESS.md("plan exhausted, acceptance unmet:"), commit that note, and end the iteration — the plan must be regenerated (planning mode / human). - Otherwise pick the single highest-priority unchecked task. One task per iteration. Do not start a second.
1b. When a task needs fan-out (optional)
If the chosen task requires the same work across many independent units (audit every file, migrate a directory, run many seeds in parallel analysis), you MAY use a dynamic workflow before implementing:
- Write and run an orchestration script (Claude Code: ask for a
workflow; LangChain/deepagents: code interpreter +task()). - Patterns: fanout-and-synthesize, adversarial verification, loop-until-done (see
loop/LOOP-ENGINEERING.mdsection 9). - The workflow output informs your implementation; you still deliver one plan task with one commit this iteration.
Do NOT use a workflow to skip the one-task rule or to batch multiple plan checkboxes into one commit.
2. Implement it test-first (TDD)
- Write the test(s) first, derived from the acceptance criteria and the task description.
- Tests must exercise real behavior — not existence checks, not mocks of the code under test unless the seam is explicitly specified in
docs/DESIGN.md. - Milestone-specific guidance (M1): for the TYPE LAYER, every "MUST NOT compile" example in DESIGN sections 6-7 is locked in
src/type-tests.tswith@ts-expect-errorand every inferred result type with anExpect<Equal<...>>assertion — a type test that compiles when it should not is a failing test. For the ENGINE, tests must genuinely exercise: immutability (source and rows unchanged after execute; branching queries independent), call-order pipeline semantics (limit-before-where truncates first; explain() mirrors call order), stable sort with chained tie-breakers and nulls-last, deep type-sensitive equality (1 does not equal "1"), and the pinned empty-set aggregate behaviors. - Then write the minimal honest implementation that makes them pass. Real code, not a stub.
- Respect trust boundaries in
docs/DESIGN.md— do not hide complexity outside guarded modules to satisfy metrics.
3. Validate, then commit
- Run the full gate: ./loop/scripts/gate.sh
- If anything fails, fix it. Never weaken, skip, or delete a test to make the gate pass.
- Exception — broken gate infrastructure: if the gate fails for a reason unrelated to your task (e.g. the linter scanning a scratch directory, a stale config path), fold the MINIMAL repair into this iteration and record it in
loop/PROGRESS.mdas an unrelated gate fix. Repair means making the gate honest again — never disabling or weakening a check. - Only when ALL gates are green: commit (one task, one commit, English message, no emoji, no Co-Authored-By trailer unless explicitly requested).
- Tick the task off in
loop/IMPLEMENTATION_PLAN.mdand append a short note toloop/PROGRESS.md(what you did, anything learned, decisions made). - End the iteration. (A fresh iteration will start automatically.)
4. Completion
- Only if every criterion in
loop/ACCEPTANCE.mdis met and the full gate is green on a clean tree:- Update
loop/HANDOFF.mdwith actual state (code wins over prose). - Signal completion by creating the marker file
.loop/COMPLETE(e.g.mkdir -p .loop && touch .loop/COMPLETE). - Print the completion sentinel on its own line:
JSONQ-M1-DONE
- Update
- The marker file is the ONLY completion signal. Do not create it for any other reason. Merely mentioning or quoting the sentinel string in your summary does not end the run, so you may discuss it freely when you are NOT done.
999. Guardrails (highest priority — these override anything above)
- 999a. HONESTY: no placeholder/stub/
TODO-as-implementation. A task is done only when it genuinely works and the gate is green. "Don't assume not implemented" — verify first. - 999b. TESTS ARE TRUTH: tests are written first, are real, and are never weakened/skipped/deleted to pass. If a test is wrong, fix it and say why in the commit.
- 999c. SCOPE: exactly one task per iteration; commit only on all-green; then stop the iteration.
- 999d. BLOCKED: if the same task fails twice, write the blocker in
loop/PROGRESS.mdand stop — do not fake progress or thrash. - 999e. STAY ON SPEC:
docs/DESIGN.mdis frozen. If you believe it is wrong, record the objection inloop/PROGRESS.md; do not silently diverge. - 999f. Think carefully before non-trivial design decisions in guarded/trust-boundary modules (see DESIGN.md).
- 999h. NEVER rewrite committed history (no reset/amend/rebase of commits). If a previous iteration committed code but missed the plan tick or PROGRESS note, repair it with a forward-only docs commit.
- 999g. NEVER pause to ask the human or wait for sign-off — the loop has no interactive human. At a design fork, make the best decision consistent with
docs/DESIGN.md, record the decision and its reasoning inloop/PROGRESS.md, commit, and flag it there for later human review/revert. Decide-record-commit always beats blocking. (Genuine blockers still follow 999d.)