@really-knows-ai/foundry 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Foundry plugin for OpenCode.ai
3
+ *
4
+ * Conditional bootstrap:
5
+ * - If foundry/ exists in project: full skill registration + pipeline context
6
+ * - If foundry/ does not exist: only init-foundry skill + minimal prompt
7
+ */
8
+
9
+ import path from 'path';
10
+ import fs from 'fs';
11
+ import { fileURLToPath } from 'url';
12
+
13
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
14
+ const packageRoot = path.resolve(__dirname, '../..');
15
+ const allSkillsDir = path.join(packageRoot, 'skills');
16
+ const initSkillDir = path.join(allSkillsDir, 'init-foundry');
17
+
18
+ function getBootstrapContent(directory) {
19
+ const foundryDir = path.join(directory, 'foundry');
20
+ const foundryExists = fs.existsSync(foundryDir) && fs.statSync(foundryDir).isDirectory();
21
+
22
+ if (!foundryExists) {
23
+ return `<FOUNDRY_CONTEXT>
24
+ Foundry is installed but not initialized in this project. There is no foundry/ directory.
25
+
26
+ To set up Foundry, use the \`init-foundry\` skill. This will create the foundry/ directory structure
27
+ and guide you through defining artefact types, laws, appraisers, cycles, and flows.
28
+ </FOUNDRY_CONTEXT>`;
29
+ }
30
+
31
+ return `<FOUNDRY_CONTEXT>
32
+ Foundry is active in this project. The foundry/ directory contains the project's artefact definitions,
33
+ laws, appraisers, cycles, and flows.
34
+
35
+ Foundry is a skill-driven framework for governed artefact generation and evaluation.
36
+ The pipeline: forge (produce) → quench (deterministic checks) → appraise (subjective evaluation) → iterate.
37
+
38
+ Available skills:
39
+ - **Pipeline:** forge, quench, appraise, cycle, flow, sort, hitl
40
+ - **Helpers:** add-artefact-type, add-law, add-appraiser, add-cycle, add-flow, init-foundry
41
+
42
+ Multi-model routing: The Foundry plugin has auto-registered \`foundry-*\` sub-agents for each available model.
43
+ Cycle definitions can specify per-stage models via the \`models\` frontmatter map. Appraisers can override with their own \`model\` field.
44
+
45
+ To start a flow, use the \`flow\` skill. All user content lives under foundry/.
46
+ Scripts are located at: ${path.join(packageRoot, 'scripts')}
47
+ </FOUNDRY_CONTEXT>`;
48
+ }
49
+
50
+ export const FoundryPlugin = async ({ client, directory }) => {
51
+ const foundryDir = path.join(directory, 'foundry');
52
+ const foundryExists = fs.existsSync(foundryDir) && fs.statSync(foundryDir).isDirectory();
53
+
54
+ return {
55
+ config: async (config) => {
56
+ config.skills = config.skills || {};
57
+ config.skills.paths = config.skills.paths || [];
58
+
59
+ if (foundryExists) {
60
+ if (!config.skills.paths.includes(allSkillsDir)) {
61
+ config.skills.paths.push(allSkillsDir);
62
+ }
63
+
64
+ // Register per-model subagents for multi-model stage routing
65
+ try {
66
+ const providers = await client.provider.list();
67
+ config.agent = config.agent || {};
68
+ for (const provider of providers) {
69
+ if (!provider.models) continue;
70
+ const modelKeys = Array.isArray(provider.models)
71
+ ? provider.models
72
+ : Object.keys(provider.models);
73
+ for (const modelKey of modelKeys) {
74
+ const agentName = `foundry-${provider.id}-${modelKey}`;
75
+ config.agent[agentName] = {
76
+ model: `${provider.id}/${modelKey}`,
77
+ mode: 'subagent',
78
+ hidden: true,
79
+ description: `Foundry stage agent using ${provider.id}/${modelKey}`,
80
+ };
81
+ }
82
+ }
83
+ } catch (err) {
84
+ console.warn('[foundry] Failed to discover models for agent registration:', err.message);
85
+ }
86
+ } else {
87
+ if (!config.skills.paths.includes(initSkillDir)) {
88
+ config.skills.paths.push(initSkillDir);
89
+ }
90
+ }
91
+ },
92
+
93
+ 'experimental.chat.messages.transform': async (_input, output) => {
94
+ const bootstrap = getBootstrapContent(directory);
95
+ if (!bootstrap || !output.messages.length) return;
96
+
97
+ const firstUser = output.messages.find(m => m.info.role === 'user');
98
+ if (!firstUser || !firstUser.parts.length) return;
99
+
100
+ if (firstUser.parts.some(p => p.type === 'text' && p.text.includes('FOUNDRY_CONTEXT'))) return;
101
+
102
+ const ref = firstUser.parts[0];
103
+ firstUser.parts.unshift({ ...ref, type: 'text', text: bootstrap });
104
+ }
105
+ };
106
+ };
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Really Knows AI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,250 @@
1
+ # Foundry
2
+
3
+ A skill-driven framework for governed artefact generation and evaluation using AI coding tools. Install it as an npm package and define your own artefact types, laws, and flows — Foundry handles the forge-quench-appraise pipeline.
4
+
5
+ ## Compatibility
6
+
7
+ - **OpenCode** — full support, multi-model routing via plugin-registered agents
8
+
9
+ Multi-model support enables model diversity across pipeline stages. The Foundry plugin auto-discovers available models at startup and registers them as hidden sub-agents. Cycle definitions specify which model each stage uses. Tools limited to a single model lose model-diversity but still get personality-based diversity.
10
+
11
+ ## Installation
12
+
13
+ Add `@really-knows-ai/foundry` to your OpenCode config:
14
+
15
+ ```json
16
+ // opencode.json
17
+ {
18
+ "packages": {
19
+ "@really-knows-ai/foundry": "latest"
20
+ }
21
+ }
22
+ ```
23
+
24
+ ## Quick start
25
+
26
+ 1. **Install** the package as shown above
27
+ 2. **Initialize** — use the `init-foundry` skill to scaffold a `foundry/` directory in your project
28
+ 3. **Define artefact types** — use `add-artefact-type` to create types with file patterns, descriptions, and optional validation
29
+ 4. **Add laws** — use `add-law` to define subjective pass/fail criteria (global or per-type)
30
+ 5. **Add appraisers** — use `add-appraiser` to create appraiser personalities
31
+ 6. **Define cycles** — use `add-cycle` to wire artefact types into forge/quench/appraise loops
32
+ 7. **Define flows** — use `add-flow` to sequence cycles into end-to-end pipelines
33
+ 8. **Run** — use the `flow` skill to execute a flow
34
+
35
+ ## How it works
36
+
37
+ ```
38
+ Foundry Flow
39
+ └─ Cycle 1 (e.g., ideation)
40
+ │ ├─ Forge → produce the artefact
41
+ │ ├─ Quench → deterministic CLI checks (if defined)
42
+ │ ├─ Appraise → subjective evaluation by multiple appraisers
43
+ │ └─ ↺ iterate until all feedback is resolved
44
+ └─ Cycle 2 (e.g., creation)
45
+ ├─ reads output from Cycle 1 (read-only)
46
+ ├─ Forge → produce the artefact
47
+ ├─ Quench → deterministic CLI checks
48
+ ├─ Appraise → subjective evaluation
49
+ └─ ↺ iterate until all feedback is resolved
50
+ ```
51
+
52
+ A **foundry flow** runs one or more **foundry cycles** in sequence. Each cycle produces a single artefact type by looping through forge → quench → appraise until the artefact passes all criteria. The output of one cycle becomes read-only input for the next.
53
+
54
+ All state lives in `WORK.md` on a dedicated work branch. Every stage micro-commits, and file modification enforcement ensures stages only touch what they're allowed to.
55
+
56
+ ## Core concepts
57
+
58
+ ### Foundry Flows
59
+
60
+ Defined in `foundry/flows/`. A flow lists cycles to execute in order. Starting a flow creates a work branch and a fresh `WORK.md`.
61
+
62
+ ### Foundry Cycles
63
+
64
+ Defined in `foundry/cycles/`. A cycle specifies:
65
+ - `output` — the artefact type it produces (read-write)
66
+ - `inputs` — artefact types from previous cycles (read-only)
67
+
68
+ ### Stages
69
+
70
+ The three steps within a cycle:
71
+ - **Forge** — produce or revise the artefact
72
+ - **Quench** — run deterministic CLI checks (skipped if artefact type has no `validation.md`)
73
+ - **Appraise** — subjective evaluation by multiple independent appraisers
74
+
75
+ ### Artefact types
76
+
77
+ Defined in `foundry/artefacts/<type>/`. Each type has:
78
+ - `definition.md` — id, name, file patterns, output directory, appraiser config, prose description
79
+ - `laws.md` (optional) — type-specific subjective criteria
80
+ - `validation.md` (optional) — CLI commands with `{file}` placeholder; non-zero exit = failure
81
+
82
+ ### Laws
83
+
84
+ Subjective pass/fail criteria. Two scopes:
85
+ - `foundry/laws/*.md` — global laws, all files concatenated, apply to everything
86
+ - `foundry/artefacts/<type>/laws.md` — type-specific laws
87
+
88
+ Each law is a `## heading` (the identifier, used in feedback tags as `#law:<id>`) with a description, passing criteria, and failing criteria.
89
+
90
+ ### Appraisers
91
+
92
+ Defined in `foundry/appraisers/`. Each appraiser has a personality and an optional model override. Appraisers are assigned to artefact types via the `appraisers` section in the type's `definition.md`:
93
+
94
+ ```yaml
95
+ appraisers:
96
+ count: 3 # how many appraisers (default: 3)
97
+ allowed: [pedantic, pragmatic] # which personalities (default: all available)
98
+ ```
99
+
100
+ Appraisers are distributed evenly across available personalities for maximum diversity. If you request 6 appraisers with 3 personalities, you get 2 of each. Model diversity is configured at the cycle level (per-stage) and optionally per-appraiser — see [concepts](docs/concepts.md).
101
+
102
+ ### WORK.md
103
+
104
+ Transient shared state on the work branch. Tracks:
105
+ - Current position (flow, cycle, stage) in frontmatter
106
+ - Goal description
107
+ - Artefact registry (what exists, its status)
108
+ - All feedback with full lifecycle
109
+
110
+ ### Feedback lifecycle
111
+
112
+ ```
113
+ open - [ ] issue #tag → needs generator action
114
+ actioned - [x] issue #tag → needs approval
115
+ wont-fix - [~] issue #tag | wont-fix: <reason> → needs approval
116
+ approved - [x] issue #tag | approved → resolved
117
+ approved - [~] issue #tag | wont-fix: <reason> | approved → resolved
118
+ rejected - [x] issue #tag | rejected: <reason> → re-opened
119
+ rejected - [~] issue #tag | wont-fix: <reason> | rejected → re-opened
120
+ ```
121
+
122
+ Validation feedback (`#validation`) cannot be wont-fixed — deterministic rules are not negotiable.
123
+
124
+ ### File modification enforcement
125
+
126
+ Every stage micro-commits. The cycle checks the git diff:
127
+ - After forge: only output artefact file patterns + WORK.md + WORK.history.yaml (input artefacts are read-only — violation if touched)
128
+ - After quench/appraise: only WORK.md + WORK.history.yaml
129
+ - Violations are hard stops
130
+
131
+ > **Merge hygiene:** WORK.md and WORK.history.yaml are ephemeral working files. Delete them before squash-merging the branch back into main.
132
+
133
+ ## Skills
134
+
135
+ Everything is a skill. Skills are either atomic (do one thing) or composite (orchestrate other skills).
136
+
137
+ ### Pipeline skills
138
+
139
+ | Skill | Type | Purpose |
140
+ |-------|------|---------|
141
+ | `forge` | atomic | Produce or revise an artefact |
142
+ | `quench` | atomic | Run deterministic CLI checks |
143
+ | `appraise` | atomic | Dispatch multiple appraisers, consolidate feedback |
144
+ | `cycle` | composite | forge → quench → appraise → iterate |
145
+ | `flow` | composite | Orchestrate cycles on a work branch |
146
+
147
+ ### Helper skills
148
+
149
+ | Skill | Purpose |
150
+ |-------|---------|
151
+ | `init-foundry` | Scaffold the `foundry/` directory in your project |
152
+ | `add-artefact-type` | Create a new artefact type with conflict and glob-overlap checks |
153
+ | `add-law` | Create a new law with conflict detection |
154
+ | `add-appraiser` | Create a new appraiser personality with semantic overlap checks |
155
+ | `add-cycle` | Create a new cycle within a flow with dependency validation |
156
+ | `add-flow` | Create a new flow definition |
157
+
158
+ ### Utility skills
159
+
160
+ | Skill | Purpose |
161
+ |-------|---------|
162
+ | `sort` | Deterministic cycle router — determines and dispatches the next stage |
163
+ | `hitl` | Human-in-the-loop intervention points |
164
+
165
+ All helper skills are interactive — they walk you through the process, check for conflicts, and confirm before writing files.
166
+
167
+ ## Package structure
168
+
169
+ ```
170
+ @really-knows-ai/foundry
171
+ ├── .opencode/
172
+ │ └── plugins/
173
+ │ └── foundry.js # OpenCode plugin (registers skills)
174
+ ├── skills/ # skill definitions (the pipeline)
175
+ │ ├── forge/
176
+ │ ├── quench/
177
+ │ ├── appraise/
178
+ │ ├── cycle/
179
+ │ ├── flow/
180
+ │ ├── init-foundry/
181
+ │ ├── add-artefact-type/
182
+ │ ├── add-law/
183
+ │ ├── add-appraiser/
184
+ │ ├── add-cycle/
185
+ │ ├── add-flow/
186
+ │ ├── sort/
187
+ │ └── hitl/
188
+ ├── scripts/ # validation support scripts
189
+ ├── docs/ # concept docs and specs
190
+ ├── package.json
191
+ └── README.md
192
+ ```
193
+
194
+ ## User project structure
195
+
196
+ After running `init-foundry`, your project gets a `foundry/` directory:
197
+
198
+ ```
199
+ your-project/
200
+ ├── foundry/
201
+ │ ├── flows/ # flow definitions
202
+ │ ├── cycles/ # cycle definitions
203
+ │ ├── artefacts/ # artefact type definitions
204
+ │ │ └── <type>/
205
+ │ │ ├── definition.md
206
+ │ │ ├── laws.md # (optional) type-specific laws
207
+ │ │ └── validation.md # (optional) CLI checks
208
+ │ ├── laws/ # global laws
209
+ │ └── appraisers/ # appraiser personalities
210
+ ├── opencode.json
211
+ └── ...
212
+ ```
213
+
214
+ ## Design decisions
215
+
216
+ ### Everything is markdown
217
+
218
+ Flow definitions, cycle definitions, artefact types, laws, appraiser personalities, skills — all markdown. Readable by humans, consumable by LLMs, versionable in git. No config files, no databases, no custom formats.
219
+
220
+ ### Skills are the pipeline
221
+
222
+ No separate runner script. Composition happens via skills referencing other skills. The `flow` skill reads a flow definition and invokes the `cycle` skill. The `cycle` skill invokes `forge`, `quench`, and `appraise`. This keeps everything in one format.
223
+
224
+ ### WORK.md as shared state
225
+
226
+ All communication between stages goes through WORK.md. No stage passes output directly to another. This gives a complete audit trail, makes the process resumable, and means any stage can be re-run independently.
227
+
228
+ ### Feedback as checklist items
229
+
230
+ Feedback uses markdown checklists with `#validation` or `#law:<id>` tags. Human-readable, trivially parseable by an LLM, with lifecycle states expressed inline.
231
+
232
+ ### Wont-fix requires appraiser approval
233
+
234
+ The generator can decline subjective feedback with a justification, but an appraiser must approve or reject that decision. This prevents silently ignoring feedback while allowing legitimate pushback.
235
+
236
+ ### Multi-model stage routing
237
+
238
+ Cycle definitions specify which model each stage uses via a `models` map. The Foundry plugin auto-discovers available models and registers them as `foundry-*` sub-agents. Individual appraisers can override the cycle-level model. Resolution order: appraiser `model` → cycle `models.<stage>` → session default. Multiple personalities catch different issues. Consolidation is union with dedup — one appraiser flagging an issue is enough.
239
+
240
+ ### Input artefacts are read-only
241
+
242
+ When a cycle reads from a previous cycle's output, those files cannot be modified. Enforced via git diff after every micro-commit. This prevents downstream cycles from corrupting upstream work.
243
+
244
+ ### Glob patterns must not overlap
245
+
246
+ Two artefact types cannot have file patterns that match the same files. This is checked when creating new types and is a hard block — file modification enforcement can't determine ownership if patterns overlap.
247
+
248
+ ## License
249
+
250
+ [MIT](LICENSE)
@@ -0,0 +1,55 @@
1
+ # Concepts
2
+
3
+ Core concepts and how they relate.
4
+
5
+ ## Foundry Flow
6
+
7
+ A foundry flow is the top-level unit of work. It is defined in `foundry/flows/` and lists the foundry cycles to execute in order. Starting a foundry flow creates a work branch and a WORK.md file. A foundry flow is complete when all its foundry cycles are done.
8
+
9
+ ## Foundry Cycle
10
+
11
+ A foundry cycle is an iterative loop that produces a single artefact type. It is defined in `foundry/cycles/` and specifies:
12
+ - An output artefact type (read-write)
13
+ - Zero or more input artefact types (read-only, from previous foundry cycles)
14
+
15
+ A foundry cycle runs: forge → quench → appraise, repeating until all feedback is resolved or the iteration limit is hit.
16
+
17
+ ## Stage
18
+
19
+ The steps within a foundry cycle. Each stage is referenced using a `base:alias` format (e.g. `forge:write-haiku`) where the base is the stage type and the alias describes its role in that cycle.
20
+
21
+ - Forge — produce or revise the artefact
22
+ - Quench — run deterministic CLI checks
23
+ - Appraise — subjective evaluation by multiple appraisers
24
+ - HITL — human-in-the-loop checkpoint (see below)
25
+
26
+ ## Artefact type
27
+
28
+ A definition of what kind of thing is being produced. Lives in `foundry/artefacts/<type>/` with:
29
+ - `definition.md` — identity, file patterns, output location, prose description
30
+ - `laws.md` — type-specific subjective evaluation criteria
31
+ - `validation.md` — CLI commands for deterministic quench checks
32
+
33
+ ## Law
34
+
35
+ A subjective pass/fail criterion. Global laws live in `foundry/laws/` (all files concatenated). Type-specific laws live in `foundry/artefacts/<type>/laws.md`. Each law has an identifier (its heading), used in feedback tags.
36
+
37
+ ## Appraiser
38
+
39
+ An independent evaluator with a defined personality. Lives in `foundry/appraisers/`. Each appraiser can optionally specify a `model` to override the cycle-level appraise model. Model diversity is configured at the cycle level (via the `models` frontmatter map) and optionally per-appraiser. They can be assigned to specific artefact types or appraise everything.
40
+
41
+ ## WORK.md
42
+
43
+ The transient shared state for a foundry flow. Created on the work branch, it tracks: where the foundry flow is (frontmatter cursor), what artefacts exist, and all feedback with its full lifecycle. See [work-spec.md](work-spec.md) for the full spec.
44
+
45
+ ## Feedback
46
+
47
+ The communication mechanism between stages. Written as markdown checklist items in WORK.md with tags (`#validation` or `#law:<id>`). Follows a lifecycle: open → actioned/wont-fix → approved/rejected. See [work-spec.md](work-spec.md) for details.
48
+
49
+ ## HITL
50
+
51
+ Human-in-the-loop checkpoint. A stage type that pauses the foundry cycle and requests human input before continuing. Configured per cycle by including a `hitl:alias` entry in the `stages` list. When a hitl stage runs, it presents the current artefact state to the human and collects feedback tagged `#hitl`. Like other feedback, hitl feedback follows the standard lifecycle (open → actioned → approved/rejected).
52
+
53
+ ## Micro commit
54
+
55
+ Every stage ends with a commit. This enables file modification enforcement — the foundry cycle checks the git diff to ensure each stage only touched files it was allowed to.
@@ -0,0 +1,78 @@
1
+ # Getting Started
2
+
3
+ How to set up and run your first foundry flow.
4
+
5
+ ## Prerequisites
6
+
7
+ - Git repository initialised
8
+ - Node.js available (for validation scripts)
9
+ - An AI coding tool that supports skills (OpenCode, Claude Code, Copilot CLI, etc.)
10
+
11
+ ## Step by step
12
+
13
+ ### 1. Define an artefact type
14
+
15
+ Create a directory under `foundry/artefacts/` with three files:
16
+
17
+ ```
18
+ foundry/artefacts/my-type/
19
+ definition.md # what it is, file patterns, output location
20
+ laws.md # subjective laws (optional)
21
+ validation.md # CLI validation commands (optional)
22
+ ```
23
+
24
+ Use the `init-foundry` skill to scaffold the `foundry/` directory, then use `add-artefact-type` to create your first artefact type interactively — or create the directory structure above manually.
25
+
26
+ ### 2. Write laws
27
+
28
+ Add global laws to any `.md` file in `foundry/laws/`. Add type-specific laws to `foundry/artefacts/<type>/laws.md`.
29
+
30
+ Each law is a `##` heading with: a description, what passing looks like, and what failing looks like.
31
+
32
+ ### 3. Define a foundry cycle
33
+
34
+ Create a file in `foundry/cycles/` that specifies what artefact type the foundry cycle produces and what inputs it reads:
35
+
36
+ ```yaml
37
+ ---
38
+ id: my-cycle
39
+ name: My Cycle
40
+ output: my-type
41
+ inputs: []
42
+ ---
43
+ ```
44
+
45
+ Cycles list their stages using `base:alias` format — e.g. `forge:write-haiku`, `quench:check-syllables`. The alias makes each stage's purpose clear when reading WORK.md. You can also include `hitl:alias` stages for human-in-the-loop checkpoints.
46
+
47
+ ### 4. Define a foundry flow
48
+
49
+ Create a file in `foundry/flows/` that lists foundry cycles in order:
50
+
51
+ ```markdown
52
+ ---
53
+ id: my-flow
54
+ name: My Flow
55
+ ---
56
+
57
+ # My Flow
58
+
59
+ Description of what this flow produces.
60
+
61
+ ## Cycles
62
+
63
+ 1. my-cycle
64
+ ```
65
+
66
+ ### 5. Run the foundry flow
67
+
68
+ Tell your AI tool to start the foundry flow. It will create a work branch, initialise WORK.md, and begin executing foundry cycles.
69
+
70
+ ## What happens during a foundry flow
71
+
72
+ 1. The foundry flow skill creates a branch and WORK.md
73
+ 2. For each foundry cycle:
74
+ - Forge produces the artefact
75
+ - Quench runs CLI commands (if defined)
76
+ - Appraise dispatches sub-agent appraisers against the laws
77
+ - If feedback exists, forge revises and the foundry cycle repeats
78
+ 3. When all foundry cycles complete, the human decides to merge, PR, or discard