@really-knows-ai/foundry 1.2.2 → 1.3.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 +408 -1
- package/README.md +31 -5
- package/docs/concepts.md +5 -1
- package/docs/work-spec.md +7 -7
- package/package.json +2 -2
- package/scripts/lib/artefacts.js +118 -0
- package/scripts/lib/config.js +154 -0
- package/scripts/lib/feedback.js +285 -0
- package/scripts/lib/history.js +47 -0
- package/scripts/lib/workfile.js +53 -0
- package/scripts/sort.js +54 -196
- package/skills/appraise/SKILL.md +24 -83
- package/skills/cycle/SKILL.md +25 -62
- package/skills/flow/SKILL.md +12 -38
- package/skills/forge/SKILL.md +25 -41
- package/skills/hitl/SKILL.md +18 -41
- package/skills/quench/SKILL.md +15 -44
- package/skills/sort/SKILL.md +20 -53
package/skills/forge/SKILL.md
CHANGED
|
@@ -6,7 +6,7 @@ description: Produces or revises an artefact, guided by WORK.md and the foundry
|
|
|
6
6
|
|
|
7
7
|
# Forge
|
|
8
8
|
|
|
9
|
-
You produce or revise artefacts. You read
|
|
9
|
+
You produce or revise artefacts. You read the work file to understand the goal and feedback, and the foundry cycle definition to understand what you're producing and what inputs you can read.
|
|
10
10
|
|
|
11
11
|
## Prerequisites
|
|
12
12
|
|
|
@@ -16,59 +16,43 @@ Before running this skill, verify that the `foundry/` directory exists in the pr
|
|
|
16
16
|
|
|
17
17
|
## Protocol
|
|
18
18
|
|
|
19
|
-
### First generation (no artefact registered
|
|
19
|
+
### First generation (no artefact registered yet)
|
|
20
20
|
|
|
21
|
-
1.
|
|
22
|
-
2.
|
|
23
|
-
3.
|
|
24
|
-
4.
|
|
25
|
-
5.
|
|
26
|
-
6.
|
|
27
|
-
7.
|
|
28
|
-
8.
|
|
29
|
-
9. Register the artefact in the WORK.md artefacts table. The table MUST have all four columns — File, Type, Cycle, Status. Set cycle to the current cycle id from WORK.md frontmatter. Set status to `draft`.
|
|
21
|
+
1. Call `foundry_workfile_get` — understand the goal
|
|
22
|
+
2. Call `foundry_config_cycle` — understand what to produce and what inputs are available
|
|
23
|
+
3. Call `foundry_config_artefact_type` with the output type ID — get the artefact type definition
|
|
24
|
+
4. Call `foundry_config_laws` — get all applicable laws (global + type-specific)
|
|
25
|
+
5. If the cycle has inputs, read the input artefacts (read-only context)
|
|
26
|
+
6. Produce the artefact, respecting all applicable laws from the start (this is judgment — use your craft)
|
|
27
|
+
7. Write the artefact file to the location specified in the artefact type definition
|
|
28
|
+
8. Call `foundry_artefacts_add` with the file path, type, and cycle to register it with status `"draft"`
|
|
30
29
|
|
|
31
|
-
### Revision (feedback exists
|
|
30
|
+
### Revision (feedback exists)
|
|
32
31
|
|
|
33
|
-
1.
|
|
34
|
-
2. Read the artefact
|
|
35
|
-
3. If the
|
|
32
|
+
1. Call `foundry_feedback_list` to find unresolved feedback for the artefact
|
|
33
|
+
2. Read the artefact file
|
|
34
|
+
3. If the cycle has inputs, read the input artefacts (read-only context)
|
|
36
35
|
4. For each unresolved feedback item, either:
|
|
37
|
-
- Address it and
|
|
38
|
-
-
|
|
36
|
+
- Address it and call `foundry_feedback_action` with the item ID (marks as actioned)
|
|
37
|
+
- Call `foundry_feedback_wontfix` with the item ID and a justification (appraisal feedback only)
|
|
39
38
|
5. Update the artefact file
|
|
40
|
-
6. Wont-fix is only available for
|
|
39
|
+
6. Wont-fix is only available for `law:` feedback (subjective appraisal). Validation feedback must be actioned — deterministic rules are not negotiable.
|
|
41
40
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
An item is unresolved if it is:
|
|
45
|
-
- `[ ]` — open, not yet addressed
|
|
46
|
-
- `[x] ... | rejected: ...` — actioned but rejected by appraiser, effectively re-opened
|
|
47
|
-
- `[~] ... | rejected` — wont-fix rejected by appraiser, effectively re-opened
|
|
48
|
-
|
|
49
|
-
An item is resolved if it is:
|
|
50
|
-
- `[x] ... | approved`
|
|
51
|
-
- `[~] ... | approved`
|
|
41
|
+
### After (both paths)
|
|
52
42
|
|
|
53
|
-
|
|
43
|
+
Call `foundry_history_append` with the current cycle, the full stage alias (e.g., `forge:write-haiku`), and a brief description of what you did.
|
|
54
44
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
```yaml
|
|
58
|
-
- timestamp: "<ISO 8601 UTC>"
|
|
59
|
-
cycle: <current-cycle-id>
|
|
60
|
-
stage: <alias>
|
|
61
|
-
iteration: <n>
|
|
62
|
-
comment: <brief description of what you did>
|
|
63
|
-
```
|
|
45
|
+
## Unresolved feedback
|
|
64
46
|
|
|
65
|
-
|
|
47
|
+
An item is unresolved if it is:
|
|
48
|
+
- `open` — not yet addressed
|
|
49
|
+
- `rejected` — actioned or wont-fixed but rejected by appraiser, effectively re-opened
|
|
66
50
|
|
|
67
|
-
|
|
51
|
+
An item is resolved if it is `approved`.
|
|
68
52
|
|
|
69
53
|
## Feedback tagged `#hitl`
|
|
70
54
|
|
|
71
|
-
Feedback tagged
|
|
55
|
+
Feedback tagged `hitl` (human-in-the-loop) is treated the same as any other open feedback. Address it or wont-fix it using the same rules as other feedback items.
|
|
72
56
|
|
|
73
57
|
## What you do NOT do
|
|
74
58
|
|
package/skills/hitl/SKILL.md
CHANGED
|
@@ -16,56 +16,33 @@ Before running this skill, verify that the `foundry/` directory exists in the pr
|
|
|
16
16
|
|
|
17
17
|
## Protocol
|
|
18
18
|
|
|
19
|
-
1.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
-
|
|
19
|
+
1. Gather context by calling:
|
|
20
|
+
- `foundry_workfile_get` — current state, goal, artefacts
|
|
21
|
+
- `foundry_config_cycle` — cycle definition and hitl configuration
|
|
22
|
+
- `foundry_history_list` — what has happened so far
|
|
23
|
+
- `foundry_feedback_list` — any existing feedback
|
|
24
|
+
|
|
25
|
+
2. Present to the human:
|
|
26
|
+
- A summary of where we are in the cycle (what's happened so far)
|
|
23
27
|
- The current state of the artefact (show it or summarise it)
|
|
24
28
|
- Any feedback that exists
|
|
25
|
-
- The prompt from the hitl configuration (or a sensible default)
|
|
26
|
-
4. Wait for the human's response
|
|
27
|
-
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
|
|
28
|
-
6. Append a history entry to `WORK.history.yaml`:
|
|
29
|
+
- The prompt from the hitl configuration (or a sensible default: "The cycle has paused for your input. Here's the current state. How would you like to proceed?")
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
- timestamp: "<ISO 8601 UTC>"
|
|
32
|
-
cycle: <current-cycle-id>
|
|
33
|
-
stage: <alias>
|
|
34
|
-
iteration: <current iteration>
|
|
35
|
-
comment: "<what the human said or decided — capture the substance>"
|
|
36
|
-
```
|
|
31
|
+
3. Wait for the human's response.
|
|
37
32
|
|
|
38
|
-
|
|
33
|
+
4. Act on the response:
|
|
34
|
+
- **Approve** — "looks good, continue" — no changes needed, sort will route to next stage
|
|
35
|
+
- **Request changes** — call `foundry_feedback_add` with the human's request and tag `"hitl"`
|
|
36
|
+
- **Provide context** — note in the history comment for future stages to reference
|
|
37
|
+
- **Abort** — call `foundry_artefacts_set_status` with status `"blocked"`, cycle ends
|
|
39
38
|
|
|
40
|
-
|
|
39
|
+
5. Call `foundry_history_append` with the current cycle, stage alias, and a comment capturing the substance of what the human said or decided.
|
|
41
40
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
```yaml
|
|
45
|
-
hitl:
|
|
46
|
-
review-draft:
|
|
47
|
-
prompt: "Here's the draft. Should we proceed to validation, or do you want changes?"
|
|
48
|
-
accept-result:
|
|
49
|
-
prompt: "The artefact has passed all checks. Accept and complete, or request further refinement?"
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
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:
|
|
53
|
-
|
|
54
|
-
> The cycle has paused for your input. Here's the current state. How would you like to proceed?
|
|
55
|
-
|
|
56
|
-
## Human responses
|
|
57
|
-
|
|
58
|
-
The human might:
|
|
59
|
-
- **Approve** — "looks good, continue" → no changes needed, sort will route to next stage
|
|
60
|
-
- **Request changes** — "change X to Y" → add as feedback in WORK.md: `- [ ] <human's request> #hitl`
|
|
61
|
-
- **Provide context** — "keep in mind that..." → note in the history comment for future stages to reference
|
|
62
|
-
- **Abort** — "stop" → set artefact status to `blocked` in WORK.md, cycle ends
|
|
63
|
-
|
|
64
|
-
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.
|
|
41
|
+
6. Return control to the sort skill.
|
|
65
42
|
|
|
66
43
|
## What you do NOT do
|
|
67
44
|
|
|
68
45
|
- You do not make decisions for the human — present the state and wait
|
|
69
|
-
- You do not modify the artefact
|
|
46
|
+
- You do not modify the artefact
|
|
70
47
|
- You do not skip the pause — the human must respond before continuing
|
|
71
48
|
- You do not filter or summarise away important details — show the full picture
|
package/skills/quench/SKILL.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: quench
|
|
3
3
|
type: atomic
|
|
4
|
-
description: Deterministic validation of an artefact by running CLI commands. Writes feedback
|
|
4
|
+
description: Deterministic validation of an artefact by running CLI commands. Writes feedback via foundry tools.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Quench
|
|
8
8
|
|
|
9
|
-
You run deterministic checks on an artefact by executing the CLI commands defined in the artefact type's validation
|
|
9
|
+
You run deterministic checks on an artefact by executing the CLI commands defined in the artefact type's validation config. No judgment — commands pass or fail.
|
|
10
10
|
|
|
11
11
|
## Prerequisites
|
|
12
12
|
|
|
@@ -14,62 +14,33 @@ Before running this skill, verify that the `foundry/` directory exists in the pr
|
|
|
14
14
|
|
|
15
15
|
> Foundry is not initialized in this project. Run the `init-foundry` skill first to create the foundry/ directory structure.
|
|
16
16
|
|
|
17
|
-
## When this skill applies
|
|
18
|
-
|
|
19
|
-
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.
|
|
20
|
-
|
|
21
17
|
## Protocol
|
|
22
18
|
|
|
23
|
-
1.
|
|
24
|
-
2.
|
|
25
|
-
3.
|
|
26
|
-
4. For each validation
|
|
27
|
-
|
|
28
|
-
- Run the command
|
|
29
|
-
- If exit code is non-zero: add feedback to WORK.md under the artefact's file heading
|
|
30
|
-
5. If all commands exit zero, add no new feedback
|
|
31
|
-
|
|
32
|
-
## Feedback format
|
|
33
|
-
|
|
34
|
-
Feedback MUST be scoped to the artefact file it applies to. Under `## Feedback`, create a `### <file-path>` sub-heading matching the artefact's File column from the artefacts table, then write feedback items beneath it:
|
|
35
|
-
|
|
36
|
-
```markdown
|
|
37
|
-
## Feedback
|
|
38
|
-
|
|
39
|
-
### foundry/output/haiku/pissed-off-spaghetti.md
|
|
40
|
-
- [ ] The haiku does not have exactly 3 lines. #validation
|
|
41
|
-
- [ ] One or more lines do not match the 5-7-5 syllable pattern. #validation
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
If the `## Feedback` section or the file sub-heading already exists, append items under the existing heading. Never write feedback items without a file sub-heading — the sort script cannot parse them.
|
|
19
|
+
1. Call `foundry_workfile_get` to identify the artefact and its type.
|
|
20
|
+
2. Call `foundry_config_validation` with the artefact type ID. If it returns null, output SKIP and stop — there is no validation for this type.
|
|
21
|
+
3. Call `foundry_validate_run` with the type ID and artefact file path. It executes all validation commands and returns results.
|
|
22
|
+
4. For each failure: call `foundry_feedback_add` with the artefact file path, a description of the failure, and tag `"validation"`.
|
|
23
|
+
5. If all commands pass, add no new feedback.
|
|
45
24
|
|
|
46
25
|
## Reviewing actioned feedback
|
|
47
26
|
|
|
48
|
-
On subsequent passes,
|
|
27
|
+
On subsequent passes, review previously actioned items:
|
|
49
28
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
29
|
+
1. Call `foundry_feedback_list` to find `actioned` items tagged `validation` for this artefact.
|
|
30
|
+
2. Re-run the relevant command via `foundry_validate_run`.
|
|
31
|
+
3. If the check now passes: call `foundry_feedback_resolve` with disposition `"approved"`.
|
|
32
|
+
4. If it still fails: call `foundry_feedback_resolve` with disposition `"rejected"` and a reason.
|
|
53
33
|
|
|
54
34
|
There is no wont-fix for validation feedback. Deterministic rules are not negotiable.
|
|
55
35
|
|
|
56
36
|
## History
|
|
57
37
|
|
|
58
|
-
After completing validation
|
|
59
|
-
|
|
60
|
-
```yaml
|
|
61
|
-
- timestamp: "<ISO 8601 UTC>"
|
|
62
|
-
cycle: <current-cycle-id>
|
|
63
|
-
stage: <alias>
|
|
64
|
-
iteration: <current iteration from history>
|
|
65
|
-
comment: <brief summary, e.g., "2 validation issues found" or "Validation passed">
|
|
66
|
-
```
|
|
38
|
+
After completing validation, call `foundry_history_append` with the current cycle, stage alias, and a brief summary (e.g., "2 validation issues found" or "Validation passed").
|
|
67
39
|
|
|
68
40
|
## What you do NOT do
|
|
69
41
|
|
|
70
42
|
- You do not make subjective judgments
|
|
71
43
|
- You do not revise the artefact
|
|
72
44
|
- You do not evaluate laws — that is the appraise skill's job
|
|
73
|
-
- You do not invent validation rules — you only run commands from the validation
|
|
74
|
-
- You do not duplicate feedback that already exists
|
|
75
|
-
- You do not write feedback items without a file sub-heading under `## Feedback`
|
|
45
|
+
- You do not invent validation rules — you only run commands from the validation config
|
|
46
|
+
- You do not duplicate feedback that already exists
|
package/skills/sort/SKILL.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sort
|
|
3
3
|
type: atomic
|
|
4
|
-
description: Deterministic routing for a foundry cycle. Runs
|
|
4
|
+
description: Deterministic routing for a foundry cycle. Runs the foundry_sort tool and returns the next stage.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Sort
|
|
8
8
|
|
|
9
|
-
You are the central dispatcher for a foundry cycle. You
|
|
9
|
+
You are the central dispatcher for a foundry cycle. You call the `foundry_sort` tool to determine what stage to execute next, then invoke that stage's skill.
|
|
10
10
|
|
|
11
11
|
## Prerequisites
|
|
12
12
|
|
|
@@ -16,68 +16,35 @@ Before running this skill, verify that the `foundry/` directory exists in the pr
|
|
|
16
16
|
|
|
17
17
|
## Protocol
|
|
18
18
|
|
|
19
|
-
1.
|
|
19
|
+
1. Call `foundry_sort` (optionally passing `cycleDef` if the cycle definition has a non-standard path). It returns `{route, model?, details?}`.
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
node scripts/sort.js --work WORK.md --history WORK.history.yaml --foundry-dir foundry [--cycle-def <path>]
|
|
23
|
-
```
|
|
21
|
+
2. Call `foundry_history_append` with the current cycle, stage `"sort"`, and a comment explaining the routing decision in natural language. This is your audit trail — if something goes wrong, this comment is what someone will read to understand what happened.
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
-
|
|
33
|
-
cycle: <current-cycle-id>
|
|
34
|
-
stage: sort
|
|
35
|
-
iteration: <current iteration>
|
|
36
|
-
comment: "<your reasoning — why this route was chosen, what feedback state you observed>"
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
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.
|
|
40
|
-
|
|
41
|
-
4. Act on the result:
|
|
42
|
-
- `forge:*` → dispatch the forge skill as a sub-agent, passing the full alias. Use model-specific dispatch (see Model dispatch below).
|
|
43
|
-
- `quench:*` → dispatch the quench skill as a sub-agent, passing the full alias. Use model-specific dispatch.
|
|
44
|
-
- `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.
|
|
45
|
-
- `hitl:*` → invoke the hitl skill, passing the full alias (no model dispatch — human stage)
|
|
46
|
-
- `done` → foundry cycle is complete, return to the cycle skill
|
|
47
|
-
- `blocked` → foundry cycle is blocked (iteration limit hit with unresolved feedback), return to the cycle skill
|
|
48
|
-
- `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
|
|
23
|
+
3. Act on the route:
|
|
24
|
+
- `forge:*` — dispatch the forge skill as a sub-agent. Use model dispatch (see below).
|
|
25
|
+
- `quench:*` — dispatch the quench skill as a sub-agent. Use model dispatch.
|
|
26
|
+
- `appraise:*` — dispatch the appraise skill as a sub-agent. Use model dispatch. Note: the appraise skill handles its own per-appraiser model resolution internally.
|
|
27
|
+
- `hitl:*` — invoke the hitl skill (no model dispatch — human stage)
|
|
28
|
+
- `done` — foundry cycle is complete, return to the cycle skill
|
|
29
|
+
- `blocked` — foundry cycle is blocked (iteration limit hit with unresolved feedback), return to the cycle skill
|
|
30
|
+
- `violation` — file modification or tag validation violation detected (see `details`). The cycle halts — call `foundry_artefacts_set_status` with status `"blocked"`, and return to the cycle skill
|
|
49
31
|
|
|
50
32
|
### Model dispatch
|
|
51
33
|
|
|
52
|
-
|
|
34
|
+
Use the `model` field from the `foundry_sort` result to determine sub-agent routing:
|
|
53
35
|
|
|
54
|
-
- If `
|
|
36
|
+
- If `model` is set (e.g., `openai/gpt-4o`):
|
|
55
37
|
- Convert to agent name: `foundry-openai-gpt-4o`
|
|
56
38
|
- Dispatch with `subagent_type: "foundry-openai-gpt-4o"`
|
|
57
39
|
- 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."
|
|
58
|
-
- If `
|
|
40
|
+
- If `model` is null:
|
|
59
41
|
- Dispatch with `subagent_type: "general"` (inherits session model)
|
|
60
42
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
## Enforcement checks
|
|
64
|
-
|
|
65
|
-
The sort script runs two enforcement checks before routing:
|
|
66
|
-
|
|
67
|
-
1. **File modification enforcement** — verifies the last commit only touched files allowed for that stage
|
|
68
|
-
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`
|
|
69
|
-
|
|
70
|
-
Either check failing produces `violation` on stdout with details on stderr.
|
|
71
|
-
|
|
72
|
-
Tag validation is also available as a standalone script:
|
|
73
|
-
|
|
74
|
-
```
|
|
75
|
-
node scripts/validate-tags.js --work WORK.md --foundry-dir foundry
|
|
76
|
-
```
|
|
43
|
+
4. After the invoked skill completes, call `foundry_sort` again. Repeat until it returns `done`, `blocked`, or `violation`.
|
|
77
44
|
|
|
78
45
|
## What you do NOT do
|
|
79
46
|
|
|
80
|
-
- You do not make routing decisions yourself — the
|
|
81
|
-
- You do not skip
|
|
82
|
-
- You do not override the
|
|
83
|
-
- You do not skip
|
|
47
|
+
- You do not make routing decisions yourself — the tool decides
|
|
48
|
+
- You do not skip calling `foundry_sort`
|
|
49
|
+
- You do not override the tool's output
|
|
50
|
+
- You do not skip the history entry — every sort invocation must be logged via `foundry_history_append`
|