Skip to content

Instantly share code, notes, and snippets.

@tavisrudd
Last active March 2, 2026 23:50
Show Gist options
  • Select an option

  • Save tavisrudd/fef9d96ad50b2e6aec65f4e53f8004a4 to your computer and use it in GitHub Desktop.

Select an option

Save tavisrudd/fef9d96ad50b2e6aec65f4e53f8004a4 to your computer and use it in GitHub Desktop.
summoning ghosts for review

Initial Prompt

i want you to do detailed Rich Hickey inspired review of our architecture. what have complected? launch another inspired by John Ousterhout and a Yaron Minsky review
now shriram krishnamurthi's review ... Kmett's: then finally Casey Muratori ... now an opus sub agent to read all of them and propose a series of architectural refactorings, each step green. write a new file

Main Agent talking to subs:

Per-Persona Sub-Agent Prompts

Rich Hickey — exploration via 3 parallel Sonnet agents

Agent 1: "Explore module structure & deps"

Very thorough exploration of the iidy-hs Haskell project architecture. I need to understand:

  1. The full module hierarchy — list every .hs file under src/ and test/
  2. The main data types — find all key data and newtype declarations, especially in types modules
  3. The dependency graph — which modules import which? Focus on circular or surprising dependencies
  4. The monad stack / effect system — how are effects handled? Is it IO, MTL, free monads, etc.?
  5. The CfnContext type — what's in it, who creates it, who reads it?
  6. The output pipeline — OutputData, OutputDispatch, renderers
  7. How configuration flows — from CLI args through to execution

Report back with concrete file paths, type signatures, and import patterns. I want to see the actual structure, not summaries.

Agent 2: "Explore data flow & coupling"

Very thorough exploration of the iidy-hs Haskell project looking for coupling and complecting patterns. Specifically:

  1. Find all uses of IORef, MVar, TVar — mutable state
  2. Find all uses of throwIO, catch, try, SomeException — error handling patterns
  3. How does the template preprocessing pipeline work? Trace from file load through variable substitution, handlebars, imports, to final YAML output
  4. Find all places where IO is done — network calls, file reads, environment variable reads. Are these interleaved with pure logic?
  5. Look at the CLI argument parsing (Main.hs, any Args/Options modules) — how tightly coupled is it to execution?
  6. Find any god-objects or mega-records that combine many concerns
  7. Look for places where serialization format (YAML/JSON) is intertwined with business logic

Report concrete evidence: file paths, line numbers, type signatures, code snippets.

Agent 3: "Explore testing & abstraction"

Very thorough exploration of the iidy-hs Haskell project focusing on abstraction boundaries and testability. Specifically:

  1. How are AWS operations abstracted? Is there a typeclass, function injection, or direct amazonka calls? Find all amazonka imports and usage patterns.
  2. How is the file system abstracted (or not)? Find all file I/O operations.
  3. The OValue type — what is it, why does it exist alongside Aeson's Value, and where is conversion done?
  4. The Handlebars and JMESPath custom implementations — what do their APIs look like? Are they pure?
  5. The JSON Schema validator — is it pure? What does its API look like?
  6. The NTP client — how is it used, where is it called from?
  7. The template loader / import resolution — how does it handle circular imports, caching?
  8. Look at test/ directory — are tests testing pure logic separately from IO? Or are they mostly integration tests?

Report concrete evidence: file paths, line numbers, type signatures, code snippets.

Main agent then wrote Hickey + Ousterhout + Minsky reviews directly from these three explorations.


Shriram Krishnamurthi

Your prompt: now shriram krishnamurthi's review

Agent 4: "Explore language/DSL patterns"

Very thorough exploration of the iidy-hs Haskell project focusing on patterns that a programming languages researcher (Shriram Krishnamurthi) would care about. Specifically:

  1. The YAML preprocessing language: Look at src/Iidy/Yaml/Ast.hs — the PreprocessingTag type and all its variants (!$if, !$map, !$let, !$concat, !$merge, !$expand, etc). List ALL the tag types. This is essentially a DSL embedded in YAML. What are its semantics? Is there a formal grammar?
  2. The resolver as an interpreter: Look at src/Iidy/Yaml/Resolution/Resolver.hs — how does it evaluate each preprocessing tag? What's the evaluation order? Is it lazy or strict? Does !$let introduce scope? How do variables work? Is there an environment? Show the key resolveAst cases.
  3. Handlebars as a sub-language: Look at src/Iidy/Yaml/Handlebars/Engine.hs — is there a parser? What's the AST? How are helpers dispatched? Is it a separate language inside the YAML DSL?
  4. JMESPath as another sub-language: Look at src/Iidy/Yaml/JMESPath.hs — what's its AST? How does evaluation work?
  5. Custom resources as a type system: Look at src/Iidy/Yaml/CustomResources/ — Params.hs, JsonSchema.hs, Expansion.hs. Is there a schema language? Type checking? Validation?
  6. The import system: Look at src/Iidy/Yaml/Engine.hs and src/Iidy/Yaml/Imports/ — is there a module system? How are names resolved? What's the scoping?
  7. Error reporting quality: Look at src/Iidy/Yaml/Errors/ — how are source locations tracked through transformations? Is there a source map?

Report ALL findings with file paths, line numbers, type signatures, and code snippets. I want to understand iidy's preprocessing as a LANGUAGE, not just a tool.

Agent 5: "Explore testing & specification"

Thorough exploration of the iidy-hs Haskell project focusing on how the YAML preprocessing semantics are specified and tested. A PL researcher would care about:

  1. Property-based testing: Look at test/Test/PropertyTest.hs — what properties are tested? Are there algebraic laws? Idempotency? Commutativity?
  2. Fixture tests as a specification: Look at fixtures/ and test-fixtures/ — what do the test fixtures look like? Do they serve as a specification of the language semantics? How many are there?
  3. Error fixture tests: Look at the error fixtures — do they specify what error messages should look like for invalid programs?
  4. Snapshot testing: Look at scripts/snapshot-compare.sh — how is the Haskell implementation compared against the Rust oracle? Is this differential testing?
  5. The Rust source as specification: Look at ~/src/iidy/ briefly — is there any formal specification document, or is the Rust implementation the de facto spec?
  6. Test coverage of language features: Are ALL preprocessing tags tested? All handlebars helpers? All JMESPath operators? Find gaps if any.

Report with file paths and specific examples.

Main agent wrote Krishnamurthi + Kmett + Muratori reviews from these two explorations plus the earlier batch.


Synthesis

Your prompt: now an opus sub agent to read all of them and propose a series of architectural refactorings, each step green. write a new file

Agent 6: "Synthesize reviews into refactoring plan" (Opus) — read all six review files + key source files, produced notes/2026-03-02-refactoring-plan.md. (Full prompt shown in my previous message.)

@tavisrudd
Copy link
Author

Claude when summarizing the reviews:

The tension between Kmett and Muratori is particularly sharp:
one says "use more of Haskell's power," the other says "use less of everything."
Both are right — the codebase could benefit from targeted
use of Haskell abstractions (typed errors, status enums, operation-specific config types)
without going full Free CfnF (ExceptT IidyError (ReaderT CfnEnv IO))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment