@really-knows-ai/foundry 2.2.1 → 2.3.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.
@@ -1,87 +0,0 @@
1
- ---
2
- name: cycle
3
- type: composite
4
- description: Runs a foundry cycle by delegating all routing to the sort skill.
5
- composes: [sort, forge, quench, appraise, human-appraise]
6
- ---
7
-
8
- # Cycle
9
-
10
- A foundry cycle reads its definition, sets up the work file for routing, then hands control to the sort skill which drives the forge/quench/appraise/human-appraise loop.
11
-
12
- ## Prerequisites
13
-
14
- Before running this skill, verify that the `foundry/` directory exists in the project root. If it does not exist, stop and tell the user:
15
-
16
- > Foundry is not initialized in this project. Run the `init-foundry` skill first to create the foundry/ directory structure.
17
-
18
- ## Starting a foundry cycle
19
-
20
- 1. Call `foundry_config_cycle` with the cycle ID — get the cycle definition
21
- 2. Call `foundry_config_artefact_type` with the output type ID — get the artefact type definition
22
- 3. Determine the stage route:
23
- - Use the cycle definition's `stages` field if present
24
- - Otherwise generate defaults: always `forge`, add `quench` if `foundry_config_validation` returns non-null for the type, always `appraise`
25
- - If the cycle definition has `human-appraise: true`, append `human-appraise` as the final stage (runs every iteration). If `human-appraise: false` (default), do NOT include it in `stages` — sort will synthesize `human-appraise:<cycle>` on deadlock when needed.
26
- - Stages should use `base:alias` format (e.g. `forge:write-haiku`, `quench:check-syllables`). If you pass bare names, the tool will auto-append the cycle ID as the alias.
27
- 4. Call `foundry_workfile_configure_from_cycle({cycleId, stages})` with the cycle ID and the stages list from step 3. The tool reads the cycle definition and writes `cycle`, `stages`, `max-iterations`, `human-appraise`, `deadlock-appraise`, `deadlock-iterations`, and (if present) `models` into WORK.md in a single call, applying defaults for anything the cycle def omits. Do **not** use `foundry_workfile_set` for this — the configure tool is the authoritative cycle-def → WORK.md translator.
28
- 5. Invoke the sort skill
29
-
30
- ## Sort drives everything
31
-
32
- Once sort is invoked, it calls `foundry_sort` to determine the next stage, dispatches the corresponding skill to a fresh subagent with a single-use token, calls `foundry_stage_finalize` to register outputs (or detect file-pattern violations), writes history, and commits. This repeats until sort returns `done`, `blocked`, or `violation`.
33
-
34
- The cycle skill does not contain routing, finalization, history, or commit logic — sort owns all of that. The cycle skill only sets up the work file and reacts to sort's terminal result.
35
-
36
- ## Completing a foundry cycle
37
-
38
- When sort returns `done`:
39
- - Call `foundry_artefacts_set_status(file, 'done')` for the cycle's output artefact.
40
- - Return control to the flow skill.
41
-
42
- When sort returns `blocked`:
43
- - The target artefact is usually already marked `blocked` by sort (on violations) or by human-appraise (on explicit abort). If not, call `foundry_artefacts_set_status(file, 'blocked')`.
44
- - Return control to the flow skill — the flow decides how to handle it.
45
-
46
- When sort returns `violation` (e.g., `stage_finalize` `unexpected_files`, missing subagent, or file-pattern violation):
47
- - Sort has already marked affected artefacts blocked and returned. Treat as the blocked path.
48
- - Return control to the flow skill.
49
-
50
- ## Human Appraise
51
-
52
- Human-appraise is controlled by two flat cycle-def keys:
53
-
54
- - `human-appraise: true` — human-appraise runs every iteration as part of the normal stage flow (appended to `stages`).
55
- - `deadlock-appraise: true` (default) — if LLM appraisers deadlock on the same feedback for `deadlock-iterations` rounds (default 5), sort routes to human-appraise to resolve it, even when it isn't in `stages`.
56
- - `deadlock-appraise: false` — no human intervention; deadlock → `blocked`.
57
-
58
- ## Micro commits
59
-
60
- Every stage ends with a micro commit, written by sort (not cycle, not subagents). The message format is `[<cycle-id>] <base>:<alias>: <brief description>`.
61
-
62
- Examples:
63
- - `[haiku-creation] forge:write-haiku: initial draft`
64
- - `[haiku-creation] quench:check-syllables: checked syllable pattern`
65
- - `[haiku-creation] forge:write-haiku: addressed validation feedback`
66
-
67
- ## Feedback states
68
-
69
- ```
70
- open - needs generator action
71
- actioned - needs approval
72
- wont-fix - needs approval (appraisal only)
73
- approved - resolved
74
- rejected - re-opened
75
- ```
76
-
77
- Tag types: `validation` (from quench), `law:<law-id>` (from appraise), `human` (from human-appraise) — indicates the source and category of feedback.
78
-
79
- ## What you do NOT do
80
-
81
- - You do not make routing decisions — sort does that.
82
- - You do not register artefacts — `foundry_stage_finalize` does that (invoked by sort).
83
- - You do not write history or commits — sort does that.
84
- - You do not change the laws mid-cycle.
85
- - You do not decide the artefact is "close enough" — it passes or it doesn't.
86
- - You do not proceed past a file modification violation — honor sort's `violation`/`blocked` return.
87
- - You do not modify input artefacts — they are read-only.
@@ -1,111 +0,0 @@
1
- ---
2
- name: sort
3
- type: atomic
4
- description: Deterministic routing for a foundry cycle. Runs the foundry_sort tool and returns the next stage.
5
- ---
6
-
7
- # Sort
8
-
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
-
11
- ## Prerequisites
12
-
13
- Before running this skill, verify that the `foundry/` directory exists in the project root. If it does not exist, stop and tell the user:
14
-
15
- > Foundry is not initialized in this project. Run the `init-foundry` skill first to create the foundry/ directory structure.
16
-
17
- ## Protocol
18
-
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
-
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
-
23
- 3. Act on the route:
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.
29
-
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.
34
-
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.
105
-
106
- ## What you do NOT do
107
-
108
- - You do not inline forge/quench/appraise work — always 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).