@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('opencode', ['models'], {
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. There is no foundry/ directory.
96
-
97
- To set up Foundry, initialise the project first. Initialisation creates the foundry/ directory structure, installs the user-facing Foundry agent, and generates model-routing stage agents. After initialisation, restart OpenCode and switch to the Foundry agent.
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 definitions,
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 initialised. Restart OpenCode so the Foundry agent and model-routing agents register. After restart, switch to the Foundry agent to author and run workflows.
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.5",
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",