@really-knows-ai/foundry 2.0.1 → 2.2.1

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.
@@ -16,11 +16,14 @@ Regenerate `.opencode/agents/foundry-*.md` files from the currently available mo
16
16
 
17
17
  ### Agent file format
18
18
 
19
- Filename: `.opencode/agents/foundry-<provider>-<model-key>.md`
19
+ Filename: `.opencode/agents/foundry-<slug>.md`
20
20
 
21
- Where `<provider>-<model-key>` is the model ID with `/` replaced by `-`.
21
+ Where `<slug>` is the model ID with **both** `/` and `.` replaced by `-`. This keeps filenames shell-safe and unambiguous.
22
22
 
23
- Example: model `opencode/claude-sonnet-4` produces `.opencode/agents/foundry-opencode-claude-sonnet-4.md`
23
+ Examples:
24
+ - `opencode/claude-sonnet-4` → `.opencode/agents/foundry-opencode-claude-sonnet-4.md`
25
+ - `github-copilot/claude-sonnet-4.6` → `.opencode/agents/foundry-github-copilot-claude-sonnet-4-6.md`
26
+ - `github-copilot/gpt-5.4` → `.opencode/agents/foundry-github-copilot-gpt-5-4.md`
24
27
 
25
28
  Content:
26
29
 
@@ -6,7 +6,7 @@ description: Deterministic routing for a foundry cycle. Runs the foundry_sort to
6
6
 
7
7
  # Sort
8
8
 
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.
9
+ You are the central dispatcher for a foundry cycle. You call `foundry_sort` to determine what stage to execute next, dispatch that stage to a fresh subagent, finalize the stage's disk output, and log history. You are the sole writer of history and git commits.
10
10
 
11
11
  ## Prerequisites
12
12
 
@@ -16,26 +16,96 @@ Before running this skill, verify that the `foundry/` directory exists in the pr
16
16
 
17
17
  ## Protocol
18
18
 
19
- 1. Call `foundry_sort` (optionally passing `cycleDef` if the cycle definition has a non-standard path). It returns `{route, model?, details?}`.
19
+ 1. Call `foundry_sort` (optionally passing `cycleDef`). It returns `{route, model?, token?, details?}`. For dispatchable routes (`forge|quench|appraise|human-appraise:*`) the tool mints a single-use, time-limited `token`.
20
20
 
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.
21
+ 2. Call `foundry_history_append({cycle, stage: 'sort', comment, route})` the `route` field records what sort decided, and **subsequent** `history_append` calls for non-sort stages are enforced to match this route. This is your audit trail.
22
22
 
23
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
- - `human-appraise:*`invoke the human-appraise 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
24
+ - `forge:*` / `quench:*` / `appraise:*` **dispatch** (see §Dispatch).
25
+ - `human-appraise:*` — invoke the human-appraise skill inline (human stage, no subagent) but still pass the `token`; the skill must call `foundry_stage_begin` with it.
26
+ - `done`cycle is complete, return to the cycle skill.
27
+ - `blocked`iteration limit hit with unresolved feedback, return to the cycle skill.
28
+ - `violation` — a validation, file-modification, or missing-subagent violation was detected (see `details`). Halt the cycle: call `foundry_artefacts_set_status(file, 'blocked')` for each affected artefact, and return to the cycle skill. If `details` mentions a missing subagent, tell the user to run `refresh-agents` and restart.
31
29
 
32
- 4. After the subagent completes, call `foundry_history_append` with the current cycle, the **dispatched stage alias** (e.g., `forge:write-haiku`), and a comment summarizing what the subagent reported doing. This is critical — sort is the only reliable writer of stage history. Subagents must NOT write their own history entries.
30
+ 4. **After** the dispatched subagent returns, call `foundry_stage_finalize({cycle})`. Handle three outcomes:
31
+ - `{ok: true, artefacts: [...]}` — the tool has already registered output artefact rows in WORK.md. Proceed to step 5.
32
+ - `{error: 'unexpected_files', files: [...]}` — the subagent wrote outside the artefact type's `file-patterns`. Mark the cycle's target artefact `blocked` via `foundry_artefacts_set_status` and do **not** re-run the stage. Add a `violation` feedback item describing the offending files, then return to the cycle skill.
33
+ - Any other error — surface it to the user and halt.
33
34
 
34
- 5. After logging the stage history, call `foundry_sort` again. Repeat from step 1 until it returns `done`, `blocked`, or `violation`.
35
+ 5. Call `foundry_history_append({cycle, stage: <dispatched-stage-alias>, comment})` summarizing what the subagent reported. The tool enforces that the stage alias matches the most recent sort's `route` — this is why step 2's `route` field matters.
36
+
37
+ 6. Call `foundry_git_commit({cycle, stage, description})` to record the stage's disk changes. **This is mandatory.** The next `foundry_sort` call will return `{route: 'violation', details: 'Uncommitted tool-managed files...'}` if WORK.md, WORK.history.yaml, or anything under `.foundry/` is dirty — the tool enforces one commit per stage.
38
+
39
+ 7. Return to step 1. Repeat until `done`, `blocked`, or `violation`.
40
+
41
+ ## Dispatch
42
+
43
+ Every forge, quench, and appraise stage runs in a **fresh subagent**. Never inline the stage work in the orchestrator conversation — even if the chosen model matches the orchestrator's. The orchestrator's job is to route, dispatch, finalize, and log. Nothing else.
44
+
45
+ ### Choosing the subagent
46
+
47
+ - If `foundry_sort` returned a `model` field, use it verbatim as `subagent_type`. It is already in `foundry-<slug>` form.
48
+ - If no `model` field, dispatch to `general`.
49
+
50
+ ### Token handling
51
+
52
+ The `token` returned by `foundry_sort` is an opaque signed string. Pass it through the dispatch prompt verbatim. **Never** invent, edit, or re-sign tokens. The subagent's first tool call must be `foundry_stage_begin({stage, cycle, token})` using this exact string; `stage_begin` verifies the signature, expiry, and single-use nonce.
53
+
54
+ ### Dispatch call shape
55
+
56
+ Use the `task` tool:
57
+
58
+ ```
59
+ task tool:
60
+ subagent_type: <model-slug-from-foundry_sort, or "general">
61
+ description: "Run <stage-alias> for <cycle-id>"
62
+ prompt: |
63
+ You are a Foundry stage agent. Invoke the <stage-base> skill and follow its instructions exactly.
64
+
65
+ Stage: <stage-alias>
66
+ Cycle: <cycle-id>
67
+ Token: <token-verbatim>
68
+ Working directory: <worktree>
69
+ File patterns (forge only): <file-patterns-list>
70
+
71
+ Your FIRST tool call MUST be foundry_stage_begin({stage, cycle, token}) using the values above.
72
+ Your LAST tool call MUST be foundry_stage_end({summary}).
73
+
74
+ When done, report back a brief summary. Do NOT call foundry_history_append, foundry_git_commit, or foundry_artefacts_add — the orchestrator handles all of those.
75
+ ```
76
+
77
+ Substitute:
78
+ - `<stage-alias>` — the full route string from `foundry_sort` (e.g., `forge:write-haiku`)
79
+ - `<stage-base>` — the base of the alias
80
+ - `<cycle-id>` — current cycle ID from WORK.md frontmatter
81
+ - `<token-verbatim>` — exactly the `token` string from `foundry_sort` — no quoting transforms, no re-encoding
82
+ - `<file-patterns-list>` — for forge stages, read via `foundry_config_artefact_type` and include so the subagent can avoid violations
83
+ - `<worktree>` — current working directory
84
+
85
+ ### Missing subagent (fail-fast)
86
+
87
+ `foundry_sort` verifies that `.opencode/agents/foundry-<slug>.md` exists before returning a `model`. If it doesn't, sort returns `{route: 'violation', details: 'Missing required subagent: ...'}`. Handle as in step 3 above.
88
+
89
+ ## Violation handling
90
+
91
+ If `foundry_stage_finalize` returns `{error: 'unexpected_files', files}`:
92
+
93
+ - The stage wrote outside its permitted `file-patterns`. This is unrecoverable within the current cycle.
94
+ - Mark the target artefact `blocked`: `foundry_artefacts_set_status(file, 'blocked')`.
95
+ - Add a feedback item describing the offense: `foundry_feedback_add(file, text: 'unexpected files: …', tag: 'violation')` (if permitted by your stage), or log in the history comment.
96
+ - Do NOT attempt to re-run the stage — the subagent already consumed the stage slot.
97
+ - Return to the cycle skill so the operator can intervene.
98
+
99
+ If `foundry_sort` returns `{route: 'violation', details: 'Uncommitted tool-managed files...'}`:
100
+
101
+ - A prior stage skipped step 6 (the micro-commit). The work is not lost — it's still in the working tree.
102
+ - Call `foundry_git_commit({cycle, stage: <the-stage-that-just-ran>, description})` to record it.
103
+ - Then call `foundry_sort` again. It should route normally.
104
+ - If you genuinely don't know which stage produced the dirty files, read `WORK.history.yaml` — the most recent non-sort entry is the culprit.
35
105
 
36
106
  ## What you do NOT do
37
107
 
38
- - You do not make routing decisions yourself the tool decides
39
- - You do not skip calling `foundry_sort`
40
- - You do not override the tool's output
41
- - You do not skip the history entry every sort invocation gets a `sort` entry, and every completed stage gets a stage entry (e.g., `forge:write-haiku`). You are the sole writer of history.
108
+ - You do not inline forge/quench/appraise workalways dispatch.
109
+ - You do not mint, modify, or cache tokens — they come from `foundry_sort` and go straight to `foundry_stage_begin`.
110
+ - You do not skip `foundry_stage_finalize` — it is the only mechanism that registers artefacts and detects file-pattern violations.
111
+ - You do not let subagents call `foundry_history_append`, `foundry_git_commit`, or `foundry_artefacts_add` (the last has been removed anyway).
@@ -27,12 +27,17 @@ Read all configuration files:
27
27
  - `foundry/laws/*.md` — global laws
28
28
  - `foundry/appraisers/*.md` — appraiser definitions
29
29
 
30
+ Also scan `.opencode/agents/foundry-*.md` for agent-filename migration (see §2).
31
+
30
32
  For each file, parse the frontmatter and body content.
31
33
 
32
34
  ### 2. Detect what needs migration
33
35
 
34
36
  Check each file against the current expected format:
35
37
 
38
+ **Agent files (v2.1 migration):**
39
+ - Any `.opencode/agents/foundry-*.md` filename containing a `.` character? → needs renaming to all-dashes format. The v2.1 naming convention replaces both `/` and `.` in the model ID with `-`. For example, `foundry-github-copilot-claude-sonnet-4.6.md` must become `foundry-github-copilot-claude-sonnet-4-6.md`. The inner `model:` frontmatter field is **not** changed — only the filename.
40
+
36
41
  **Flows:**
37
42
  - Has `starting-cycles` field? If not → needs DAG migration
38
43
  - Has ordered numbered list under `## Cycles`? → needs conversion to unordered list
@@ -41,7 +46,7 @@ Check each file against the current expected format:
41
46
  - Has `targets` field? If not → needs target routing
42
47
  - Has `inputs.type` (`any-of`/`all-of`)? If `inputs` is a plain list → needs contract type
43
48
  - Has `hitl` in stages or frontmatter? → needs human-appraise migration
44
- - Has `human-appraise` config? Check format is correct
49
+ - Has nested `human-appraise: {enabled, deadlock-threshold}`? v2.2.1 flat-keys migration (see §4b)
45
50
  - Has `models` map? Check format
46
51
 
47
52
  **Artefact types:**
@@ -84,7 +89,48 @@ Present a grouped summary of all issues found:
84
89
 
85
90
  If nothing needs migration, say so and stop.
86
91
 
87
- ### 4. Migrate flows
92
+ ### 4. Migrate agent files (v2.1)
93
+
94
+ For each `.opencode/agents/foundry-*.md` file with a `.` in its filename:
95
+ - Compute the new filename by replacing all `.` with `-` (keep the `.md` extension)
96
+ - `git mv <old> <new>` to preserve history
97
+ - Do **not** modify the file contents — the `model:` field inside retains its original dots
98
+
99
+ After renaming, remind the user: **Restart OpenCode** for the new agent filenames to register.
100
+
101
+ ### 4a. v2.2.0 lifecycle upgrade
102
+
103
+ Foundry v2.2.0 introduces a tool-enforced stage lifecycle (`stage_begin` / `stage_end` / `stage_finalize`) backed by a per-project state directory and HMAC-signed dispatch tokens. The upgrade is non-destructive — no WORK.md or artefact migration is required — but the project needs three small changes:
104
+
105
+ 1. **Create `.foundry/`** (if absent):
106
+ - `mkdir -p .foundry`
107
+ - The plugin auto-creates `.foundry/.secret` on first boot via `readOrCreateSecret`. You do not need to generate it by hand; just ensure the directory exists and is writable.
108
+ 2. **Gitignore `.foundry/`**:
109
+ - Ensure `.gitignore` contains a line `.foundry/` (append if missing; do not duplicate). The directory holds a per-worktree HMAC secret and transient active-stage state — neither should be committed.
110
+ 3. **Pre-existing state:** v2.2.0 is a fresh state system. There is no `active-stage.json` to migrate. If one happens to exist from a manually-aborted prior run, leave it alone — the new plugin treats its absence as "no active stage" and its presence as a legitimate in-flight stage.
111
+
112
+ The `foundry_artefacts_add` tool has been removed in v2.2.0 — artefact registration now happens automatically via `foundry_stage_finalize`. No existing config references this tool, so there is nothing to migrate in `foundry/`.
113
+
114
+ ### 4b. v2.2.1 cycle-definition flat human-appraise keys
115
+
116
+ v2.2.1 replaces the nested `human-appraise: {enabled, deadlock-threshold}` block in cycle definitions with three flat keys:
117
+
118
+ ```yaml
119
+ human-appraise: <true|false> # default: false — run human-appraise every iteration
120
+ deadlock-appraise: <true|false> # default: true — pull in human-appraise when LLM appraisers deadlock
121
+ deadlock-iterations: <number> # default: 5 — deadlock detection threshold
122
+ ```
123
+
124
+ For each `foundry/cycles/*.md` whose frontmatter has the old nested form, migrate:
125
+
126
+ - `human-appraise.enabled: true` → `human-appraise: true`
127
+ - `human-appraise.enabled: false` (or missing) → `human-appraise: false`
128
+ - `human-appraise.deadlock-threshold: N` → `deadlock-iterations: N`
129
+ - Always add `deadlock-appraise: true` unless the user explicitly wants the stricter "no human ever" behavior (`deadlock-appraise: false` → deadlock marks the cycle `blocked`).
130
+
131
+ The old nested form is no longer read. After migration, verify by asking: "cycle `<id>`: human-appraise every iteration? deadlock-appraise on? deadlock-iterations = N?".
132
+
133
+ ### 5. Migrate flows
88
134
 
89
135
  For each flow needing migration:
90
136
  - Show the current ordered cycle list
@@ -93,7 +139,7 @@ For each flow needing migration:
93
139
  - Present the proposed `starting-cycles` and confirm
94
140
  - Convert numbered `## Cycles` list to unordered
95
141
 
96
- ### 5. Migrate cycles
142
+ ### 6. Migrate cycles
97
143
 
98
144
  For each cycle needing migration:
99
145
 
@@ -112,20 +158,20 @@ For each cycle needing migration:
112
158
 
113
159
  Remove `hitl` from stages and add `human-appraise` config if enabled.
114
160
 
115
- ### 6. Migrate other config
161
+ ### 7. Migrate other config
116
162
 
117
163
  For artefact types, appraisers, laws, and validation with issues:
118
164
  - Present each issue with a suggested fix
119
165
  - Ask the user to confirm or adjust
120
166
 
121
- ### 7. Present migration plan
167
+ ### 8. Present migration plan
122
168
 
123
169
  Before writing anything, show the complete list of changes:
124
170
  - Group by category
125
171
  - Show each file and the specific changes
126
172
  - Ask for confirmation
127
173
 
128
- ### 8. Apply changes
174
+ ### 9. Apply changes
129
175
 
130
176
  - Update all affected files
131
177
  - Commit with message: `[foundry] upgrade: migrate to current format`