@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.
- package/README.md +200 -198
- package/dist/.opencode/plugins/foundry-tools/appraiser-tools.js +28 -0
- package/dist/.opencode/plugins/foundry-tools/artefact-tools.js +58 -0
- package/dist/.opencode/plugins/foundry-tools/assay-tools.js +92 -0
- package/dist/.opencode/plugins/foundry-tools/attestation-tools.js +191 -0
- package/dist/.opencode/plugins/foundry-tools/config-create-tools.js +128 -0
- package/dist/.opencode/plugins/foundry-tools/config-law-tools.js +380 -0
- package/dist/.opencode/plugins/foundry-tools/config-tools.js +43 -0
- package/dist/.opencode/plugins/foundry-tools/feedback-tools.js +234 -0
- package/dist/.opencode/plugins/foundry-tools/git-helpers.js +354 -0
- package/dist/.opencode/plugins/foundry-tools/git-tools.js +181 -0
- package/dist/.opencode/plugins/foundry-tools/helpers.js +340 -0
- package/dist/.opencode/plugins/foundry-tools/history-tools.js +20 -0
- package/dist/.opencode/plugins/foundry-tools/memory-admin-tools.js +296 -0
- package/dist/.opencode/plugins/foundry-tools/memory-helpers.js +104 -0
- package/dist/.opencode/plugins/foundry-tools/memory-tools.js +286 -0
- package/dist/.opencode/plugins/foundry-tools/orchestrate-tool.js +159 -0
- package/dist/.opencode/plugins/foundry-tools/snapshot-tools.js +104 -0
- package/dist/.opencode/plugins/foundry-tools/stage-tools.js +186 -0
- package/dist/.opencode/plugins/foundry-tools/validate-tools.js +263 -0
- package/dist/.opencode/plugins/foundry-tools/workfile-tools.js +102 -0
- package/dist/.opencode/plugins/foundry.js +105 -0
- package/dist/CHANGELOG.md +490 -0
- package/dist/LICENSE +21 -0
- package/dist/README.md +278 -0
- package/dist/docs/README.md +59 -0
- package/dist/docs/architecture.md +434 -0
- package/dist/docs/concepts.md +396 -0
- package/dist/docs/getting-started.md +345 -0
- package/dist/docs/memory-maintenance.md +176 -0
- package/dist/docs/tools.md +1411 -0
- package/dist/docs/work-spec.md +283 -0
- package/dist/scripts/lib/artefacts.js +151 -0
- package/dist/scripts/lib/assay/loader.js +151 -0
- package/dist/scripts/lib/assay/parse-jsonl.js +102 -0
- package/dist/scripts/lib/assay/permissions.js +52 -0
- package/dist/scripts/lib/assay/run.js +219 -0
- package/dist/scripts/lib/assay/spawn-with-timeout.js +138 -0
- package/dist/scripts/lib/attestation/attest.js +111 -0
- package/dist/scripts/lib/attestation/canonical-json.js +109 -0
- package/dist/scripts/lib/attestation/hash.js +17 -0
- package/dist/scripts/lib/attestation/parse.js +14 -0
- package/dist/scripts/lib/attestation/payload.js +106 -0
- package/dist/scripts/lib/attestation/render.js +16 -0
- package/dist/scripts/lib/attestation/verify.js +15 -0
- package/dist/scripts/lib/branch-guard.js +72 -0
- package/dist/scripts/lib/config-creators/appraiser.js +9 -0
- package/dist/scripts/lib/config-creators/artefact-type.js +9 -0
- package/dist/scripts/lib/config-creators/cycle.js +11 -0
- package/dist/scripts/lib/config-creators/factory.js +49 -0
- package/dist/scripts/lib/config-creators/flow.js +11 -0
- package/dist/scripts/lib/config-validators/appraiser.js +49 -0
- package/dist/scripts/lib/config-validators/artefact-type.js +38 -0
- package/dist/scripts/lib/config-validators/cycle.js +131 -0
- package/dist/scripts/lib/config-validators/flow.js +57 -0
- package/dist/scripts/lib/config-validators/helpers.js +96 -0
- package/dist/scripts/lib/config-validators/law.js +96 -0
- package/dist/scripts/lib/config.js +393 -0
- package/dist/scripts/lib/failed-flow.js +131 -0
- package/dist/scripts/lib/feedback-store.js +249 -0
- package/dist/scripts/lib/feedback-transitions.js +105 -0
- package/dist/scripts/lib/finalize.js +70 -0
- package/dist/scripts/lib/foundational-guards.js +13 -0
- package/dist/scripts/lib/git-bridge.js +77 -0
- package/dist/scripts/lib/git-finish/work-finish.js +233 -0
- package/dist/scripts/lib/git-policy.js +101 -0
- package/dist/scripts/lib/guards.js +125 -0
- package/dist/scripts/lib/history.js +132 -0
- package/dist/scripts/lib/memory/admin/create-edge-type.js +91 -0
- package/dist/scripts/lib/memory/admin/create-entity-type.js +43 -0
- package/dist/scripts/lib/memory/admin/create-extractor.js +67 -0
- package/dist/scripts/lib/memory/admin/drop-edge-type.js +40 -0
- package/dist/scripts/lib/memory/admin/drop-entity-type.js +172 -0
- package/dist/scripts/lib/memory/admin/dump.js +47 -0
- package/dist/scripts/lib/memory/admin/helpers.js +31 -0
- package/dist/scripts/lib/memory/admin/init.js +170 -0
- package/dist/scripts/lib/memory/admin/live-store.js +76 -0
- package/dist/scripts/lib/memory/admin/reembed.js +285 -0
- package/dist/scripts/lib/memory/admin/rename-edge-type.js +54 -0
- package/dist/scripts/lib/memory/admin/rename-entity-type.js +151 -0
- package/dist/scripts/lib/memory/admin/reset.js +24 -0
- package/dist/scripts/lib/memory/admin/vacuum.js +9 -0
- package/dist/scripts/lib/memory/admin/validate.js +19 -0
- package/dist/scripts/lib/memory/config.js +149 -0
- package/dist/scripts/lib/memory/cozo.js +136 -0
- package/dist/scripts/lib/memory/drift.js +71 -0
- package/dist/scripts/lib/memory/embeddings.js +128 -0
- package/dist/scripts/lib/memory/frontmatter.js +75 -0
- package/dist/scripts/lib/memory/ndjson.js +84 -0
- package/dist/scripts/lib/memory/paths.js +25 -0
- package/dist/scripts/lib/memory/permissions.js +41 -0
- package/dist/scripts/lib/memory/prompt.js +109 -0
- package/dist/scripts/lib/memory/query.js +56 -0
- package/dist/scripts/lib/memory/reads.js +109 -0
- package/dist/scripts/lib/memory/schema.js +64 -0
- package/dist/scripts/lib/memory/search.js +73 -0
- package/dist/scripts/lib/memory/singleton.js +49 -0
- package/dist/scripts/lib/memory/store.js +162 -0
- package/dist/scripts/lib/memory/types.js +93 -0
- package/dist/scripts/lib/memory/validate.js +58 -0
- package/dist/scripts/lib/memory/writes.js +40 -0
- package/{scripts → dist/scripts}/lib/pending.js +7 -2
- package/dist/scripts/lib/secret.js +59 -0
- package/{scripts → dist/scripts}/lib/slug.js +3 -2
- package/dist/scripts/lib/snapshot/finish.js +103 -0
- package/dist/scripts/lib/snapshot/inspect.js +253 -0
- package/dist/scripts/lib/snapshot/render.js +55 -0
- package/dist/scripts/lib/sort-fs-check.js +121 -0
- package/dist/scripts/lib/sort-routing.js +101 -0
- package/{scripts → dist/scripts}/lib/stage-guard.js +12 -6
- package/{scripts → dist/scripts}/lib/state.js +4 -0
- package/dist/scripts/lib/token.js +57 -0
- package/dist/scripts/lib/tracing.js +59 -0
- package/dist/scripts/lib/ulid.js +100 -0
- package/dist/scripts/lib/validator-jsonl.js +162 -0
- package/{scripts → dist/scripts}/lib/workfile.js +38 -20
- package/dist/scripts/orchestrate-cycle.js +215 -0
- package/dist/scripts/orchestrate-phases.js +314 -0
- package/dist/scripts/orchestrate.js +163 -0
- package/dist/scripts/sort.js +278 -0
- package/{skills → dist/skills}/add-appraiser/SKILL.md +42 -6
- package/{skills → dist/skills}/add-artefact-type/SKILL.md +49 -21
- package/{skills → dist/skills}/add-cycle/SKILL.md +60 -14
- package/dist/skills/add-extractor/SKILL.md +133 -0
- package/{skills → dist/skills}/add-flow/SKILL.md +39 -7
- package/dist/skills/add-law/SKILL.md +191 -0
- package/dist/skills/add-memory-edge-type/SKILL.md +52 -0
- package/dist/skills/add-memory-entity-type/SKILL.md +74 -0
- package/{skills → dist/skills}/appraise/SKILL.md +62 -13
- package/dist/skills/assay/SKILL.md +72 -0
- package/dist/skills/change-embedding-model/SKILL.md +58 -0
- package/dist/skills/drop-memory-edge-type/SKILL.md +54 -0
- package/dist/skills/drop-memory-entity-type/SKILL.md +57 -0
- package/dist/skills/dry-run/SKILL.md +116 -0
- package/{skills → dist/skills}/flow/SKILL.md +15 -2
- package/dist/skills/forge/SKILL.md +121 -0
- package/dist/skills/human-appraise/SKILL.md +153 -0
- package/{skills → dist/skills}/init-foundry/SKILL.md +23 -4
- package/dist/skills/init-memory/SKILL.md +92 -0
- package/{skills → dist/skills}/orchestrate/SKILL.md +30 -4
- package/dist/skills/quench/SKILL.md +99 -0
- package/{skills → dist/skills}/refresh-agents/SKILL.md +1 -1
- package/dist/skills/rename-memory-edge-type/SKILL.md +50 -0
- package/dist/skills/rename-memory-entity-type/SKILL.md +51 -0
- package/dist/skills/reset-memory/SKILL.md +54 -0
- package/dist/skills/upgrade-foundry/SKILL.md +192 -0
- package/package.json +34 -17
- package/.opencode/plugins/foundry.js +0 -761
- package/CHANGELOG.md +0 -90
- package/docs/concepts.md +0 -59
- package/docs/getting-started.md +0 -78
- package/docs/work-spec.md +0 -193
- package/scripts/lib/artefacts.js +0 -124
- package/scripts/lib/config.js +0 -175
- package/scripts/lib/feedback-transitions.js +0 -25
- package/scripts/lib/feedback.js +0 -440
- package/scripts/lib/finalize.js +0 -41
- package/scripts/lib/history.js +0 -59
- package/scripts/lib/secret.js +0 -23
- package/scripts/lib/tags.js +0 -108
- package/scripts/lib/token.js +0 -26
- package/scripts/orchestrate.js +0 -418
- package/scripts/sort.js +0 -370
- package/scripts/validate-tags.js +0 -54
- package/skills/add-law/SKILL.md +0 -105
- package/skills/forge/SKILL.md +0 -88
- package/skills/human-appraise/SKILL.md +0 -82
- package/skills/quench/SKILL.md +0 -62
- package/skills/upgrade-foundry/SKILL.md +0 -216
- /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.
|
package/docs/getting-started.md
DELETED
|
@@ -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
|
-
```
|
package/scripts/lib/artefacts.js
DELETED
|
@@ -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
|
-
}
|