@really-knows-ai/foundry 3.5.3 → 3.5.4

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.
@@ -87,18 +87,28 @@ async function injectDispatchPromptExtras(result, cwd) {
87
87
  result.prompt = `${result.prompt}\n\n${extras}`;
88
88
  }
89
89
 
90
+ function buildOrchestrateArgs(tool) {
91
+ return {
92
+ lastResult: tool.schema.object({
93
+ ok: tool.schema.boolean(),
94
+ error: tool.schema.string().optional(),
95
+ }).optional().describe('Result of a single-subagent dispatch or human-appraise stage'),
96
+ lastResults: tool.schema.array(tool.schema.object({
97
+ ok: tool.schema.boolean(),
98
+ output: tool.schema.string().optional(),
99
+ error: tool.schema.string().optional(),
100
+ })).optional().describe('Results of a dispatch_multi (appraise) — one entry per completed appraiser task'),
101
+ cycleDef: tool.schema.string().optional().describe('Test-mode cycle definition override (path to cycle file)'),
102
+ baseBranch: tool.schema.string().optional().describe('Git base branch for artefact diff comparison (default "main")'),
103
+ defaultModel: tool.schema.string().optional().describe('Fallback model for stages with no explicit model in the cycle definition (e.g. "opencode-go/deepseek-v4-flash")'),
104
+ };
105
+ }
106
+
90
107
  export function createOrchestrateTool({ tool, pending }) {
91
108
  return {
92
109
  foundry_orchestrate: tool({
93
- description: 'Run the next step of the current cycle. Call with no args on first invocation; call with lastResult={ok,error?} after a dispatch/human_appraise completes. Returns {action, ...} describing what the caller should do next.',
94
- args: {
95
- lastResult: tool.schema.object({
96
- ok: tool.schema.boolean(),
97
- error: tool.schema.string().optional(),
98
- }).optional(),
99
- cycleDef: tool.schema.string().optional().describe('Test-mode cycle definition override (path to cycle file)'),
100
- defaultModel: tool.schema.string().optional().describe('Fallback model for stages with no explicit model in the cycle definition (e.g. "opencode-go/deepseek-v4-flash")'),
101
- },
110
+ description: 'Run the next step of the current cycle. Call with no args on first invocation. After a dispatch or human_appraise, pass lastResult={ok,error?}. After a dispatch_multi (appraise), pass lastResults as an array of {ok,output?,error?} — one entry per completed task. Returns {action, ...} describing what the caller should do next.',
111
+ args: buildOrchestrateArgs(tool),
102
112
 
103
113
  async execute(args, context) {
104
114
  const { runOrchestrate } = await import('../../../scripts/orchestrate.js');
@@ -107,21 +117,9 @@ export function createOrchestrateTool({ tool, pending }) {
107
117
  const secret = readOrCreateSecret(context.worktree);
108
118
 
109
119
  try {
110
- // Branch guard. Kept inline because the orchestrate tool surfaces all errors through its violation
111
- // envelope (see comment on the failed-flow guard below). A
112
- // wrong-branch refusal is a more fundamental error than failed
113
- // flow, so it runs first.
114
120
  const branchGuard = requireOnFlowBranch({ exec: makeExec(cwd) });
115
121
  if (!branchGuard.ok) return JSON.stringify({ error: `foundry_orchestrate: ${branchGuard.error}` });
116
122
 
117
- // Failed-flow guard. Kept inline to preserve the violation envelope.
118
- // because requireNotFailed parses WORK.md frontmatter, which throws
119
- // on malformed YAML. The surrounding try/catch (line 30) converts
120
- // that throw into a violation-shaped envelope per the contract
121
- // exercised by tests/plugin/orchestrate-wrapper.test.js. A guarded()
122
- // wrapper would let the throw escape to a plain { error } envelope
123
- // and break that contract. orchestrate-tool is the one Phase 1.5
124
- // exception to the inline-gate refactor.
125
123
  const failedGuard = requireNotFailed(io);
126
124
  if (!failedGuard.ok) return JSON.stringify({ error: `foundry_orchestrate: ${failedGuard.error}` });
127
125
 
@@ -132,7 +130,9 @@ export function createOrchestrateTool({ tool, pending }) {
132
130
  const result = await runOrchestrate({
133
131
  cwd, cycleDef: args.cycleDef, git, mint, finalize,
134
132
  now: () => Date.now(),
135
- lastResult: args.lastResult ?? null,
133
+ lastResult: args.lastResult,
134
+ lastResults: args.lastResults,
135
+ baseBranch: args.baseBranch,
136
136
  defaultModel: args.defaultModel,
137
137
  }, io);
138
138
 
package/dist/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## [3.5.4] - 2026-05-23
4
+
5
+ ### Fixed
6
+
7
+ - `lastResults` was handled by the orchestration engine but invisible to the tool interface — the schema, description, and execute bridge all omitted it, making the appraise consolidation path unreachable through `foundry_orchestrate`.
8
+ - `baseBranch` was computed by the engine but dropped at the tool boundary.
9
+
10
+ ### Changed
11
+
12
+ - Clarified the commit model in the add-flow skill so agents do not re-check whether config file edits were committed.
13
+
3
14
  ## [3.5.3] - 2026-05-23
4
15
 
5
16
  ### Added
@@ -103,6 +103,8 @@ If the user rejects the plan, return to the Understand phase and adjust.
103
103
 
104
104
  For each dependency, invoke the sub-skill's protocol with the captured context object. The context object for each sub-skill matches the args of the corresponding `foundry_config_create_*` tool, with fields populated from the Understand and Gather phases.
105
105
 
106
+ Each `foundry_config_create_*` tool commits every pending change under `foundry/`, not just the file it creates. If you edit a config file directly between tool calls (for example, to add appraiser configuration to an artefact type after those appraisers are created), the next `foundry_config_create_*` call picks it up. After the final tool call `git status` is always clean — no further checks are needed.
107
+
106
108
  Build order (dependency order):
107
109
 
108
110
  1. **Artefact types**: For each new artefact type, invoke the `add-artefact-type` protocol with the captured context. Example:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@really-knows-ai/foundry",
3
- "version": "3.5.3",
3
+ "version": "3.5.4",
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",