@really-knows-ai/foundry 2.3.1 → 3.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.
Files changed (170) hide show
  1. package/README.md +200 -198
  2. package/dist/.opencode/plugins/foundry-tools/appraiser-tools.js +28 -0
  3. package/dist/.opencode/plugins/foundry-tools/artefact-tools.js +58 -0
  4. package/dist/.opencode/plugins/foundry-tools/assay-tools.js +92 -0
  5. package/dist/.opencode/plugins/foundry-tools/attestation-tools.js +191 -0
  6. package/dist/.opencode/plugins/foundry-tools/config-create-tools.js +128 -0
  7. package/dist/.opencode/plugins/foundry-tools/config-law-tools.js +380 -0
  8. package/dist/.opencode/plugins/foundry-tools/config-tools.js +43 -0
  9. package/dist/.opencode/plugins/foundry-tools/feedback-tools.js +234 -0
  10. package/dist/.opencode/plugins/foundry-tools/git-helpers.js +354 -0
  11. package/dist/.opencode/plugins/foundry-tools/git-tools.js +181 -0
  12. package/dist/.opencode/plugins/foundry-tools/helpers.js +340 -0
  13. package/dist/.opencode/plugins/foundry-tools/history-tools.js +20 -0
  14. package/dist/.opencode/plugins/foundry-tools/memory-admin-tools.js +296 -0
  15. package/dist/.opencode/plugins/foundry-tools/memory-helpers.js +104 -0
  16. package/dist/.opencode/plugins/foundry-tools/memory-tools.js +286 -0
  17. package/dist/.opencode/plugins/foundry-tools/orchestrate-tool.js +159 -0
  18. package/dist/.opencode/plugins/foundry-tools/snapshot-tools.js +104 -0
  19. package/dist/.opencode/plugins/foundry-tools/stage-tools.js +186 -0
  20. package/dist/.opencode/plugins/foundry-tools/validate-tools.js +263 -0
  21. package/dist/.opencode/plugins/foundry-tools/workfile-tools.js +102 -0
  22. package/dist/.opencode/plugins/foundry.js +105 -0
  23. package/dist/CHANGELOG.md +490 -0
  24. package/dist/LICENSE +21 -0
  25. package/dist/README.md +278 -0
  26. package/dist/docs/README.md +59 -0
  27. package/dist/docs/architecture.md +434 -0
  28. package/dist/docs/concepts.md +396 -0
  29. package/dist/docs/getting-started.md +345 -0
  30. package/dist/docs/memory-maintenance.md +176 -0
  31. package/dist/docs/tools.md +1411 -0
  32. package/dist/docs/work-spec.md +283 -0
  33. package/dist/scripts/lib/artefacts.js +151 -0
  34. package/dist/scripts/lib/assay/loader.js +151 -0
  35. package/dist/scripts/lib/assay/parse-jsonl.js +102 -0
  36. package/dist/scripts/lib/assay/permissions.js +52 -0
  37. package/dist/scripts/lib/assay/run.js +219 -0
  38. package/dist/scripts/lib/assay/spawn-with-timeout.js +138 -0
  39. package/dist/scripts/lib/attestation/attest.js +111 -0
  40. package/dist/scripts/lib/attestation/canonical-json.js +109 -0
  41. package/dist/scripts/lib/attestation/hash.js +17 -0
  42. package/dist/scripts/lib/attestation/parse.js +14 -0
  43. package/dist/scripts/lib/attestation/payload.js +106 -0
  44. package/dist/scripts/lib/attestation/render.js +16 -0
  45. package/dist/scripts/lib/attestation/verify.js +15 -0
  46. package/dist/scripts/lib/branch-guard.js +72 -0
  47. package/dist/scripts/lib/config-creators/appraiser.js +9 -0
  48. package/dist/scripts/lib/config-creators/artefact-type.js +9 -0
  49. package/dist/scripts/lib/config-creators/cycle.js +11 -0
  50. package/dist/scripts/lib/config-creators/factory.js +49 -0
  51. package/dist/scripts/lib/config-creators/flow.js +11 -0
  52. package/dist/scripts/lib/config-validators/appraiser.js +49 -0
  53. package/dist/scripts/lib/config-validators/artefact-type.js +38 -0
  54. package/dist/scripts/lib/config-validators/cycle.js +131 -0
  55. package/dist/scripts/lib/config-validators/flow.js +57 -0
  56. package/dist/scripts/lib/config-validators/helpers.js +96 -0
  57. package/dist/scripts/lib/config-validators/law.js +96 -0
  58. package/dist/scripts/lib/config.js +393 -0
  59. package/dist/scripts/lib/failed-flow.js +131 -0
  60. package/dist/scripts/lib/feedback-store.js +249 -0
  61. package/dist/scripts/lib/feedback-transitions.js +105 -0
  62. package/dist/scripts/lib/finalize.js +70 -0
  63. package/dist/scripts/lib/foundational-guards.js +13 -0
  64. package/dist/scripts/lib/git-bridge.js +77 -0
  65. package/dist/scripts/lib/git-finish/work-finish.js +233 -0
  66. package/dist/scripts/lib/git-policy.js +101 -0
  67. package/dist/scripts/lib/guards.js +125 -0
  68. package/dist/scripts/lib/history.js +132 -0
  69. package/dist/scripts/lib/memory/admin/create-edge-type.js +91 -0
  70. package/dist/scripts/lib/memory/admin/create-entity-type.js +43 -0
  71. package/dist/scripts/lib/memory/admin/create-extractor.js +67 -0
  72. package/dist/scripts/lib/memory/admin/drop-edge-type.js +40 -0
  73. package/dist/scripts/lib/memory/admin/drop-entity-type.js +172 -0
  74. package/dist/scripts/lib/memory/admin/dump.js +47 -0
  75. package/dist/scripts/lib/memory/admin/helpers.js +31 -0
  76. package/dist/scripts/lib/memory/admin/init.js +170 -0
  77. package/dist/scripts/lib/memory/admin/live-store.js +76 -0
  78. package/dist/scripts/lib/memory/admin/reembed.js +285 -0
  79. package/dist/scripts/lib/memory/admin/rename-edge-type.js +54 -0
  80. package/dist/scripts/lib/memory/admin/rename-entity-type.js +151 -0
  81. package/dist/scripts/lib/memory/admin/reset.js +24 -0
  82. package/dist/scripts/lib/memory/admin/vacuum.js +9 -0
  83. package/dist/scripts/lib/memory/admin/validate.js +19 -0
  84. package/dist/scripts/lib/memory/config.js +149 -0
  85. package/dist/scripts/lib/memory/cozo.js +136 -0
  86. package/dist/scripts/lib/memory/drift.js +71 -0
  87. package/dist/scripts/lib/memory/embeddings.js +128 -0
  88. package/dist/scripts/lib/memory/frontmatter.js +75 -0
  89. package/dist/scripts/lib/memory/ndjson.js +84 -0
  90. package/dist/scripts/lib/memory/paths.js +25 -0
  91. package/dist/scripts/lib/memory/permissions.js +41 -0
  92. package/dist/scripts/lib/memory/prompt.js +109 -0
  93. package/dist/scripts/lib/memory/query.js +56 -0
  94. package/dist/scripts/lib/memory/reads.js +109 -0
  95. package/dist/scripts/lib/memory/schema.js +64 -0
  96. package/dist/scripts/lib/memory/search.js +73 -0
  97. package/dist/scripts/lib/memory/singleton.js +49 -0
  98. package/dist/scripts/lib/memory/store.js +162 -0
  99. package/dist/scripts/lib/memory/types.js +93 -0
  100. package/dist/scripts/lib/memory/validate.js +58 -0
  101. package/dist/scripts/lib/memory/writes.js +40 -0
  102. package/{scripts → dist/scripts}/lib/pending.js +7 -2
  103. package/dist/scripts/lib/secret.js +59 -0
  104. package/{scripts → dist/scripts}/lib/slug.js +3 -2
  105. package/dist/scripts/lib/snapshot/finish.js +103 -0
  106. package/dist/scripts/lib/snapshot/inspect.js +253 -0
  107. package/dist/scripts/lib/snapshot/render.js +55 -0
  108. package/dist/scripts/lib/sort-fs-check.js +121 -0
  109. package/dist/scripts/lib/sort-routing.js +101 -0
  110. package/{scripts → dist/scripts}/lib/stage-guard.js +12 -6
  111. package/{scripts → dist/scripts}/lib/state.js +4 -0
  112. package/dist/scripts/lib/token.js +57 -0
  113. package/dist/scripts/lib/tracing.js +59 -0
  114. package/dist/scripts/lib/ulid.js +100 -0
  115. package/dist/scripts/lib/validator-jsonl.js +162 -0
  116. package/{scripts → dist/scripts}/lib/workfile.js +38 -20
  117. package/dist/scripts/orchestrate-cycle.js +215 -0
  118. package/dist/scripts/orchestrate-phases.js +314 -0
  119. package/dist/scripts/orchestrate.js +163 -0
  120. package/dist/scripts/sort.js +278 -0
  121. package/{skills → dist/skills}/add-appraiser/SKILL.md +42 -6
  122. package/{skills → dist/skills}/add-artefact-type/SKILL.md +49 -21
  123. package/{skills → dist/skills}/add-cycle/SKILL.md +60 -14
  124. package/dist/skills/add-extractor/SKILL.md +133 -0
  125. package/{skills → dist/skills}/add-flow/SKILL.md +39 -7
  126. package/dist/skills/add-law/SKILL.md +191 -0
  127. package/dist/skills/add-memory-edge-type/SKILL.md +52 -0
  128. package/dist/skills/add-memory-entity-type/SKILL.md +74 -0
  129. package/{skills → dist/skills}/appraise/SKILL.md +62 -13
  130. package/dist/skills/assay/SKILL.md +72 -0
  131. package/dist/skills/change-embedding-model/SKILL.md +58 -0
  132. package/dist/skills/drop-memory-edge-type/SKILL.md +54 -0
  133. package/dist/skills/drop-memory-entity-type/SKILL.md +57 -0
  134. package/dist/skills/dry-run/SKILL.md +116 -0
  135. package/{skills → dist/skills}/flow/SKILL.md +15 -2
  136. package/dist/skills/forge/SKILL.md +121 -0
  137. package/dist/skills/human-appraise/SKILL.md +153 -0
  138. package/{skills → dist/skills}/init-foundry/SKILL.md +23 -4
  139. package/dist/skills/init-memory/SKILL.md +92 -0
  140. package/{skills → dist/skills}/orchestrate/SKILL.md +30 -4
  141. package/dist/skills/quench/SKILL.md +99 -0
  142. package/{skills → dist/skills}/refresh-agents/SKILL.md +1 -1
  143. package/dist/skills/rename-memory-edge-type/SKILL.md +50 -0
  144. package/dist/skills/rename-memory-entity-type/SKILL.md +51 -0
  145. package/dist/skills/reset-memory/SKILL.md +54 -0
  146. package/dist/skills/upgrade-foundry/SKILL.md +192 -0
  147. package/package.json +34 -17
  148. package/.opencode/plugins/foundry.js +0 -761
  149. package/CHANGELOG.md +0 -90
  150. package/docs/concepts.md +0 -59
  151. package/docs/getting-started.md +0 -78
  152. package/docs/work-spec.md +0 -193
  153. package/scripts/lib/artefacts.js +0 -124
  154. package/scripts/lib/config.js +0 -175
  155. package/scripts/lib/feedback-transitions.js +0 -25
  156. package/scripts/lib/feedback.js +0 -440
  157. package/scripts/lib/finalize.js +0 -41
  158. package/scripts/lib/history.js +0 -59
  159. package/scripts/lib/secret.js +0 -23
  160. package/scripts/lib/tags.js +0 -108
  161. package/scripts/lib/token.js +0 -26
  162. package/scripts/orchestrate.js +0 -418
  163. package/scripts/sort.js +0 -370
  164. package/scripts/validate-tags.js +0 -54
  165. package/skills/add-law/SKILL.md +0 -105
  166. package/skills/forge/SKILL.md +0 -88
  167. package/skills/human-appraise/SKILL.md +0 -82
  168. package/skills/quench/SKILL.md +0 -62
  169. package/skills/upgrade-foundry/SKILL.md +0 -216
  170. /package/{skills → dist/skills}/list-agents/SKILL.md +0 -0
package/CHANGELOG.md DELETED
@@ -1,90 +0,0 @@
1
- # Changelog
2
-
3
- ## 2.3.1 — 2026-04-20
4
-
5
- ### Changed
6
-
7
- - `flow` skill: any cycle in a flow may now be the starting cycle (previously limited to `starting-cycles`). The list becomes a hint for ambiguous requests. A cycle whose `inputs` contract cannot be satisfied from files on disk is not eligible to start.
8
- - `flow` skill: between-cycles logic no longer implies any carry-over ceremony. The next cycle's forge discovers the previous cycle's output via filesystem scan against its input types' `file-patterns`.
9
- - `forge` skill: input discovery now explicitly uses filesystem scan against each input type's `file-patterns`, with the goal guiding which candidates are relevant.
10
- - `forge` skill: the write invariant is restated accurately — forge may only write to files matching the output artefact type's `file-patterns` (plus the tool-managed files). All other files on disk are read-only. The previous "inputs are read-only" framing was a special case of this rule.
11
-
12
- ### Notes
13
-
14
- - No tool, schema, or enforcement changes. Existing flows continue to work. `sort.js`'s `checkModifiedFiles` already enforces the write invariant.
15
-
16
- ## 2.3.0 — 2026-04-20
17
-
18
- ### Breaking
19
-
20
- - **LLM orchestration replaced with deterministic `foundry_orchestrate` tool.** The `cycle` and `sort` skills are removed; replaced by a single thin `orchestrate` skill that drives a 3-line loop.
21
- - **Six tools deregistered** from the plugin (still exist as internal imports for tests): `foundry_sort`, `foundry_history_append`, `foundry_stage_finalize`, `foundry_git_commit`, `foundry_workfile_configure_from_cycle`, `foundry_workfile_set`.
22
- - Upgrade requires clean main + no in-flight workfile (see `upgrade-foundry` skill).
23
-
24
- ### Added
25
-
26
- - `foundry_orchestrate` — single tool that owns the sort → history → dispatch → finalize → history → commit loop. Atomic stage completion.
27
- - `scripts/orchestrate.js` — deterministic orchestration logic, composes existing internal functions.
28
- - Orphaned-stage detection: if orchestrate is called without `lastResult` but an active stage exists, returns `violation`. Fixes the ses_256c failure mode where an LLM skipped the post-dispatch history append and wedged the cycle.
29
-
30
- ### Fixed
31
-
32
- - Root cause of all deferred HARDEN.md bugs (B, C, D, E, G) and the ses_256c bug: LLM misfollowing a deterministic protocol. Protocol now lives inside the plugin tool.
33
-
34
- ### Migration
35
-
36
- See `skills/upgrade-foundry/SKILL.md` for v2.3.0 pre-flight checks. No automated state migration — complete or discard in-flight cycles on v2.2.x before upgrading.
37
-
38
- ## 2.2.1 — 2026-04-20
39
-
40
- Follow-up patch addressing the five bugs deferred from v2.2.0 (see `HARDEN.md` §Deferred).
41
-
42
- ### Breaking changes
43
-
44
- - **Cycle-definition deadlock config flattened.** The nested `human-appraise: {enabled, deadlock-threshold}` block is replaced by three flat keys:
45
- - `human-appraise: <bool>` (default `false`) — include `human-appraise` in the stage loop every iteration
46
- - `deadlock-appraise: <bool>` (default `true`) — route to `human-appraise` when LLM appraisers deadlock
47
- - `deadlock-iterations: <number>` (default `5`) — deadlock threshold
48
- Run the `upgrade-foundry` skill to migrate existing cycle defs — the old nested form is no longer read.
49
-
50
- ### New
51
-
52
- - **`foundry_workfile_configure_from_cycle({cycleId, stages})`** — populates WORK.md frontmatter from a cycle definition in one call. Replaces the prior 6–7 sequential `foundry_workfile_set` calls at cycle start. Defaults for `max-iterations`, `human-appraise`, `deadlock-appraise`, `deadlock-iterations`, and `models` now live in plugin code rather than skill prose.
53
- - **`foundry_artefacts_list({cycle})`** — optional cycle filter. Callers should always pass the current cycle to avoid picking up stale rows from prior aborted sessions.
54
-
55
- ### Fixed
56
-
57
- - **Bug B — deadlock routing.** Sort now reads the flat deadlock keys from WORK.md frontmatter and routes to `human-appraise` on deadlock (either an existing `human-appraise:<cycle>` stage in `stages`, or a synthesized one). When `deadlock-appraise: false`, deadlock marks the cycle `blocked`.
58
- - **Bug C — stale artefact validation.** `quench`, `appraise`, and `human-appraise` skills now pass the current cycle to `foundry_artefacts_list`, scoping validation to artefacts produced by the current cycle instead of every row that has ever landed in WORK.md.
59
- - **Bug D — overwriting WORK.md.** The `flow` skill now calls `foundry_workfile_get` before `foundry_workfile_create` and prompts the user to resume, discard, or abort when an existing workfile is detected. Silent overwrite is not offered; resume requires matching `flow` and `cycle`.
60
- - **Bug E — missing micro-commits.** `foundry_sort` now returns `{route: 'violation'}` when `WORK.md`, `WORK.history.yaml`, or anything under `.foundry/` has uncommitted changes at the start of a sort call and history is non-empty. Structurally enforces the one-commit-per-stage contract that previously lived only in skill prose. First sort of a cycle is exempt (empty history).
61
- - **Bug G — workfile setup boilerplate.** See `foundry_workfile_configure_from_cycle` above.
62
-
63
- ### Migration
64
-
65
- Run the `upgrade-foundry` skill to migrate cycle definitions to the flat deadlock keys (Bug B). No other migration required — WORK.md, `.foundry/`, and feedback state are forward-compatible.
66
-
67
- ## 2.2.0 — 2026-04-19
68
-
69
- ### Breaking changes
70
-
71
- - **`foundry_artefacts_add` removed.** Artefact registration now happens exclusively via `foundry_stage_finalize` after a forge stage closes.
72
- - **`foundry_artefacts_set_status` no longer accepts `draft`.** Only `done` and `blocked` are valid. New artefacts are registered as `draft` automatically by `stage_finalize`.
73
- - **Feedback / artefact / workfile mutation tools now enforce stage-lock preconditions.** Tools callable by subagents require an active stage matching their role; tools callable by the orchestrator require no active stage. Out-of-band calls return a structured error instead of mutating state.
74
- - **Feedback state machine strictly enforced.** `approved` is terminal. `quench` cannot approve/reject `wont-fix` items. See `HARDEN.md` §4 for the full matrix.
75
- - **`foundry_sort` dispatchable routes now return a `token` field.** Subagents must redeem the token via `foundry_stage_begin`; forged or replayed tokens are rejected.
76
-
77
- ### New
78
-
79
- - **`foundry_stage_begin(stage, cycle, token)`** — subagents open a work stage by consuming a single-use HMAC-signed token.
80
- - **`foundry_stage_end(summary)`** — subagents close a stage; preserves `baseSha` for finalize.
81
- - **`foundry_stage_finalize(cycle)`** — orchestrator verifies stage output against allowed file patterns, registers matching files as draft artefacts, rejects stray writes with `{error: "unexpected_files", files: [...]}`.
82
- - **`.foundry/` state directory** (gitignored) — holds `.secret` (per-worktree HMAC key, mode 0600), `active-stage.json` (present only during an active stage), `last-stage.json` (for finalize lookup).
83
-
84
- ### Fixed
85
-
86
- - Normalized `maxIterations` → `max-iterations` across workfile read/write paths (previously inconsistent between flow and cycle skills, causing latent deadlock-detection issues).
87
-
88
- ### Migration
89
-
90
- Upgrade with the `upgrade-foundry` skill. `.foundry/` is created automatically on first plugin boot; `.secret` is generated idempotently. No data migration required — existing `WORK.md` and `foundry/*` configs are compatible.
package/docs/concepts.md DELETED
@@ -1,59 +0,0 @@
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 (via the `foundry_git_commit` tool). This enables file modification enforcement — the sort tool checks the git diff to ensure each stage only touched files it was allowed to.
56
-
57
- ## Custom tools
58
-
59
- All deterministic pipeline operations are exposed as custom tools via the Foundry plugin. Skills call tools instead of manipulating files directly. The tools are backed by shared library modules in `scripts/lib/` with injectable I/O for testability. This separation ensures that file format parsing, state transitions, and routing logic are handled by tested code rather than LLM interpretation.
@@ -1,78 +0,0 @@
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
package/docs/work-spec.md DELETED
@@ -1,193 +0,0 @@
1
- # WORK.md Spec
2
-
3
- WORK.md is created at the start of a foundry flow on a work branch. It is the shared state between all stages in all foundry cycles. It is transient — it exists only for the duration of the foundry flow.
4
-
5
- ## Frontmatter
6
-
7
- ```yaml
8
- ---
9
- flow: <flow-id>
10
- cycle: <current-cycle-id>
11
- stages: [forge:write-haiku, quench:check-syllables, appraise:evaluate-quality]
12
- max-iterations: 3
13
- ---
14
- ```
15
-
16
- Fields:
17
- - `flow` — the foundry flow being executed
18
- - `cycle` — the current foundry cycle id
19
- - `stages` — the ordered route for this foundry cycle, set when the foundry cycle starts. Each entry uses `base:alias` format where `base` is the stage type (`forge`, `quench`, `appraise`, or `hitl`) and `alias` is a human-readable name for what that stage does in this cycle. Determined from the artefact type: if `validation.md` exists, include `quench`; always include `forge` and `appraise`. A `hitl` stage can be included for human-in-the-loop checkpoints.
20
- - `max-iterations` — how many forge passes before the foundry cycle is blocked (default: 3)
21
-
22
- The `stages` list is the happy path. Sort follows it but loops back to `forge` when unresolved feedback demands it.
23
-
24
- ### Who sets what
25
-
26
- - `flow` — set by the foundry flow skill at foundry flow start, never changes
27
- - `cycle` — set by the foundry flow skill when starting each foundry cycle
28
- - `stages` — set by the orchestrate skill when starting each foundry cycle (reads artefact type to determine if quench is needed)
29
- - `max-iterations` — set by the orchestrate skill (default 3, could be overridden in foundry cycle definition)
30
-
31
- ## Sections
32
-
33
- ### Goal
34
-
35
- Free text describing what the foundry flow is producing and any context the human provided. Written once at foundry flow start, not modified after.
36
-
37
- ### Artefacts
38
-
39
- A table tracking every artefact produced by the foundry flow.
40
-
41
- ```markdown
42
- # Artefacts
43
-
44
- | File | Type | Cycle | Status |
45
- |------|------|-------|--------|
46
- | petitions/login-change.md | petition | write-petition | draft |
47
- | features/login-change.feature | gherkin | petition-to-gherkin | draft |
48
- ```
49
-
50
- Statuses:
51
- - `draft` — artefact exists but has not cleared all stages
52
- - `done` — artefact has cleared all stages
53
- - `blocked` — artefact hit iteration limit or a violation
54
-
55
- ### Feedback
56
-
57
- Grouped by artefact file path. Each item is a checklist entry with a tag indicating its source.
58
-
59
- ```markdown
60
- # Feedback
61
-
62
- ## petitions/login-change.md
63
-
64
- - [ ] Missing "Acceptance Criteria" section #validation
65
- - [x] Justification is circular #law:justified-change | approved
66
- - [~] Could be more concise #law:clear-language | wont-fix: brevity would lose necessary context | approved
67
- ```
68
-
69
- #### Tags
70
-
71
- - `#validation` — from a deterministic quench command
72
- - `#law:<law-id>` — from subjective appraise, tied to a specific law
73
- - `#hitl` — from human-provided feedback at a hitl checkpoint
74
-
75
- #### Lifecycle states
76
-
77
- ```
78
- - [ ] issue #tag open, needs forge action
79
- - [x] issue #tag actioned, needs approval
80
- - [~] issue #tag | wont-fix: <reason> declined by forge, needs approval (appraise only)
81
- - [x] issue #tag | approved resolved
82
- - [~] issue #tag | wont-fix: <reason> | approved resolved
83
- - [x] issue #tag | rejected: <reason> re-opened
84
- - [~] issue #tag | wont-fix: <reason> | rejected re-opened
85
- ```
86
-
87
- #### Rules
88
-
89
- - Validation feedback (`#validation`) cannot be wont-fixed
90
- - Feedback is never deleted — it stays as a record of the iteration history
91
- - New feedback is appended, not inserted
92
- - Items are grouped under the artefact they relate to
93
-
94
- ## Who writes what
95
-
96
- | Section | Written by | Updated by |
97
- |---------|-----------|------------|
98
- | Frontmatter (`flow`) | `foundry_workfile_create` (flow skill) | nobody |
99
- | Frontmatter (`cycle`, `stages`, `max-iterations`) | `foundry_workfile_set` (orchestrate skill) | `foundry_workfile_set` (reset on each new cycle) |
100
- | Goal | `foundry_workfile_create` (flow skill) | nobody |
101
- | Artefacts | `foundry_artefacts_add` (forge skill) | `foundry_artefacts_set_status` (orchestrate skill) |
102
- | Feedback | `foundry_feedback_add` (quench/appraise/hitl) | `foundry_feedback_action`/`foundry_feedback_wontfix` (forge), `foundry_feedback_resolve` (quench/appraise/hitl) |
103
-
104
- ## WORK.history.yaml
105
-
106
- A separate file (`WORK.history.yaml`) alongside WORK.md. Append-only log of every stage execution.
107
-
108
- ```yaml
109
- - timestamp: "2026-04-17T14:32:01Z"
110
- cycle: write-petition
111
- stage: forge:draft-petition
112
- iteration: 1
113
- comment: Initial petition draft created
114
-
115
- - timestamp: "2026-04-17T14:32:45Z"
116
- cycle: write-petition
117
- stage: quench:validate-petition
118
- iteration: 1
119
- comment: 2 validation issues found
120
-
121
- - timestamp: "2026-04-17T14:33:12Z"
122
- cycle: write-petition
123
- stage: forge:draft-petition
124
- iteration: 2
125
- comment: Addressed 2 validation issues
126
-
127
- - timestamp: "2026-04-17T14:33:30Z"
128
- cycle: write-petition
129
- stage: quench:validate-petition
130
- iteration: 2
131
- comment: Validation passed
132
-
133
- - timestamp: "2026-04-17T14:34:00Z"
134
- cycle: write-petition
135
- stage: appraise:review-petition
136
- iteration: 2
137
- comment: No issues found, cycle complete
138
- ```
139
-
140
- ### Fields
141
-
142
- - `timestamp` — ISO 8601 UTC
143
- - `cycle` — which foundry cycle this entry belongs to
144
- - `stage` — which stage just completed, in `base:alias` format (e.g. `forge:draft-petition`, `quench:validate-petition`, `appraise:review-petition`, `hitl:human-review`)
145
- - `iteration` — the current iteration number (increments each time forge runs within a cycle)
146
- - `comment` — brief description of what happened
147
-
148
- ### Rules
149
-
150
- - Append-only — never edit or delete entries
151
- - Every stage skill appends an entry when it completes
152
- - The sort tool reads this to determine what has happened in the current foundry cycle
153
- - Iteration is derived from counting forge entries for the current foundry cycle
154
-
155
- ### Who writes
156
-
157
- Every stage skill (forge, quench, appraise, hitl) appends an entry when it finishes via the `foundry_history_append` tool.
158
-
159
- ## Example
160
-
161
- A complete WORK.md mid-foundry flow:
162
-
163
- ```markdown
164
- ---
165
- flow: make-haiku
166
- cycle: haiku-creation
167
- stages: [forge:write-haiku, quench:check-syllables, appraise:evaluate-quality]
168
- max-iterations: 3
169
- ---
170
-
171
- # Goal
172
-
173
- Write a haiku about autumn rain. Should evoke loneliness
174
- and the sound of rain on leaves.
175
-
176
- # Artefacts
177
-
178
- | File | Type | Cycle | Status |
179
- |------|------|-------|--------|
180
- | petitions/autumn-rain-haiku.md | petition | haiku-ideation | done |
181
- | haiku/autumn-rain.md | haiku | haiku-creation | draft |
182
-
183
- # Feedback
184
-
185
- ## petitions/autumn-rain-haiku.md
186
-
187
- - [x] Acceptance criteria should mention seasonal reference #law:clear-acceptance-criteria | approved
188
-
189
- ## haiku/autumn-rain.md
190
-
191
- - [ ] Line 2 has 8 syllables, expected 7 #validation
192
- - [x] No seasonal reference detected #law:seasonal-reference | approved
193
- ```
@@ -1,124 +0,0 @@
1
- /**
2
- * Artefacts table utilities for WORK.md.
3
- *
4
- * Parses, adds rows to, and updates status in the markdown artefacts table.
5
- */
6
-
7
- /**
8
- * Parse the artefacts markdown table from text.
9
- * @param {string} text
10
- * @returns {Array<{file: string, type: string, cycle: string, status: string}>}
11
- */
12
- export function parseArtefactsTable(text) {
13
- const artefacts = [];
14
- let inTable = false;
15
-
16
- for (const line of text.split('\n')) {
17
- const stripped = line.trim();
18
-
19
- if (stripped.startsWith('| File')) {
20
- inTable = true;
21
- continue;
22
- }
23
- if (inTable && stripped.startsWith('|---')) {
24
- continue;
25
- }
26
- if (inTable && stripped.startsWith('|')) {
27
- const cols = stripped.split('|').slice(1, -1).map(c => c.trim());
28
- if (cols.length >= 4) {
29
- artefacts.push({
30
- file: cols[0],
31
- type: cols[1],
32
- cycle: cols[2],
33
- status: cols[3],
34
- });
35
- }
36
- } else if (inTable) {
37
- inTable = false;
38
- }
39
- }
40
-
41
- return artefacts;
42
- }
43
-
44
- /**
45
- * Add a row to the artefacts table.
46
- * @param {string} text - Full WORK.md text
47
- * @param {{file: string, type: string, cycle: string, status: string}} row
48
- * @returns {string} Updated text
49
- */
50
- export function addArtefactRow(text, { file, type, cycle, status }) {
51
- const lines = text.split('\n');
52
- let lastTableRow = -1;
53
- let inTable = false;
54
-
55
- for (let i = 0; i < lines.length; i++) {
56
- const stripped = lines[i].trim();
57
- if (stripped.startsWith('| File')) {
58
- inTable = true;
59
- continue;
60
- }
61
- if (inTable && stripped.startsWith('|---')) {
62
- if (lastTableRow < 0) lastTableRow = i; // insert after separator if no data rows
63
- continue;
64
- }
65
- if (inTable && stripped.startsWith('|')) {
66
- lastTableRow = i;
67
- } else if (inTable) {
68
- break;
69
- }
70
- }
71
-
72
- if (lastTableRow === -1) {
73
- throw new Error('Artefacts table not found');
74
- }
75
-
76
- const newRow = `| ${file} | ${type} | ${cycle} | ${status} |`;
77
- lines.splice(lastTableRow + 1, 0, newRow);
78
- return lines.join('\n');
79
- }
80
-
81
- /**
82
- * Update the status column for a specific file in the artefacts table.
83
- * @param {string} text - Full WORK.md text
84
- * @param {string} file - File name to match
85
- * @param {string} newStatus - New status value
86
- * @returns {string} Updated text
87
- */
88
- export function setArtefactStatus(text, file, newStatus) {
89
- if (newStatus === 'draft') {
90
- throw new Error('status draft not permitted; use stage_finalize for registration');
91
- }
92
- if (!['done', 'blocked'].includes(newStatus)) {
93
- throw new Error(`invalid status: ${newStatus}`);
94
- }
95
- const lines = text.split('\n');
96
- let inTable = false;
97
- let found = false;
98
-
99
- for (let i = 0; i < lines.length; i++) {
100
- const stripped = lines[i].trim();
101
- if (stripped.startsWith('| File')) {
102
- inTable = true;
103
- continue;
104
- }
105
- if (inTable && stripped.startsWith('|---')) continue;
106
- if (inTable && stripped.startsWith('|')) {
107
- const cols = stripped.split('|').slice(1, -1).map(c => c.trim());
108
- if (cols.length >= 4 && cols[0] === file) {
109
- cols[3] = newStatus;
110
- lines[i] = '| ' + cols.join(' | ') + ' |';
111
- found = true;
112
- break;
113
- }
114
- } else if (inTable) {
115
- break;
116
- }
117
- }
118
-
119
- if (!found) {
120
- throw new Error(`File not found in artefacts table: ${file}`);
121
- }
122
-
123
- return lines.join('\n');
124
- }