Get the FREE Ultimate OpenClaw Setup Guide →

hole-driven-development-iterative-reasoning

Scanned
npx machina-cli add skill jhhuh/hole-driven-development-skill/hole-driven-development-iterative-reasoning --openclaw
Files (1)
SKILL.md
4.8 KB

Hole Driven Development — Iterative Reasoning

REQUIRED BACKGROUND: hole-driven-development-core

Overview

You are the type checker. Decompose implementation into visible hole markers in the file, reason about each hole's contract (inputs, outputs, constraints), and fill them one at a time.

Core principle: Make your reasoning visible. Holes live in the file, not in your head.

When to Use

  • Implementing in any language, especially those without typed holes
  • HDD discipline for dynamically typed languages (Python, JS, Go, Bash)
  • When no compiler with hole diagnostics is available

Hole Markers

Write real, language-appropriate placeholder code that makes holes visible in the editor:

LanguageHole marker
Pythonraise NotImplementedError("HOLE_N: <description> # expects: <type>")
JavaScript/TypeScriptthrow new Error("HOLE_N: <description> // expects: <type>")
Gopanic("HOLE_N: <description> // expects: <type>")
Bashecho "HOLE_N: <description>" && exit 1
OtherComment: /* HOLE_N: <description> — expects: <type> */

Each hole has: a number, a description of what it does, and what type/contract it fulfills.

The Reasoning Loop

1. Receive intention
2. Write skeleton to the file with HOLE markers for each sub-problem
3. PICK the most constrained hole
4. REASON about what it needs:
   - What type/value does it produce?
   - What inputs are available in scope?
   - What constraints apply?
5. FILL exactly one hole in the file — introduce sub-holes if complex
6. VALIDATE (optional): run type checker if available (see table below)
7. VERIFY cross-hole interactions: for each filled hole sharing state with this fill:
   - Shared mutable state: is access properly synchronized?
   - Resource lifecycle: are acquire/release scopes correct across hole boundaries?
   - Error/cancellation paths: do they propagate correctly to other holes?
   Fix any issue before continuing.
8. Repeat from 3 until no holes remain
9. REVIEW-ALL: before declaring done, re-read the complete implementation:
   - State transitions that span multiple fills
   - Resource acquired in one fill, released in another
   - Error paths that cross fill boundaries
   - Loop invariants depending on multiple fills
   Fix any systemic bug the per-hole VERIFY could not catch.

One hole per iteration. Fill one, reassess, then pick the next.

Each distinct concern gets a hole. When the spec has N distinct requirements or sub-problems, the skeleton should have at least N holes. Don't collapse multiple concerns into one hole — that defeats the purpose of decomposition.

Reason before filling. For each hole, explicitly state: what it needs to produce, what it has available, and why your fill is correct. Do not skip this reasoning step.

Verify after filling. Cross-cutting concerns (concurrency, resource lifecycle, error handling) don't decompose into independent holes. After each fill, check interactions with previously filled code.

When NOT to decompose further. Algorithms with tightly coupled state machines (dual-cursor walks, FSMs with shared transition state) should stay as a single hole. Use internal comments to mark structure within the hole, but do not split the state machine across sub-holes — the transitions are too interdependent for per-hole reasoning to catch interaction bugs.

External Validation (Optional)

When a type checker is available, run it after filling to catch errors:

LanguageType checkerDetection
Pythonmypy, pyrightpyproject.toml, .py
TypeScripttsc --noEmittsconfig.json, .ts
Gogo buildgo.mod, .go

If no type checker is available, your reasoning is the sole oracle. Be more careful with constraint analysis.

Autonomy

Run the loop autonomously. Stop only when:

  • Done: No holes remain, code satisfies the intention, and REVIEW-ALL found no systemic bugs.
  • Ambiguous: A hole's contract is unclear — multiple valid approaches with different semantics. Surface options to the human.
  • Stuck: 5+ iterations on the same hole without progress. Ask for help.

Red Flags — STOP

  • Writing complete implementation without creating holes first
  • Keeping holes in your head — every hole must be in the file
  • Filling multiple holes in one step
  • Skipping the reasoning step ("obvious what goes here")
  • Not stating the hole's contract before filling it

If you catch yourself doing any of these: STOP. Write holes to the file first.

Source

git clone https://github.com/jhhuh/hole-driven-development-skill/blob/master/skills/hole-driven-development-iterative-reasoning/SKILL.mdView on GitHub

Overview

Hole Driven Development — Iterative Reasoning lets you implement in any language by decomposing into visible hole markers in the file and reasoning about each hole's contract. The core principle is to make your reasoning visible, with holes living in the file and filled one at a time.

How This Skill Works

You mark holes in the code using language-appropriate placeholders, identify the most constrained hole, reason about its produced type, inputs, and constraints, then fill exactly one hole. After filling, you can run a type check if available and verify cross-hole interactions before moving to the next hole, repeating until all holes are resolved.

When to Use It

  • Implementing in any language, especially those without typed holes
  • HDD discipline for dynamically typed languages (Python, JS, Go, Bash)
  • When no compiler with hole diagnostics is available
  • Creating a top-down decomposition for complex features
  • When you need explicit, cross-hole reasoning and verification

Quick Start

  1. Step 1: Receive intention
  2. Step 2: Write skeleton to the file with HOLE markers for each sub-problem
  3. Step 3: PICK the most constrained hole and begin the reasoning/fill cycle

Best Practices

  • Place real language-appropriate hole markers with descriptive notes and the expected type
  • Give every hole a unique number and a contract (inputs, outputs, constraints)
  • Create at least as many holes as distinct requirements; avoid collapsing concerns
  • Reason before filling: state intended output, available inputs, and justification
  • Verify after each fill for cross-hole effects (resources, state, error paths) and re-check at the end

Example Use Cases

  • Python: raise NotImplementedError("HOLE_1: parse_user_input -> dict # expects: dict")
  • JavaScript/TypeScript: throw new Error("HOLE_2: fetchUser -> User // expects: User")
  • Go: panic("HOLE_3: buildResponse // expects: *Response")
  • Bash: echo \"HOLE_4: validate_config\" && exit 1
  • Other: /* HOLE_5: log_event — expects: void */

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers