Status: planning
This document is the shared contract for agents building Foundry. Every agent must read it before creating or modifying files.
Foundry is a greenfield, local-first, hands-on learning workspace for programming and software engineering.
It should take a learner from programming fundamentals through professional software construction, architecture, production engineering, and system design. It is a companion to Heyrian:
- Heyrian is the browser-first educational experience: explanations, visualizations, guided learning, and low-friction practice.
- Foundry is the code-first workbench: real files, toolchains, tests, debugging, reviews, refactoring, projects, and long-term learning history.
Foundry must not copy the old foundry-old tree blindly. Use it as a source of ideas only. Prefer stable concepts, clear ownership, and runnable artifacts.
The initial language shortlist is:
- TypeScript
- Go
- Python
- Rust
- Haskell
- Java
The tracks should share a common curriculum vocabulary, but they do not need identical content. A language may omit a module when the concept is not idiomatic or useful in that language; explain the omission in the track README.
SQL is an essential supporting subject for database and system-design work, but is not an initial general-purpose language track.
The intended top-level structure is:
foundry/
├── AGENTS.md
├── README.md
│
├── curriculum/
│ ├── roadmap.md # Human-readable recommended progression
│ ├── catalog.yaml # Stable module IDs, outcomes, prerequisites
│ ├── progress.yaml # Learner state
│ └── sessions/ # Session logs
│
├── shared/
│ ├── concepts/ # Language-agnostic explanations
│ ├── comparisons/ # Cross-language comparisons
│ └── templates/ # Reusable content templates
│
├── dsa/
│ ├── README.md
│ ├── 01_concepts/
│ └── 02_problems/
│
├── typescript/
├── go/
├── python/
├── rust/
├── haskell/
├── java/
│
├── workspace/
│ ├── notes/
│ ├── attempts/
│ └── scratch/
│
└── tools/
The language directories are deliberately top-level and self-contained. A learner should be able to enter rust/ or go/ and follow that language's progression without jumping through separate tracks/, labs/, and concepts/ directories.
The shared directories are exceptions for genuinely cross-language material and project-wide coordination.
Parallel work must be isolated by path. The following rules are mandatory:
- Every task has one explicit owner and one explicit path scope before work begins.
- A language agent may create, edit, rename, or delete files only below its assigned language directory.
- The coordinator owns all shared files, including root documentation, curriculum metadata, DSA content, templates, tools, and learner progress.
- Agents must not “helpfully” update shared indexes, global progress, or another agent's README. Report those changes in the handoff instead.
- If a shared change is necessary, create a proposal under
shared/proposals/<language>/<topic>.mdor report it to the coordinator. Do not modify the shared source directly. - Stable module IDs and language-prefixed paths are required. Do not invent duplicate aliases for an existing module or exercise.
- Each exercise and project owns its own manifest, dependencies, test fixtures, and build output. No language may write generated artifacts into another language's directory or into the repository root.
- Before handing off, an agent must inspect its changed-path list and confirm that every changed path is within its assigned scope.
The coordinator should integrate parallel work by branch or worktree when possible. If agents share one working tree, they must still obey the same path boundaries and must not run bulk formatters or generators from the repository root unless the coordinator explicitly authorizes it.
Recommended ownership check:
Allowed for the Rust agent: rust/**
Not allowed: curriculum/**, shared/**, dsa/**, go/**, README.md
The only expected cross-agent overlap is conceptual: all agents may implement the same module ID in their own language directory. Their files remain separate because the full path includes the language name.
Use numeric prefixes on stages and modules where a recommended order exists:
go/
├── 01_fundamentals/
│ ├── 01_variables-and-types/
│ ├── 02_control-flow/
│ ├── 03_functions-and-closures/
│ ├── 04_data-modeling/
│ ├── 05_collections/
│ ├── 06_error-handling/
│ ├── 07_modules-and-packages/
│ └── 08_io-and-serialization/
├── 02_application-building/
├── 03_software-craft/
├── 04_design/
├── 05_architecture/
├── 06_production/
├── 07_system-design/
└── 99_projects/
Numbers are the default human navigation path, not the complete curriculum model. curriculum/roadmap.md explains the path, while curriculum/catalog.yaml owns prerequisites, optional branches, and stable unnumbered IDs.
Do not number the language directories. There is no universal progression from TypeScript to Go to Rust.
One agent owns one language directory:
| Agent | Owned directory |
|---|---|
| TypeScript agent | typescript/ |
| Go agent | go/ |
| Python agent | python/ |
| Rust agent | rust/ |
| Haskell agent | haskell/ |
| Java agent | java/ |
The coordinator or a designated curriculum agent owns:
curriculum/shared/dsa/workspace/tools/- root-level documentation
Track agents must not modify another language directory or shared files unless explicitly assigned. To reduce merge conflicts, agents should work in separate branches or worktrees when possible.
Each track agent may add a proposed module list to its own README, but changes to the canonical curriculum map and global progress file belong to the coordinator.
No two agents should be assigned the same language directory in the same milestone. DSA work is assigned separately from language tracks because it has its own cross-language ownership boundary.
Each language directory must have a track README and use the same broad stage names:
<language>/
├── README.md
├── 01_fundamentals/
├── 02_application-building/
├── 03_software-craft/
├── 04_design/
├── 05_architecture/
├── 06_production/
├── 07_system-design/
└── 99_projects/
Do not create every possible directory as an empty placeholder. Create a stage when it has real content or when the current milestone explicitly calls for the stage skeleton.
Each module should be self-contained:
<language>/01_fundamentals/01_variables-and-types/
├── README.md
├── lesson.md
├── reference.md
├── examples/
└── practice/
├── README.md
├── 01_build/
├── 02_debug/
├── 03_review/
└── 04_refactor/
Not every practice type is required for every module, but every module needs a clear practice index and at least one meaningful exercise.
The module index and entry point. It should include:
- learning objectives
- prerequisites
- the recommended order of files and exercises
- available practice types and their status
- language-specific notes
- links to shared concepts and relevant Heyrian content, when available
This is the Foundry lesson, not a copy of a Heyrian page. It should be practical and language-specific while still teaching mental models.
Use this general shape:
- Why the concept matters
- Mental model
- Core language behavior
- How it works under the hood
- Idiomatic patterns
- Common mistakes and failure modes
- Tradeoffs and when not to use an approach
- Runnable examples
- Practice guidance
- Reflection prompts for the learner
The lesson should explain why a technique exists, not only show syntax. It should include comparisons to at least one other supported language when that comparison clarifies the idea.
An authoritative lookup document, separate from the conversational lesson. It should include:
- exact terminology
- syntax and semantics
- type or memory behavior where relevant
- edge cases
- compiler/runtime behavior
- concise examples
- links to official language and standard-library documentation
Do not present uncertain or version-sensitive behavior as fact. Record the language/toolchain version when it affects the material.
Runnable examples that demonstrate the lesson. Examples should be small, focused, and named after the concept.
Rules:
- Do not commit compiled binaries or build directories.
- Examples must be formatted with the language's standard formatter where one exists.
- Examples should run with the commands documented in the track README or module README.
- Every file in
examples/must be a complete, runnable example. Do not leave pseudocode, unresolved placeholders, or unexplained compile errors in this directory. - Go and Haskell examples with separate entry points must use separate subdirectories to avoid duplicate entry-point errors.
- Other languages should still use a structure that is easy to run independently.
Agents must distinguish between teaching scaffolds and finished code:
examples/: must compile or run successfully.practice/01_build/starter/: should compile when practical, with behavioral TODOs exposed by tests. If compilation is intentionally blocked, document why in the exercise README.practice/01_build/solution/: must compile and pass the exercise tests.practice/02_debug/buggy/: must compile or run and fail for the intended reason; it must not fail because of an unrelated syntax or setup error.practice/02_debug/solution: must compile or run and pass the debugging tests.practice/03_review/proposed/: should be runnable enough that review findings can be demonstrated. Any intentional build failure must be part of the review scenario.practice/04_refactor/before/andafter/: must compile or run; the documented behavior tests should pass before and after unless a behavior change is intentional.
Every track README must document its supported toolchain and the exact commands for:
- formatting
- running examples
- running exercise tests
- running the complete track or project test suite, when one exists
Code snippets inside prose are illustrative unless explicitly labeled as runnable. The
actual runnable source of truth belongs in examples/ or a practice directory.
All exercises should use realistic engineering scenarios: configuration loaders, webhook processors, notification dispatchers, rate limiters, connection pools, job workers, API clients, and similar systems. Avoid toy animal or shape hierarchies unless the concept specifically requires them.
Build a working feature from a starter repository.
01_build/
├── README.md
├── starter/
├── tests/
├── solution/
└── variants/ # Optional alternative constraints
The README must state the scenario, constraints, acceptance criteria, suggested commands, and optional hints. The solution is included at creation time.
Diagnose and fix intentionally broken code.
02_debug/
├── README.md # Symptoms and context, not the root cause
├── buggy/
├── tests/
└── solution.md
The bug must map directly to the lesson. The solution should explain the cause, the fix, and how to prevent the issue.
Review a proposed change as if it were a pull request.
03_review/
├── README.md
├── proposed/
├── context/
├── my-review.md # Learner template
└── expert-review.md
Issues should include correctness, maintainability, API design, testing, security, or performance concerns appropriate to the module.
Improve working but poorly structured code.
04_refactor/
├── README.md
├── before/
├── tests/
├── after/
└── analysis.md
Tests should pass before and after the refactoring unless the exercise explicitly explains a behavior change.
Additional practice types such as API design, performance investigation, or codebase navigation may be added when they reinforce the module.
DSA is cross-language and belongs at the repository root:
dsa/
├── README.md
├── 01_concepts/
└── 02_problems/
└── 01_arrays-and-hashing/
└── 01_two-sum/
├── problem.md
├── hints.md
├── tests/
├── solutions/
│ ├── typescript/
│ ├── go/
│ ├── python/
│ ├── rust/
│ ├── haskell/
│ └── java/
└── review.md
Language tracks may teach language-specific collection behavior, but they should link to the root DSA workshop rather than duplicate the same algorithm problems.
Every agent must follow these principles:
- Teach concepts, not syntax memorization.
- Prefer realistic production-flavored scenarios.
- Explain tradeoffs and failure modes.
- Use idiomatic code for the target language.
- Keep examples and solutions runnable.
- Include tests for behavior that matters.
- Make starter code intentionally incomplete only where the exercise requires it.
- Keep solutions available; learners may use them after attempting the work.
- Do not put learner-specific notes or attempts into canonical lesson files.
- Do not copy large blocks of Heyrian content. Link to it or provide a Foundry-specific practical treatment.
- Avoid premature abstraction and unnecessary dependencies.
- Keep module IDs stable even if directory ordering changes.
Agents should work in milestones rather than attempting to generate an entire language universe in one pass.
For each language:
- track README
- variables and types
- control flow
- functions and closures
- data modeling
- collections
- error handling
- modules and packages
- I/O and serialization
- testing fundamentals
- at least one build exercise and one debugging or review exercise per module
- CLI and configuration
- HTTP and API clients/servers
- persistence and database boundaries
- testing strategy and test doubles
- debugging and observability
- concurrency or asynchronous programming
- refactoring and API design
- interfaces and abstraction boundaries
- strategy, observer, factory, builder, decorator/middleware
- repository and dependency injection
- layered and hexagonal architecture
- event-driven and CQRS-style designs where idiomatic
- resilience and retries
- caching and queues
- security fundamentals
- performance and profiling
- system design
- realistic multi-module projects
The coordinator may change the phase scope, but agents should preserve the same quality bar at every phase.
A module is complete when:
README.md,lesson.md, andreference.mdare present and substantive.- Runnable examples exist and the documented commands work.
- At least one practice exercise is complete.
- A standard build exercise includes a starter, tests, and solution.
- Finished solutions pass their tests; intentional starter/debug failures are documented and fail for the intended reason only.
- Debug/review/refactor material contains intentional, explainable issues.
- Links are relative and valid inside the repository where possible.
- No compiled artifacts, caches, or secrets are committed.
- The track README accurately reports coverage and known gaps.
- The agent has recorded verification results and remaining limitations.
A track is complete only when its planned phase milestone is complete. Do not mark an entire language complete merely because its directory exists.
Use this prompt when assigning a track agent:
You are the Foundry <LANGUAGE> track agent.
Read foundry/AGENTS.md completely before working.
Your ownership is only foundry/<LANGUAGE>/. Do not modify other language
directories, shared/, dsa/, curriculum/, workspace/, tools/, or root docs
unless explicitly authorized.
Build the current assigned phase using the track and module contracts in
AGENTS.md. Use stable semantic module IDs and numeric directory prefixes for
recommended navigation. Create substantive lessons, references, runnable
examples, and practice exercises. Do not copy Heyrian content wholesale.
Before finishing:
1. Run the documented formatters, compilers, and tests.
2. Confirm no generated artifacts or secrets are present.
3. Check internal links within your owned directory.
4. Update your track README with actual coverage and known gaps.
5. Return the handoff report below.
Every agent should finish with:
Track: <language>
Phase: <phase>
Completed:
- ...
Files added or changed:
- ...
Verification:
- Formatter: ...
- Example commands: ...
- Tests: ...
Known gaps:
- ...
Shared follow-ups for coordinator:
- ...