@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
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: assay
|
|
3
|
+
type: atomic
|
|
4
|
+
description: Deterministic population of flow memory by running project-authored extractor scripts. Writes JSONL output into entities and edges via foundry tools.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Assay
|
|
8
|
+
|
|
9
|
+
Runs the `assay` stage of a cycle. An assay stage executes every extractor listed in the cycle's `assay.extractors` frontmatter, in order. Each extractor is a project-authored CLI script at the path given in its definition file — see the `foundry/memory/extractors/<name>.md` files for what each one does.
|
|
10
|
+
|
|
11
|
+
The assay stage is **deterministic**. This skill does **not** interpret extractor output. It only calls `foundry_assay_run`, which handles spawning, parsing, validation, and memory upserts. On any failure (extractor non-zero exit, parse error, permission violation, timeout, or post-run memory sync failure), `foundry_assay_run` marks the workfile failed (`status: failed`) with a reason describing the failure, and returns `{error, flow_failed: true, ...}`. The cycle is over — extractor scripts live outside any artefact's `file-patterns`, so forge cannot fix them. The user must fix the extractor and start a new cycle. Your job is to wrap the lifecycle cleanly: end the stage with a descriptive summary even on failure, then stop.
|
|
12
|
+
|
|
13
|
+
## Protocol
|
|
14
|
+
|
|
15
|
+
You have been dispatched to run an assay stage. The dispatch prompt contains a stage identifier like `assay:<cycle>` and a token.
|
|
16
|
+
|
|
17
|
+
Follow these steps exactly and in order.
|
|
18
|
+
|
|
19
|
+
### 1. Begin the stage
|
|
20
|
+
|
|
21
|
+
Call `foundry_stage_begin({ stage, cycle, token })` with the values from the dispatch prompt. If the result is not `{ok: true}`, stop and report the error — something is wrong with the token or an already-active stage.
|
|
22
|
+
|
|
23
|
+
### 2. Read WORK.md to find the extractor list
|
|
24
|
+
|
|
25
|
+
Call `foundry_workfile_get()`. Read `frontmatter.assay.extractors`. This is an ordered array of extractor names. If it is missing or empty, this is a routing bug — end the stage (step 5) with an error summary describing the missing extractor list.
|
|
26
|
+
|
|
27
|
+
### Check for failed flow state
|
|
28
|
+
|
|
29
|
+
If `foundry_workfile_get` returns `{status: "failed", reason: ...}`, STOP. Do not call any other tool. Tell the user:
|
|
30
|
+
|
|
31
|
+
> The flow is in a failed state. Reason: `<reason>`.
|
|
32
|
+
>
|
|
33
|
+
> No further work is permitted. To recover:
|
|
34
|
+
>
|
|
35
|
+
> 1. `foundry_workfile_delete({confirm: true})` to abandon the cycle.
|
|
36
|
+
> 2. Back out to main (`git checkout main`) and delete the work branch.
|
|
37
|
+
> 3. Investigate and fix the root cause of the failure before restarting.
|
|
38
|
+
|
|
39
|
+
Then return control to the user and stop.
|
|
40
|
+
|
|
41
|
+
### 3. Run the extractors
|
|
42
|
+
|
|
43
|
+
Call `foundry_assay_run({ cycle, extractors })` passing exactly those values. Do not modify the list. Do not split it into multiple calls. The tool returns one of:
|
|
44
|
+
|
|
45
|
+
- `{ok: true, perExtractor: [{name, rowsUpserted, durationMs}, ...]}` — all extractors succeeded.
|
|
46
|
+
- `{error, flow_failed: true, aborted: true, failedExtractor, reason, stderr, perExtractor: [...]}` — the run aborted on an extractor failure. The workfile is already marked failed; no further work is permitted until the user abandons the cycle.
|
|
47
|
+
- `{error, flow_failed: true}` — post-run memory sync failed. Same recovery path: workfile is failed, user must abandon.
|
|
48
|
+
- `{error: "..."}` (without `flow_failed`) — a precondition failed (not an active assay stage, etc.). This should not happen if step 1 succeeded; treat as an error and end the stage (step 5) with the error text as the summary.
|
|
49
|
+
|
|
50
|
+
### 4. Prepare the summary
|
|
51
|
+
|
|
52
|
+
Build a short summary string for `foundry_stage_end`. Examples:
|
|
53
|
+
|
|
54
|
+
- On success: `"ran 2 extractors, upserted 47 rows in 1420ms"`.
|
|
55
|
+
- On abort: `"aborted on extractor 'java-symbols': extractor exited with exit code 2"`.
|
|
56
|
+
|
|
57
|
+
Do not add feedback items, do not call `foundry_feedback_add`. Assay stages cannot file feedback — extractor failure is recorded directly on the workfile (`status: failed`).
|
|
58
|
+
|
|
59
|
+
### 5. End the stage
|
|
60
|
+
|
|
61
|
+
Call `foundry_stage_end({ summary })` with the summary from step 4. Always end the stage, whether the run succeeded or aborted. The stage lifecycle must close cleanly so the orchestrator can commit.
|
|
62
|
+
|
|
63
|
+
## What this skill must not do
|
|
64
|
+
|
|
65
|
+
- **Must not** read or parse extractor output files itself.
|
|
66
|
+
- **Must not** call any memory write tools (`foundry_memory_put`, `foundry_memory_relate`, etc.). All writes go through `foundry_assay_run`.
|
|
67
|
+
- **Must not** invoke `foundry_feedback_add`. Assay stages cannot file feedback; extractor failure is signalled by the workfile's `status: failed` field.
|
|
68
|
+
- **Must not** modify any artefact files. The assay stage writes only to flow memory.
|
|
69
|
+
|
|
70
|
+
## If something unexpected happens
|
|
71
|
+
|
|
72
|
+
If `foundry_assay_run` throws an unrelated error (e.g. `error: memory not enabled`), that is a programming error in the cycle configuration — not an expected extractor failure. Do not retry. End the stage with a summary quoting the error and stop.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: change-embedding-model
|
|
3
|
+
type: atomic
|
|
4
|
+
description: Swap the embedding model for memory and re-embed all existing entities
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Change Embedding Model
|
|
8
|
+
|
|
9
|
+
Update `foundry/memory/config.md` to target a new OpenAI-compatible endpoint / model
|
|
10
|
+
and re-embed every existing entity.
|
|
11
|
+
|
|
12
|
+
## Prerequisites
|
|
13
|
+
|
|
14
|
+
Before running this skill, verify all of the following:
|
|
15
|
+
|
|
16
|
+
1. The `foundry/` directory exists in the project root. If it does not
|
|
17
|
+
exist, stop and tell the user:
|
|
18
|
+
|
|
19
|
+
> Foundry is not initialized in this project. Run the
|
|
20
|
+
> `init-foundry` skill first to create the foundry/ directory
|
|
21
|
+
> structure.
|
|
22
|
+
|
|
23
|
+
2. The current git branch is a `config/*` branch. Run
|
|
24
|
+
`git rev-parse --abbrev-ref HEAD` and confirm it matches
|
|
25
|
+
`config/<description>`.
|
|
26
|
+
|
|
27
|
+
3. If the branch does not start with `config/`, instruct the user to
|
|
28
|
+
create one before continuing:
|
|
29
|
+
|
|
30
|
+
> Foundry configuration changes must be made on a config/* branch.
|
|
31
|
+
> From a clean main branch, call:
|
|
32
|
+
>
|
|
33
|
+
> `foundry_git_branch({ kind: "config", description: "<short-name>" })`
|
|
34
|
+
>
|
|
35
|
+
> Then re-run this skill.
|
|
36
|
+
|
|
37
|
+
If the user is on a `dry-run/*/*` branch, they must finish
|
|
38
|
+
that dry-run first (`foundry_git_finish({ message, confirm: true })`)
|
|
39
|
+
before re-running this skill on the parent `config/*`.
|
|
40
|
+
|
|
41
|
+
4. Memory is initialised and enabled. The new provider is reachable
|
|
42
|
+
from this machine. Allow enough time and bandwidth to re-embed
|
|
43
|
+
(O(#entities) requests in batches).
|
|
44
|
+
|
|
45
|
+
## Steps
|
|
46
|
+
|
|
47
|
+
1. **Ask the user for**: `model`, `dimensions`, optionally new `baseURL`, `apiKey`.
|
|
48
|
+
2. **Invoke `foundry_memory_change_embedding_model`** with `{ model, dimensions, baseURL?, apiKey? }`.
|
|
49
|
+
The tool probes the new provider, re-embeds every entity, rewrites
|
|
50
|
+
`schema.json`, and then updates `foundry/memory/config.md` frontmatter to
|
|
51
|
+
match. On probe or re-embed failure, nothing is written.
|
|
52
|
+
3. **Verify** by invoking `foundry_memory_search` with a sample query.
|
|
53
|
+
4. **Commit**:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
git add foundry/memory/config.md foundry/memory/schema.json foundry-memory/relations/
|
|
57
|
+
git commit -m "chore(memory): change embedding model to <model>"
|
|
58
|
+
```
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: drop-memory-edge-type
|
|
3
|
+
type: atomic
|
|
4
|
+
description: Delete an edge type and all its rows
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Drop Memory Edge Type
|
|
8
|
+
|
|
9
|
+
**Destructive.** Deletes all edges of this type.
|
|
10
|
+
|
|
11
|
+
## Prerequisites
|
|
12
|
+
|
|
13
|
+
Before running this skill, verify all of the following:
|
|
14
|
+
|
|
15
|
+
1. The `foundry/` directory exists in the project root. If it does not
|
|
16
|
+
exist, stop and tell the user:
|
|
17
|
+
|
|
18
|
+
> Foundry is not initialized in this project. Run the
|
|
19
|
+
> `init-foundry` skill first to create the foundry/ directory
|
|
20
|
+
> structure.
|
|
21
|
+
|
|
22
|
+
2. The current git branch is a `config/*` branch. Run
|
|
23
|
+
`git rev-parse --abbrev-ref HEAD` and confirm it matches
|
|
24
|
+
`config/<description>`.
|
|
25
|
+
|
|
26
|
+
3. If the branch does not start with `config/`, instruct the user to
|
|
27
|
+
create one before continuing:
|
|
28
|
+
|
|
29
|
+
> Foundry configuration changes must be made on a config/* branch.
|
|
30
|
+
> From a clean main branch, call:
|
|
31
|
+
>
|
|
32
|
+
> `foundry_git_branch({ kind: "config", description: "<short-name>" })`
|
|
33
|
+
>
|
|
34
|
+
> Then re-run this skill.
|
|
35
|
+
|
|
36
|
+
If the user is on a `dry-run/*/*` branch, they must finish
|
|
37
|
+
that dry-run first (`foundry_git_finish({ message, confirm: true })`)
|
|
38
|
+
before re-running this skill on the parent `config/*`.
|
|
39
|
+
|
|
40
|
+
4. Memory is initialised (`foundry/memory/` exists; run `init-memory`
|
|
41
|
+
if not).
|
|
42
|
+
|
|
43
|
+
## Steps
|
|
44
|
+
|
|
45
|
+
1. Ask the user for the edge type name.
|
|
46
|
+
2. Invoke `foundry_memory_drop_edge_type` with `{ name, confirm: false }` (or omit `confirm`). This returns `{ requiresConfirm: true, preview: { rows } }` — show the user the row count that will be deleted.
|
|
47
|
+
3. Require explicit "yes, delete it" confirmation.
|
|
48
|
+
4. Invoke `foundry_memory_drop_edge_type` again with `{ name, confirm: true }`.
|
|
49
|
+
5. Commit:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
git add -A foundry/memory/ foundry-memory/relations/
|
|
53
|
+
git commit -m "refactor(memory): drop edge type <name>"
|
|
54
|
+
```
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: drop-memory-entity-type
|
|
3
|
+
type: atomic
|
|
4
|
+
description: Delete an entity type; cascades to affected edges
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Drop Memory Entity Type
|
|
8
|
+
|
|
9
|
+
**Destructive.** This deletes all rows of this type and strips or removes any
|
|
10
|
+
edges that reference it.
|
|
11
|
+
|
|
12
|
+
## Prerequisites
|
|
13
|
+
|
|
14
|
+
Before running this skill, verify all of the following:
|
|
15
|
+
|
|
16
|
+
1. The `foundry/` directory exists in the project root. If it does not
|
|
17
|
+
exist, stop and tell the user:
|
|
18
|
+
|
|
19
|
+
> Foundry is not initialized in this project. Run the
|
|
20
|
+
> `init-foundry` skill first to create the foundry/ directory
|
|
21
|
+
> structure.
|
|
22
|
+
|
|
23
|
+
2. The current git branch is a `config/*` branch. Run
|
|
24
|
+
`git rev-parse --abbrev-ref HEAD` and confirm it matches
|
|
25
|
+
`config/<description>`.
|
|
26
|
+
|
|
27
|
+
3. If the branch does not start with `config/`, instruct the user to
|
|
28
|
+
create one before continuing:
|
|
29
|
+
|
|
30
|
+
> Foundry configuration changes must be made on a config/* branch.
|
|
31
|
+
> From a clean main branch, call:
|
|
32
|
+
>
|
|
33
|
+
> `foundry_git_branch({ kind: "config", description: "<short-name>" })`
|
|
34
|
+
>
|
|
35
|
+
> Then re-run this skill.
|
|
36
|
+
|
|
37
|
+
If the user is on a `dry-run/*/*` branch, they must finish
|
|
38
|
+
that dry-run first (`foundry_git_finish({ message, confirm: true })`)
|
|
39
|
+
before re-running this skill on the parent `config/*`.
|
|
40
|
+
|
|
41
|
+
4. Memory is initialised (`foundry/memory/` exists; run `init-memory`
|
|
42
|
+
if not).
|
|
43
|
+
|
|
44
|
+
## Steps
|
|
45
|
+
|
|
46
|
+
1. Ask the user for the type name.
|
|
47
|
+
2. Invoke `foundry_memory_drop_entity_type` with `{ name, confirm: false }` (or omit `confirm`). This returns `{ requiresConfirm: true, preview: { entityRows, affectedEdges: [...] } }`. Show the user:
|
|
48
|
+
- `entityRows` — number of entities of this type that will be deleted.
|
|
49
|
+
- For each `affectedEdges` entry: `cascadeDrop` means the whole edge type disappears; `prune` means `rowsAffected` rows will be removed but the edge type survives.
|
|
50
|
+
3. Require explicit "yes, delete it" confirmation.
|
|
51
|
+
4. Invoke `foundry_memory_drop_entity_type` again with `{ name, confirm: true }`.
|
|
52
|
+
5. Commit:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
git add -A foundry/memory/ foundry-memory/relations/
|
|
56
|
+
git commit -m "refactor(memory): drop entity type <name>"
|
|
57
|
+
```
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dry-run
|
|
3
|
+
type: atomic
|
|
4
|
+
description: Trial-run a flow against in-progress config on a dry-run/<x>/<y> branch; finish writes a forensic snapshot and discards the branch.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Dry-run
|
|
8
|
+
|
|
9
|
+
You help the user trial in-progress config changes against a real flow,
|
|
10
|
+
without merging the config or polluting the config branch's history.
|
|
11
|
+
|
|
12
|
+
## When to use
|
|
13
|
+
|
|
14
|
+
The user is on a `config/<x>` branch with edits in progress (a new law, a
|
|
15
|
+
modified flow, a fresh appraiser, etc.) and wants to see how a flow
|
|
16
|
+
behaves under those changes — without merging, and without leaving WORK
|
|
17
|
+
files or memory rows behind on `config/<x>`.
|
|
18
|
+
|
|
19
|
+
## Prerequisites
|
|
20
|
+
|
|
21
|
+
1. Current branch is `config/<x>` (single segment, not nested).
|
|
22
|
+
2. Working tree is clean.
|
|
23
|
+
3. The flow id and a one-line description of the goal are known.
|
|
24
|
+
|
|
25
|
+
If on `main`, edit on a `config/<x>` branch first:
|
|
26
|
+
`foundry_git_branch({ kind: "config", description: "<short-name>" })`.
|
|
27
|
+
|
|
28
|
+
## Protocol
|
|
29
|
+
|
|
30
|
+
### 1. Branch into dry-run mode
|
|
31
|
+
|
|
32
|
+
```text
|
|
33
|
+
foundry_git_branch({
|
|
34
|
+
kind: "dry-run",
|
|
35
|
+
flowId: "<flow-id>",
|
|
36
|
+
description: "<dry-run-purpose-slug>"
|
|
37
|
+
})
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
This creates `dry-run/<x>/<flow>-<purpose>` and truncates the trace
|
|
41
|
+
file. From here every `foundry_*` tool call is logged to
|
|
42
|
+
`.foundry/trace/<branch-slug>.jsonl`.
|
|
43
|
+
|
|
44
|
+
### 2. Run the flow
|
|
45
|
+
|
|
46
|
+
Use the `flow` skill (or call `foundry_orchestrate` directly) to drive
|
|
47
|
+
the flow against the goal. Memory data writes go to `foundry-memory/`
|
|
48
|
+
on this branch — they are discarded with the branch.
|
|
49
|
+
|
|
50
|
+
If the flow needs config to be adjusted mid-run: stop, finish the
|
|
51
|
+
dry-run (step 4), edit on `config/<x>`, then start a new dry-run.
|
|
52
|
+
|
|
53
|
+
### 3. Inspect WORK during the run (optional)
|
|
54
|
+
|
|
55
|
+
`foundry_workfile_get` and the read-only memory tools work as normal;
|
|
56
|
+
they appear in the trace.
|
|
57
|
+
|
|
58
|
+
### 4. Finish: snapshot + discard
|
|
59
|
+
|
|
60
|
+
```text
|
|
61
|
+
foundry_git_finish({
|
|
62
|
+
message: "<one-paragraph findings>",
|
|
63
|
+
confirm: true
|
|
64
|
+
})
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The tool:
|
|
68
|
+
|
|
69
|
+
- writes `.snapshots/<run-id>/` on the parent `config/<x>` working
|
|
70
|
+
tree, containing `README.md`, `work/WORK*`, `diff.patch`, and
|
|
71
|
+
`trace.jsonl`;
|
|
72
|
+
- force-deletes the dry-run branch (its commits become unreachable);
|
|
73
|
+
- truncates `.foundry/trace/<branch-slug>.jsonl`.
|
|
74
|
+
|
|
75
|
+
The user is now back on `config/<x>` with the snapshot on disk.
|
|
76
|
+
Nothing is committed. The snapshot directory is gitignored.
|
|
77
|
+
|
|
78
|
+
`baseBranch` is **not valid** for a dry-run finish — the parent is the
|
|
79
|
+
config branch the dry-run was started from.
|
|
80
|
+
|
|
81
|
+
### 5. Inspect the snapshot
|
|
82
|
+
|
|
83
|
+
- `foundry_snapshot_list()` enumerates all snapshots.
|
|
84
|
+
- `foundry_snapshot_show({ runId })` returns a structured summary.
|
|
85
|
+
- The actual files at `.snapshots/<run-id>/` are flat — read directly
|
|
86
|
+
with `Read` or shell tools.
|
|
87
|
+
|
|
88
|
+
If the snapshot reveals the config needs adjustment: edit on
|
|
89
|
+
`config/<x>` (still on it after finish), then optionally re-enter
|
|
90
|
+
dry-run mode for another run. Snapshots accumulate; prune them with
|
|
91
|
+
`foundry_snapshot_delete` or `foundry_snapshot_prune`.
|
|
92
|
+
|
|
93
|
+
### 6. Finish the config
|
|
94
|
+
|
|
95
|
+
When ready, finish `config/<x>` to `main`:
|
|
96
|
+
|
|
97
|
+
```text
|
|
98
|
+
foundry_git_finish({
|
|
99
|
+
message: "<config description>",
|
|
100
|
+
baseBranch: "main",
|
|
101
|
+
confirm: true
|
|
102
|
+
})
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Snapshots are gitignored and stay in the local working tree; they do
|
|
106
|
+
not merge with the config.
|
|
107
|
+
|
|
108
|
+
## What you do NOT do
|
|
109
|
+
|
|
110
|
+
- You do not run schema-mutation tools while on a dry-run branch.
|
|
111
|
+
`foundry_config_create_*` and the memory-schema tools refuse there
|
|
112
|
+
by design.
|
|
113
|
+
- You do not nest dry-runs (deeper nesting under `dry-run/` is refused).
|
|
114
|
+
- You do not commit the snapshot directory by hand. If a particular
|
|
115
|
+
snapshot must be preserved beyond the local checkout, copy it out
|
|
116
|
+
first, then delete the original via `foundry_snapshot_delete`.
|
|
@@ -9,6 +9,8 @@ composes: [orchestrate]
|
|
|
9
9
|
|
|
10
10
|
A foundry flow reads a flow definition, creates a work branch, and executes cycles by following the dependency graph — each cycle declares its own targets and input contracts.
|
|
11
11
|
|
|
12
|
+
**Testing uncommitted config changes:** If you are on a `config/<x>` branch with in-progress edits to artefact types, laws, cycles, or flows and want to trial-run a flow against those changes without committing them, use the `dry-run` skill instead. Dry-run creates an isolated `dry-run/<x>/<y>` branch, runs the flow, captures a forensic snapshot, and discards the branch — leaving your config branch clean.
|
|
13
|
+
|
|
12
14
|
## Prerequisites
|
|
13
15
|
|
|
14
16
|
Before running this skill, verify that the `foundry/` directory exists in the project root. If it does not exist, stop and tell the user:
|
|
@@ -18,7 +20,7 @@ Before running this skill, verify that the `foundry/` directory exists in the pr
|
|
|
18
20
|
## Starting a flow
|
|
19
21
|
|
|
20
22
|
1. Call `foundry_config_flow` with the flow ID — get the flow definition
|
|
21
|
-
2. Call `foundry_git_branch` with the flow ID and a short description — create the work branch
|
|
23
|
+
2. Call `foundry_git_branch` with `kind: "work"`, the flow ID, and a short description — create the work branch (e.g. `foundry_git_branch({ kind: "work", flowId, description })`)
|
|
22
24
|
3. Determine the starting cycle:
|
|
23
25
|
- Any cycle listed in the flow can be the starting cycle. The flow's `starting-cycles` list is a hint for when the user's request is ambiguous.
|
|
24
26
|
- Map the user's goal to a cycle by matching the requested output (e.g. "write a short story from the tennis haiku" → `create-short-story`; "write a haiku" → `create-haiku`).
|
|
@@ -31,6 +33,17 @@ Before running this skill, verify that the `foundry/` directory exists in the pr
|
|
|
31
33
|
- **Resume** — keep the existing workfile and skip to step 6. **Only offer resume if the existing `flow` AND `cycle` match what the user just asked for.** If either differs, do not offer resume — running the wrong cycle against stale state corrupts the workflow.
|
|
32
34
|
- **Discard** — call `foundry_workfile_delete`, then proceed to step 5.
|
|
33
35
|
- **Abort** — stop the skill without modifying anything.
|
|
36
|
+
d. Check for failed flow state. If `foundry_workfile_get` returns `{status: "failed", reason: ...}`, STOP. Do not call any other tool. Tell the user:
|
|
37
|
+
|
|
38
|
+
> The flow is in a failed state. Reason: `<reason>`.
|
|
39
|
+
>
|
|
40
|
+
> No further work is permitted. To recover:
|
|
41
|
+
>
|
|
42
|
+
> 1. `foundry_workfile_delete({confirm: true})` to abandon the cycle.
|
|
43
|
+
> 2. Back out to main (`git checkout main`) and delete the work branch.
|
|
44
|
+
> 3. Investigate and fix the root cause of the failure before restarting.
|
|
45
|
+
|
|
46
|
+
Then return control to the user and stop.
|
|
34
47
|
5. Call `foundry_workfile_create` with **only** the flow ID, chosen cycle ID, and goal — do **not** pass `stages` or `maxIterations`. The `orchestrate` skill will read the cycle definition and handle setup on its first call.
|
|
35
48
|
6. Execute the cycle by invoking the orchestrate skill
|
|
36
49
|
|
|
@@ -61,7 +74,7 @@ When all desired cycles are done:
|
|
|
61
74
|
|
|
62
75
|
1. Present a summary of what was produced (all artefacts and their status)
|
|
63
76
|
2. Ask the user how they want to finish:
|
|
64
|
-
- **Squash merge** — call `foundry_git_finish` with a commit message and base branch
|
|
77
|
+
- **Squash merge** — call `foundry_git_finish` with a commit message and base branch. The flow skill always lands on `work/<flow>-<desc>`, so the tool dispatches to its `work` mode. **Audit-aware**: commits `WORK.*` cleanup on the work branch, preserves the branch as `archive/work/<flow>-<desc>-<hash>` for immutable forensic history, squash-merges to the base branch, and creates a signed commit embedding the canonical Foundry attestation block. Requires `confirm: true` (without it returns a plan); refuses dirty worktrees; on merge conflict aborts and preserves the work branch. (`foundry_git_finish` self-classifies by current branch — `config/<x>` finishes integrate without WORK cleanup, and `dry-run/<x>/<y>` finishes write a snapshot. The flow skill exits on `work/<x>`, so only the `work`-mode behaviour applies here.)
|
|
65
78
|
- **Keep the branch** — leave as-is for manual handling
|
|
66
79
|
- **Create a PR** — push and create a pull request
|
|
67
80
|
3. Execute the chosen option
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: forge
|
|
3
|
+
type: atomic
|
|
4
|
+
description: Produces or revises an artefact, guided by WORK.md and the foundry cycle definition.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Forge
|
|
8
|
+
|
|
9
|
+
You produce or revise artefacts. You read the work file to understand the goal, call `foundry_feedback_list` to understand feedback, and read the foundry cycle definition to understand what you're producing and what inputs you can read.
|
|
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
|
+
## Stage lifecycle (mandatory)
|
|
18
|
+
|
|
19
|
+
Forge runs inside an enforced stage. Your **first** and **last** tool calls are fixed:
|
|
20
|
+
|
|
21
|
+
1. **First:** `foundry_stage_begin({stage, cycle, token})` — the orchestrator hands you `stage`, `cycle`, and an opaque `token` string in the dispatch prompt. Copy the token verbatim; never invent, edit, or re-sign it. No other tool call is permitted before this one. Any writes before `stage_begin` will be blocked by preconditions.
|
|
22
|
+
2. **Last:** `foundry_stage_end({summary})` — return control to the orchestrator. After `stage_end`, the orchestrator's internal finalize step scans the disk and registers your output artefact. **You do not register artefacts yourself.**
|
|
23
|
+
|
|
24
|
+
## Protocol
|
|
25
|
+
|
|
26
|
+
### First generation (no artefact registered yet)
|
|
27
|
+
|
|
28
|
+
1. `foundry_stage_begin(...)` with the token from the dispatch prompt.
|
|
29
|
+
2. `foundry_workfile_get` — understand the goal.
|
|
30
|
+
|
|
31
|
+
**Check for failed flow state.** If `foundry_workfile_get` returns `{status: "failed", reason: ...}`, STOP. Do not call any other tool. Tell the user:
|
|
32
|
+
|
|
33
|
+
> The flow is in a failed state. Reason: `<reason>`.
|
|
34
|
+
>
|
|
35
|
+
> No further work is permitted. To recover:
|
|
36
|
+
>
|
|
37
|
+
> 1. `foundry_workfile_delete({confirm: true})` to abandon the cycle.
|
|
38
|
+
> 2. Back out to main (`git checkout main`) and delete the work branch.
|
|
39
|
+
> 3. Investigate and fix the root cause of the failure before restarting.
|
|
40
|
+
|
|
41
|
+
Then return control to the user and stop.
|
|
42
|
+
3. `foundry_config_cycle` — understand what to produce and what inputs are available.
|
|
43
|
+
4. `foundry_config_artefact_type` with the output type ID — get the artefact type definition, especially its `file-patterns`.
|
|
44
|
+
5. `foundry_config_laws` — get all applicable laws (global + type-specific).
|
|
45
|
+
6. If the cycle declares `inputs`, discover input files by filesystem scan:
|
|
46
|
+
- For each type listed in `inputs`, call `foundry_config_artefact_type` to get its `file-patterns`.
|
|
47
|
+
- Glob the working tree against those patterns to enumerate candidate input files.
|
|
48
|
+
- Read the goal (from `foundry_workfile_get`) and select the files that are relevant to this run. If the goal names specific files or slugs, use those; if it describes a category ("all the auth tests"), select the matching subset; if it's open-ended, you may consume all candidates or ask the user when the set is clearly ambiguous.
|
|
49
|
+
- Read the selected files for context.
|
|
50
|
+
7. Produce the artefact, respecting all applicable laws from the start.
|
|
51
|
+
8. Write the artefact file to a location that matches the artefact type's `file-patterns`.
|
|
52
|
+
9. `foundry_stage_end({summary})`.
|
|
53
|
+
|
|
54
|
+
### Revision (feedback exists)
|
|
55
|
+
|
|
56
|
+
1. `foundry_stage_begin(...)`.
|
|
57
|
+
2. `foundry_feedback_list` — find feedback whose state is `open` or `rejected` for the current cycle.
|
|
58
|
+
3. Read the artefact file.
|
|
59
|
+
4. If the cycle declares `inputs`, discover them via filesystem scan against each input type's `file-patterns` (same protocol as first-generation step 6). Re-read the relevant files — they may have changed on disk since the previous iteration (nothing in this cycle wrote to them, but the user may have modified them between iterations).
|
|
60
|
+
5. For each item whose state is `open` or `rejected`, follow the feedback handling rules below.
|
|
61
|
+
6. Update the artefact file.
|
|
62
|
+
7. `foundry_stage_end({summary})`.
|
|
63
|
+
|
|
64
|
+
## Feedback handling
|
|
65
|
+
|
|
66
|
+
Call `foundry_feedback_list` to see feedback items for the current cycle.
|
|
67
|
+
Each entry has shape `{ id, file, tag, text, source, state, depth, reason? }`.
|
|
68
|
+
Action every item whose `state` is `open` or `rejected`:
|
|
69
|
+
|
|
70
|
+
- If you address the feedback in the artefact: call `foundry_feedback_action`
|
|
71
|
+
with `{ id }`. This marks the item `actioned`. The tool returns
|
|
72
|
+
`{ ok: true }` on success; keep using the original list entry's `id` for
|
|
73
|
+
any follow-up.
|
|
74
|
+
- If you decide not to address the feedback: call `foundry_feedback_wontfix`
|
|
75
|
+
with `{ id, reason }`. The reason is required. **You may only mark
|
|
76
|
+
`wont-fix` on items whose `source` stage base is `appraise`.** If the
|
|
77
|
+
item's source base is `quench` (objective validation failure) or
|
|
78
|
+
`human-appraise` (direct user instruction), you must action it — the
|
|
79
|
+
tool will return an error if you attempt `wont-fix`. This replaces the
|
|
80
|
+
old tag-based restriction (`#validation`/`#human` tag check); tags are
|
|
81
|
+
now categorical/display-only and not consulted by the state machine.
|
|
82
|
+
|
|
83
|
+
`foundry_feedback_add` (if you ever call it — forge normally does not)
|
|
84
|
+
returns `{ ok, id, deduped }`. `deduped: true` means an existing
|
|
85
|
+
non-resolved item with the same `(file, tag, hash(text))` was found and no
|
|
86
|
+
new item was written; the returned `id` is the existing item's id.
|
|
87
|
+
`deduped: false` means a new item was created.
|
|
88
|
+
|
|
89
|
+
You cannot resolve or reject items — only the stage that created the item
|
|
90
|
+
(the `source` on each list entry) can do that, with the exception that
|
|
91
|
+
human-appraise can override any non-resolved item. You also cannot action
|
|
92
|
+
items whose state is `actioned`, `wont-fix`, `deadlocked`, or `resolved`.
|
|
93
|
+
|
|
94
|
+
## Write invariant
|
|
95
|
+
|
|
96
|
+
Forge may only write to:
|
|
97
|
+
- Files matching the output artefact type's `file-patterns`.
|
|
98
|
+
- `WORK.md`, `WORK.feedback.yaml`, and `WORK.history.yaml` (tool-managed).
|
|
99
|
+
|
|
100
|
+
Everything else on disk — including files of the cycle's input types, files of unrelated artefact types, and files outside any artefact type — is read-only for this stage. This rule is tool-enforced: the orchestrator's internal finalize step returns `{error: 'unexpected_files'}` and the orchestrator's modified-file check routes a violation on the next call. Either outcome marks the cycle's target artefact `blocked` and you do not get a retry.
|
|
101
|
+
|
|
102
|
+
When a cycle's output type overlaps with one of its input types (e.g. a `refine-haiku` cycle with input `haiku` and output `haiku`), the overlap is intentional: the cycle's job is to modify existing files of that type. The write invariant still holds — you may only touch files matching the output type's patterns, which in this case includes the files you read as inputs.
|
|
103
|
+
|
|
104
|
+
## Resolution vocabulary
|
|
105
|
+
|
|
106
|
+
An item is **unresolved** if its `history[0].state` is one of `open`,
|
|
107
|
+
`rejected`, `actioned`, `wont-fix`, or `deadlocked`. An item is
|
|
108
|
+
**resolved** only when `history[0].state === 'resolved'` (terminal).
|
|
109
|
+
Forge only acts on `open` and `rejected` items; it never sees `resolved`
|
|
110
|
+
items in the list output.
|
|
111
|
+
|
|
112
|
+
## What you do NOT do
|
|
113
|
+
|
|
114
|
+
- You normally do not add feedback — that is the quench and appraise skills' job.
|
|
115
|
+
- You do not `foundry_feedback_resolve` — that belongs to quench/appraise/human-appraise.
|
|
116
|
+
- You do not register artefacts — the orchestrator's internal finalize step handles that automatically.
|
|
117
|
+
- You do not call `foundry_history_append` or `foundry_git_commit` — `foundry_orchestrate` does (those tools are not registered publicly).
|
|
118
|
+
- You do not evaluate or score the artefact.
|
|
119
|
+
- You do not mark feedback as actioned unless you actually changed the artefact to address it.
|
|
120
|
+
- You do not wont-fix items whose `source` stage base is `quench` or `human-appraise`.
|
|
121
|
+
- You do not write to any file outside the output artefact type's `file-patterns` (plus `WORK.md` / `WORK.feedback.yaml` / `WORK.history.yaml`). Input files are read-only unless the output type's patterns happen to cover them.
|