@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.
- package/.opencode/plugins/foundry.js +106 -0
- package/LICENSE +21 -0
- package/README.md +250 -0
- package/docs/concepts.md +55 -0
- package/docs/getting-started.md +78 -0
- package/docs/work-spec.md +193 -0
- package/package.json +44 -0
- package/scripts/lib/tags.js +108 -0
- package/scripts/sort.js +410 -0
- package/scripts/validate-tags.js +54 -0
- package/skills/add-appraiser/SKILL.md +101 -0
- package/skills/add-artefact-type/SKILL.md +147 -0
- package/skills/add-cycle/SKILL.md +131 -0
- package/skills/add-flow/SKILL.md +84 -0
- package/skills/add-law/SKILL.md +99 -0
- package/skills/appraise/SKILL.md +142 -0
- package/skills/cycle/SKILL.md +111 -0
- package/skills/flow/SKILL.md +38 -0
- package/skills/forge/SKILL.md +73 -0
- package/skills/hitl/SKILL.md +65 -0
- package/skills/init-foundry/SKILL.md +51 -0
- package/skills/quench/SKILL.md +55 -0
- package/skills/sort/SKILL.md +77 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: hitl
|
|
3
|
+
type: atomic
|
|
4
|
+
description: Human-in-the-loop checkpoint. Pauses the cycle for human input before continuing.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# HITL
|
|
8
|
+
|
|
9
|
+
You are a human-in-the-loop checkpoint. Sort has routed to you because the cycle definition includes a pause point here. Your job is to present context, ask the human whatever needs asking, record their response, and return control to sort.
|
|
10
|
+
|
|
11
|
+
## Protocol
|
|
12
|
+
|
|
13
|
+
1. Read `WORK.md` — understand the current state: goal, artefacts, feedback
|
|
14
|
+
2. Read the cycle definition from `foundry/cycles/<cycle-id>.md` — find the `hitl` configuration for your alias
|
|
15
|
+
3. Present to the human:
|
|
16
|
+
- A summary of where we are in the cycle (what's happened so far, based on WORK.history.yaml)
|
|
17
|
+
- The current state of the artefact (show it or summarise it)
|
|
18
|
+
- Any feedback that exists
|
|
19
|
+
- The prompt from the hitl configuration (or a sensible default)
|
|
20
|
+
4. Wait for the human's response
|
|
21
|
+
5. Record the response — if the human provided actionable direction, note it in WORK.md under the artefact's feedback section as context for the next forge pass
|
|
22
|
+
6. Append a history entry to `WORK.history.yaml`:
|
|
23
|
+
|
|
24
|
+
```yaml
|
|
25
|
+
- timestamp: "<ISO 8601 UTC>"
|
|
26
|
+
cycle: <current-cycle-id>
|
|
27
|
+
stage: <alias>
|
|
28
|
+
iteration: <current iteration>
|
|
29
|
+
comment: "<what the human said or decided — capture the substance>"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
7. Return control to the sort skill
|
|
33
|
+
|
|
34
|
+
## Cycle definition hitl config
|
|
35
|
+
|
|
36
|
+
The cycle definition can include configuration for each hitl checkpoint:
|
|
37
|
+
|
|
38
|
+
```yaml
|
|
39
|
+
hitl:
|
|
40
|
+
review-draft:
|
|
41
|
+
prompt: "Here's the draft. Should we proceed to validation, or do you want changes?"
|
|
42
|
+
accept-result:
|
|
43
|
+
prompt: "The artefact has passed all checks. Accept and complete, or request further refinement?"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The key matches the alias (the part after `hitl:` in the stages list). If no config exists for a hitl alias, use a sensible default:
|
|
47
|
+
|
|
48
|
+
> The cycle has paused for your input. Here's the current state. How would you like to proceed?
|
|
49
|
+
|
|
50
|
+
## Human responses
|
|
51
|
+
|
|
52
|
+
The human might:
|
|
53
|
+
- **Approve** — "looks good, continue" → no changes needed, sort will route to next stage
|
|
54
|
+
- **Request changes** — "change X to Y" → add as feedback in WORK.md: `- [ ] <human's request> #hitl`
|
|
55
|
+
- **Provide context** — "keep in mind that..." → note in the history comment for future stages to reference
|
|
56
|
+
- **Abort** — "stop" → set artefact status to `blocked` in WORK.md, cycle ends
|
|
57
|
+
|
|
58
|
+
If the human adds change requests via hitl, these become feedback items tagged `#hitl`. The forge skill treats them like any other open feedback — it must address or wont-fix them.
|
|
59
|
+
|
|
60
|
+
## What you do NOT do
|
|
61
|
+
|
|
62
|
+
- You do not make decisions for the human — present the state and wait
|
|
63
|
+
- You do not modify the artefact — only WORK.md and WORK.history.yaml
|
|
64
|
+
- You do not skip the pause — the human must respond before continuing
|
|
65
|
+
- You do not filter or summarise away important details — show the full picture
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: init-foundry
|
|
3
|
+
type: atomic
|
|
4
|
+
description: Initialize a Foundry project by creating the foundry/ directory structure
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Initialize Foundry
|
|
8
|
+
|
|
9
|
+
Set up the `foundry/` directory structure in the current project.
|
|
10
|
+
|
|
11
|
+
## Prerequisites
|
|
12
|
+
|
|
13
|
+
- The project must not already have a `foundry/` directory.
|
|
14
|
+
|
|
15
|
+
## Steps
|
|
16
|
+
|
|
17
|
+
1. **Check for existing foundry/ directory**
|
|
18
|
+
- If `foundry/` already exists, inform the user and stop.
|
|
19
|
+
|
|
20
|
+
2. **Create the directory structure**
|
|
21
|
+
Create the following directories, each with a `.gitkeep` file:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
foundry/
|
|
25
|
+
artefacts/.gitkeep
|
|
26
|
+
flows/.gitkeep
|
|
27
|
+
cycles/.gitkeep
|
|
28
|
+
laws/.gitkeep
|
|
29
|
+
appraisers/.gitkeep
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
3. **Commit the structure**
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
git add foundry/
|
|
36
|
+
git commit -m "feat: initialize Foundry project structure"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
4. **Guide next steps**
|
|
40
|
+
|
|
41
|
+
Tell the user:
|
|
42
|
+
|
|
43
|
+
> Foundry is initialized. Here's how to set up your first pipeline:
|
|
44
|
+
>
|
|
45
|
+
> 1. **Define an artefact type** — use the `add-artefact-type` skill
|
|
46
|
+
> 2. **Add laws** — use the `add-law` skill to define quality criteria
|
|
47
|
+
> 3. **Create appraiser personalities** — use the `add-appraiser` skill
|
|
48
|
+
> 4. **Define a cycle** — use the `add-cycle` skill
|
|
49
|
+
> 5. **Create a flow** — use the `add-flow` skill
|
|
50
|
+
>
|
|
51
|
+
> Then run your flow with the `flow` skill.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: quench
|
|
3
|
+
type: atomic
|
|
4
|
+
description: Deterministic validation of an artefact by running CLI commands. Writes feedback to WORK.md.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Quench
|
|
8
|
+
|
|
9
|
+
You run deterministic checks on an artefact by executing the CLI commands defined in the artefact type's validation file. No judgment — commands pass or fail.
|
|
10
|
+
|
|
11
|
+
## When this skill applies
|
|
12
|
+
|
|
13
|
+
This skill only runs if `foundry/artefacts/<type>/validation.md` exists. If there is no validation file for the artefact type, this skill is skipped.
|
|
14
|
+
|
|
15
|
+
## Protocol
|
|
16
|
+
|
|
17
|
+
1. Read `WORK.md` — identify the artefact to validate and its type
|
|
18
|
+
2. Read `foundry/artefacts/<type>/validation.md`
|
|
19
|
+
3. If the file does not exist, output SKIP and stop
|
|
20
|
+
4. For each validation entry:
|
|
21
|
+
- Substitute `{file}` in the command with the artefact path
|
|
22
|
+
- Run the command
|
|
23
|
+
- If exit code is non-zero: add feedback to WORK.md:
|
|
24
|
+
- `- [ ] <failure description from validation.md> #validation`
|
|
25
|
+
5. If all commands exit zero, add no new feedback
|
|
26
|
+
|
|
27
|
+
## Reviewing actioned feedback
|
|
28
|
+
|
|
29
|
+
On subsequent passes, the quench skill re-runs the relevant command for previously actioned items:
|
|
30
|
+
|
|
31
|
+
- `[x]` actioned items: re-run the command
|
|
32
|
+
- If exit code is zero: mark `| approved`
|
|
33
|
+
- If non-zero: mark `| rejected: still failing` (item is effectively re-opened)
|
|
34
|
+
|
|
35
|
+
There is no wont-fix for validation feedback. Deterministic rules are not negotiable.
|
|
36
|
+
|
|
37
|
+
## History
|
|
38
|
+
|
|
39
|
+
After completing validation (whether issues were found or not), append an entry to `WORK.history.yaml`:
|
|
40
|
+
|
|
41
|
+
```yaml
|
|
42
|
+
- timestamp: "<ISO 8601 UTC>"
|
|
43
|
+
cycle: <current-cycle-id>
|
|
44
|
+
stage: <alias>
|
|
45
|
+
iteration: <current iteration from history>
|
|
46
|
+
comment: <brief summary, e.g., "2 validation issues found" or "Validation passed">
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## What you do NOT do
|
|
50
|
+
|
|
51
|
+
- You do not make subjective judgments
|
|
52
|
+
- You do not revise the artefact
|
|
53
|
+
- You do not evaluate laws — that is the appraise skill's job
|
|
54
|
+
- You do not invent validation rules — you only run commands from the validation file
|
|
55
|
+
- You do not duplicate feedback that already exists in WORK.md
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sort
|
|
3
|
+
type: atomic
|
|
4
|
+
description: Deterministic routing for a foundry cycle. Runs scripts/sort.js and returns the next stage.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Sort
|
|
8
|
+
|
|
9
|
+
You are the central dispatcher for a foundry cycle. You run the sort script to determine what stage to execute next, then invoke that stage's skill.
|
|
10
|
+
|
|
11
|
+
## Protocol
|
|
12
|
+
|
|
13
|
+
1. Run the sort script:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
node scripts/sort.js --work WORK.md --history WORK.history.yaml --foundry-dir foundry [--cycle-def <path>]
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The `--cycle-def` argument is optional. It tells the script where to find the cycle definition file for file modification enforcement. Resolution order: `--cycle-def` CLI arg → `cycle-def` frontmatter field in WORK.md → `<foundry-dir>/cycles/<cycle-id>.md`. Only needed if the cycle definition file has a non-standard name or location.
|
|
20
|
+
|
|
21
|
+
2. Read the output: a full alias (e.g., `forge:write-haiku`, `quench:write-haiku`, `hitl:review-draft`) or a bare status (`done`, `blocked`, `violation`)
|
|
22
|
+
|
|
23
|
+
3. Append a sort entry to `WORK.history.yaml`:
|
|
24
|
+
|
|
25
|
+
```yaml
|
|
26
|
+
- timestamp: "<ISO 8601 UTC>"
|
|
27
|
+
cycle: <current-cycle-id>
|
|
28
|
+
stage: sort
|
|
29
|
+
iteration: <current iteration>
|
|
30
|
+
comment: "<your reasoning — why this route was chosen, what feedback state you observed>"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Write the comment yourself in natural language. Explain what the script returned and why it makes sense given the current state. This is your audit trail — if something goes wrong, this comment is what someone will read to understand what happened.
|
|
34
|
+
|
|
35
|
+
4. Act on the result:
|
|
36
|
+
- `forge:*` → dispatch the forge skill as a sub-agent, passing the full alias. Use model-specific dispatch (see Model dispatch below).
|
|
37
|
+
- `quench:*` → dispatch the quench skill as a sub-agent, passing the full alias. Use model-specific dispatch.
|
|
38
|
+
- `appraise:*` → dispatch the appraise skill as a sub-agent, passing the full alias. Use model-specific dispatch. Note: the appraise skill handles its own per-appraiser model resolution internally.
|
|
39
|
+
- `hitl:*` → invoke the hitl skill, passing the full alias (no model dispatch — human stage)
|
|
40
|
+
- `done` → foundry cycle is complete, return to the cycle skill
|
|
41
|
+
- `blocked` → foundry cycle is blocked (iteration limit hit with unresolved feedback), return to the cycle skill
|
|
42
|
+
- `violation` → file modification or tag validation violation detected (details on stderr). The cycle halts — log the violation in WORK.md, set artefact status to `blocked`, and return to the cycle skill
|
|
43
|
+
|
|
44
|
+
### Model dispatch
|
|
45
|
+
|
|
46
|
+
When dispatching a stage as a sub-agent, check WORK.md frontmatter for a `models` map. Extract the stage's base name (e.g., `forge` from `forge:write-haiku`).
|
|
47
|
+
|
|
48
|
+
- If `models.<base>` is set (e.g., `models.forge: openai/gpt-4o`):
|
|
49
|
+
- Convert to agent name: `foundry-openai-gpt-4o`
|
|
50
|
+
- Dispatch with `subagent_type: "foundry-openai-gpt-4o"`
|
|
51
|
+
- If no agent with that name exists, **hard fail**: "Cycle specifies model `<model>` for stage `<base>` but no matching agent `foundry-<name>` is registered. Check your OpenCode provider config."
|
|
52
|
+
- If `models.<base>` is not set:
|
|
53
|
+
- Dispatch with `subagent_type: "general"` (inherits session model)
|
|
54
|
+
|
|
55
|
+
5. After the invoked skill completes, run sort again. Repeat until sort returns `done`, `blocked`, or `violation`.
|
|
56
|
+
|
|
57
|
+
## Enforcement checks
|
|
58
|
+
|
|
59
|
+
The sort script runs two enforcement checks before routing:
|
|
60
|
+
|
|
61
|
+
1. **File modification enforcement** — verifies the last commit only touched files allowed for that stage
|
|
62
|
+
2. **Tag validation** — verifies all feedback tags match `#validation`, `#law:<id>`, or `#hitl`, and that referenced law IDs exist in `foundry/laws/` or the artefact type's `laws.md`
|
|
63
|
+
|
|
64
|
+
Either check failing produces `violation` on stdout with details on stderr.
|
|
65
|
+
|
|
66
|
+
Tag validation is also available as a standalone script:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
node scripts/validate-tags.js --work WORK.md --foundry-dir foundry
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## What you do NOT do
|
|
73
|
+
|
|
74
|
+
- You do not make routing decisions yourself — the script decides
|
|
75
|
+
- You do not skip running the script
|
|
76
|
+
- You do not override the script's output
|
|
77
|
+
- You do not skip writing the history entry — every sort invocation must be logged
|