@really-knows-ai/foundry 3.2.5 → 3.2.7
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.
|
@@ -6,6 +6,7 @@ import path from 'path';
|
|
|
6
6
|
import { execFileSync } from 'child_process';
|
|
7
7
|
import { mkdirSync, readdirSync, readFileSync, writeFileSync, unlinkSync, existsSync } from 'fs';
|
|
8
8
|
import { createHash } from 'crypto';
|
|
9
|
+
import { resolveOpenCode } from '../../../scripts/lib/tool-paths.js';
|
|
9
10
|
|
|
10
11
|
const AGENT_FRONTMATTER_TEMPLATE = `---
|
|
11
12
|
description: "Foundry stage agent using MODEL_ID"
|
|
@@ -25,7 +26,7 @@ function buildAgentContent(modelId) {
|
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
function listModels(worktree) {
|
|
28
|
-
const stdout = execFileSync(
|
|
29
|
+
const stdout = execFileSync(resolveOpenCode(), ['models'], {
|
|
29
30
|
cwd: worktree,
|
|
30
31
|
encoding: 'utf8',
|
|
31
32
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
@@ -92,9 +92,11 @@ export function listFlows(foundryDir) {
|
|
|
92
92
|
|
|
93
93
|
function buildFoundryNotInitializedMessage() {
|
|
94
94
|
return `<FOUNDRY_CONTEXT>
|
|
95
|
-
Foundry is installed but not initialised in this project
|
|
96
|
-
|
|
97
|
-
|
|
95
|
+
Foundry is installed but not yet initialised in this project — there is no foundry/ directory.
|
|
96
|
+
The plugin will bootstrap the directory structure, generate stage agents, and install the
|
|
97
|
+
Foundry guide agent automatically on the next startup. The user may just need to restart
|
|
98
|
+
OpenCode for this to happen. Once initialised, direct the user to restart again so the new
|
|
99
|
+
agents register, then switch to the Foundry agent.
|
|
98
100
|
</FOUNDRY_CONTEXT>`;
|
|
99
101
|
}
|
|
100
102
|
|
|
@@ -110,8 +112,9 @@ function buildFlowList(flows) {
|
|
|
110
112
|
|
|
111
113
|
function buildFoundryInitializedMessage(flowList, packageRoot) {
|
|
112
114
|
return `<FOUNDRY_CONTEXT>
|
|
113
|
-
Foundry is active in this project. The foundry/ directory contains the project's artefact
|
|
114
|
-
laws, appraisers, cycles, and flows.
|
|
115
|
+
Foundry is active in this project. The foundry/ directory contains the project's artefact
|
|
116
|
+
definitions, laws, appraisers, cycles, and flows. The user should switch to the Foundry agent
|
|
117
|
+
to author and run workflows.
|
|
115
118
|
|
|
116
119
|
Foundry is a skill-driven framework for governed artefact generation and evaluation.
|
|
117
120
|
The pipeline: assay (populate memory) → forge (produce) → quench (deterministic checks) → appraise (subjective evaluation) → human-appraise (human review) → iterate.
|
|
@@ -142,7 +145,10 @@ Scripts are located at: ${path.join(packageRoot, 'scripts')}
|
|
|
142
145
|
export function getBootstrapContent(directory, packageRoot, restartNeeded = false) {
|
|
143
146
|
if (restartNeeded) {
|
|
144
147
|
return `<FOUNDRY_CONTEXT>
|
|
145
|
-
Foundry
|
|
148
|
+
Foundry has just been initialised in this project. The directory structure, stage agent files,
|
|
149
|
+
and Foundry guide agent have all been created. Tell the user to restart OpenCode now so the new
|
|
150
|
+
agents register. After restarting, the user should switch to the Foundry agent to author and
|
|
151
|
+
run workflows.
|
|
146
152
|
</FOUNDRY_CONTEXT>`;
|
|
147
153
|
}
|
|
148
154
|
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import path from 'path';
|
|
14
14
|
import { fileURLToPath } from 'url';
|
|
15
15
|
import { existsSync, readdirSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
16
|
+
import { execFileSync } from 'child_process';
|
|
16
17
|
import { tool } from '@opencode-ai/plugin';
|
|
17
18
|
import { createPendingStore } from '../../scripts/lib/pending.js';
|
|
18
19
|
import { getBootstrapContent } from './foundry-tools/helpers.js';
|
|
@@ -35,6 +36,7 @@ import { createMemoryAdminTools } from './foundry-tools/memory-admin-tools.js';
|
|
|
35
36
|
import { createSnapshotTools } from './foundry-tools/snapshot-tools.js';
|
|
36
37
|
import { createAttestationTools } from './foundry-tools/attestation-tools.js';
|
|
37
38
|
import { createRefreshAgentsTool } from './foundry-tools/refresh-agents-tool.js';
|
|
39
|
+
import { resolveGit } from '../../scripts/lib/tool-paths.js';
|
|
38
40
|
|
|
39
41
|
function findPackageRoot(startDir) {
|
|
40
42
|
let dir = startDir;
|
|
@@ -81,7 +83,7 @@ function bootstrapGitignore(worktree) {
|
|
|
81
83
|
}
|
|
82
84
|
content = ensureNewlineSuffix(content);
|
|
83
85
|
const existingLines = content.split('\n').map(l => l.trim());
|
|
84
|
-
const lines = ['.snapshots/', 'node_modules/', '.DS_Store'];
|
|
86
|
+
const lines = ['.snapshots/', '.foundry/', 'node_modules/', '.DS_Store'];
|
|
85
87
|
for (const line of lines) {
|
|
86
88
|
if (existingLines.includes(line)) continue;
|
|
87
89
|
content += `${line}\n`;
|
|
@@ -89,6 +91,18 @@ function bootstrapGitignore(worktree) {
|
|
|
89
91
|
writeFileSync(gitignorePath, content, 'utf8');
|
|
90
92
|
}
|
|
91
93
|
|
|
94
|
+
function initGitRepo(worktree) {
|
|
95
|
+
if (existsSync(path.join(worktree, '.git'))) return;
|
|
96
|
+
try {
|
|
97
|
+
const git = resolveGit();
|
|
98
|
+
execFileSync(git, ['init'], { cwd: worktree, stdio: 'pipe' });
|
|
99
|
+
execFileSync(git, ['add', '.'], { cwd: worktree, stdio: 'pipe' });
|
|
100
|
+
execFileSync(git, ['commit', '-m', 'chore: initialise Foundry'], { cwd: worktree, stdio: 'pipe' });
|
|
101
|
+
} catch (err) {
|
|
102
|
+
console.error('Foundry git init error:', err.message);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
92
106
|
function runBootstrapSequence(worktree, pkgRoot) {
|
|
93
107
|
bootstrapDirectories(worktree);
|
|
94
108
|
bootstrapGitignore(worktree);
|
|
@@ -96,6 +110,7 @@ function runBootstrapSequence(worktree, pkgRoot) {
|
|
|
96
110
|
writeFoundryGuideAgent(worktree, pkgRoot);
|
|
97
111
|
const pkg = JSON.parse(readFileSync(path.join(pkgRoot, 'package.json'), 'utf8'));
|
|
98
112
|
writeFileSync(path.join(worktree, 'foundry', 'VERSION'), pkg.version, 'utf8');
|
|
113
|
+
initGitRepo(worktree);
|
|
99
114
|
}
|
|
100
115
|
|
|
101
116
|
function checkVersionMatch(foundryDir, pkgRoot) {
|
package/dist/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [3.2.7] - 2026-05-14
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **Git repo initialisation during bootstrap.** If the worktree has no
|
|
8
|
+
`.git` directory, Foundry now runs `git init`, `git add .`, and
|
|
9
|
+
`git commit` after creating the initial directory structure. Projects
|
|
10
|
+
start with a clean initial commit of the generated configuration.
|
|
11
|
+
- **Tool path resolution from PATH.** A new `tool-paths.js` module
|
|
12
|
+
resolves `git` and `opencode` from `PATH` on each call instead of
|
|
13
|
+
executing bare command names. Overridable via `FOUNDRY_GIT_PATH` and
|
|
14
|
+
`FOUNDRY_OPENCODE_PATH` environment variables. Removed
|
|
15
|
+
`sonarjs/no-os-command-from-path` lint overrides for `foundry.js`
|
|
16
|
+
and `agent-refresh.js`.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- **`.foundry/` added to default `.gitignore`.** The runtime state
|
|
21
|
+
directory was previously created but not ignored by default.
|
|
22
|
+
|
|
23
|
+
## [3.2.6] - 2026-05-14
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- **Bootstrap context messages confused the AI.** The injected `FOUNDRY_CONTEXT`
|
|
28
|
+
messages were written as direct user instructions ("Restart OpenCode..."),
|
|
29
|
+
but the AI reads them as system context and interprets them as commands to
|
|
30
|
+
itself. Rewritten as AI-facing framing: "Tell the user to restart...",
|
|
31
|
+
"The user should switch to the Foundry agent...".
|
|
32
|
+
|
|
3
33
|
## [3.2.5] - 2026-05-14
|
|
4
34
|
|
|
5
35
|
### Changed
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { existsSync } from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
function resolveFromPath(name) {
|
|
5
|
+
const dirs = (process.env.PATH || '').split(path.delimiter);
|
|
6
|
+
for (const dir of dirs) {
|
|
7
|
+
const candidate = path.join(dir, name);
|
|
8
|
+
if (existsSync(candidate)) return candidate;
|
|
9
|
+
}
|
|
10
|
+
return name;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function resolveGit() {
|
|
14
|
+
return process.env.FOUNDRY_GIT_PATH || resolveFromPath('git');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function resolveOpenCode() {
|
|
18
|
+
return process.env.FOUNDRY_OPENCODE_PATH || resolveFromPath('opencode');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { resolveGit, resolveOpenCode };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@really-knows-ai/foundry",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.7",
|
|
4
4
|
"description": "A skill-driven framework for governed artefact generation with AI coding tools. Define your own artefact types, laws, and flows — Foundry handles the forge → quench → appraise pipeline with deterministic routing, quality gates, and iterative refinement.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/.opencode/plugins/foundry.js",
|