@looplia/looplia-cli 0.7.4 → 0.7.5

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.
@@ -8,6 +8,7 @@ import {
8
8
  applyPreset,
9
9
  buildSummarizePrompt,
10
10
  clearClaudeCodePathCache,
11
+ createBuildHooks,
11
12
  createClaudeAgentExecutor,
12
13
  createQueryLogger,
13
14
  createWorkflowHooks,
@@ -32,7 +33,7 @@ import {
32
33
  validateConfig,
33
34
  writeLoopliaSettings,
34
35
  writeUserProfile
35
- } from "./chunk-PXCY2LDE.js";
36
+ } from "./chunk-GIZRTNY3.js";
36
37
  import "./chunk-VRBGWKZ6.js";
37
38
  import "./chunk-Y55L47HC.js";
38
39
  export {
@@ -43,6 +44,7 @@ export {
43
44
  applyPreset,
44
45
  buildSummarizePrompt,
45
46
  clearClaudeCodePathCache,
47
+ createBuildHooks,
46
48
  createClaudeAgentExecutor,
47
49
  createQueryLogger,
48
50
  createWorkflowHooks,
package/dist/cli.js CHANGED
@@ -1,20 +1,14 @@
1
1
  #!/usr/bin/env bun
2
2
  import {
3
3
  ensureWorkflowSkills,
4
- extractWorkflowSkills,
5
4
  findSkill,
6
- generateValidationManifest,
7
5
  getAvailableSkills,
8
- getFinalStep,
9
6
  getInstalledSkills,
10
7
  installSkill,
11
- isInputlessWorkflow,
12
8
  loadCompiledRegistry,
13
- parseWorkflow,
14
9
  removeSkill,
15
- updateSkill,
16
- validateUserProfile
17
- } from "./chunk-XKLZXCWO.js";
10
+ updateSkill
11
+ } from "./chunk-4TKNQ5RW.js";
18
12
  import "./chunk-QQGRKUSM.js";
19
13
  import {
20
14
  addSource,
@@ -30,22 +24,29 @@ import {
30
24
  PRESETS,
31
25
  applyPreset,
32
26
  copyPlugins,
27
+ createBuildHooks,
33
28
  createClaudeAgentExecutor,
34
29
  createWorkflowHooks,
35
30
  downloadRemotePlugins,
36
31
  ensureWorkspace,
32
+ extractWorkflowSkills,
33
+ generateValidationManifest,
37
34
  getConfigPath,
35
+ getFinalStep,
38
36
  getLoopliaPluginPath,
39
37
  getSettingsDisplayInfo,
40
38
  initializeCommandEnvironment,
39
+ isInputlessWorkflow,
41
40
  isLoopliaInitialized,
42
41
  maskAuthToken,
42
+ parseWorkflow,
43
43
  readLoopliaSettings,
44
44
  readUserProfile,
45
45
  removeLoopliaSettings,
46
+ validateUserProfile,
46
47
  writeLoopliaSettings,
47
48
  writeUserProfile
48
- } from "./chunk-PXCY2LDE.js";
49
+ } from "./chunk-GIZRTNY3.js";
49
50
  import "./chunk-VRBGWKZ6.js";
50
51
  import {
51
52
  copyOutputsToDestination,
@@ -24971,9 +24972,9 @@ init_esm_shims();
24971
24972
 
24972
24973
  // src/commands/build.ts
24973
24974
  init_esm_shims();
24974
- import { existsSync as existsSync3, mkdirSync as mkdirSync2 } from "fs";
24975
+ import { existsSync as existsSync3, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
24975
24976
  import { homedir as homedir2 } from "os";
24976
- import { resolve } from "path";
24977
+ import { join as join2, resolve } from "path";
24977
24978
 
24978
24979
  // src/components/index.ts
24979
24980
  init_esm_shims();
@@ -32871,7 +32872,7 @@ async function* analyzeDescriptionStreaming(description, workspace, questionCall
32871
32872
  const { createSandboxDirectories: createSandboxDirectories2, generateSandboxId: generateSandboxId2 } = await import("./sandbox-XVMNWAJO.js");
32872
32873
  const sandboxId = generateSandboxId2("build");
32873
32874
  createSandboxDirectories2(workspace, sandboxId);
32874
- const { executeInteractiveQueryStreaming } = await import("./claude-agent-sdk-IC25DTKL.js");
32875
+ const { executeInteractiveQueryStreaming } = await import("./claude-agent-sdk-W5MXMV4Q.js");
32875
32876
  const prompt = `${buildAnalysisPrompt(description)} --sandbox-id ${sandboxId}`;
32876
32877
  const generator = executeInteractiveQueryStreaming(
32877
32878
  prompt,
@@ -34118,9 +34119,13 @@ async function executeBatch(prompt, workspace, executor) {
34118
34119
  console.error("\u23F3 Building workflow...");
34119
34120
  const { createSandboxDirectories: createSandboxDirectories2, generateSandboxId: generateSandboxId2 } = await import("./sandbox-XVMNWAJO.js");
34120
34121
  const sandboxId = generateSandboxId2("build");
34122
+ const sandboxDir = join2(workspace, "sandbox", sandboxId);
34121
34123
  createSandboxDirectories2(workspace, sandboxId);
34124
+ createBuildValidationJson(sandboxDir, sandboxId, "untitled");
34125
+ process.env.LOOPLIA_SANDBOX_ID = sandboxId;
34126
+ process.env.LOOPLIA_SANDBOX_ROOT = join2(workspace, "sandbox");
34122
34127
  const promptWithSandbox = `${prompt} --sandbox-id ${sandboxId}`;
34123
- const exec2 = executor ?? createClaudeAgentExecutor({ workspace });
34128
+ const exec2 = executor ?? createClaudeAgentExecutor({ workspace, buildHooks: createBuildHooks() });
34124
34129
  const result = await exec2.executePrompt(promptWithSandbox, {
34125
34130
  workspace,
34126
34131
  contentId: sandboxId
@@ -34128,17 +34133,65 @@ async function executeBatch(prompt, workspace, executor) {
34128
34133
  if (result.success && result.data) {
34129
34134
  return result.data;
34130
34135
  }
34136
+ if (result.success && !result.data) {
34137
+ const validation = readBuildValidationSync(sandboxDir);
34138
+ if (validation?.workflowValidated && validation.workflowPath) {
34139
+ return {
34140
+ status: "success",
34141
+ workflowPath: validation.workflowPath,
34142
+ workflowName: validation.workflowName ?? void 0
34143
+ };
34144
+ }
34145
+ }
34131
34146
  return {
34132
34147
  status: "error",
34133
34148
  error: result.error?.message ?? "Unknown error"
34134
34149
  };
34135
34150
  }
34151
+ function createBuildValidationJson(sandboxDir, sandboxId, workflowName) {
34152
+ const validation = {
34153
+ type: "build",
34154
+ workflow: workflowName,
34155
+ version: "1.0.0",
34156
+ sandboxId,
34157
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
34158
+ status: "building",
34159
+ workflowValidated: false,
34160
+ workflowPath: null,
34161
+ workflowName: null
34162
+ };
34163
+ writeFileSync2(
34164
+ join2(sandboxDir, "validation.json"),
34165
+ JSON.stringify(validation, null, 2),
34166
+ "utf-8"
34167
+ );
34168
+ }
34169
+ function readBuildValidationSync(sandboxDir) {
34170
+ try {
34171
+ const { readFileSync: readFileSync3 } = __require("fs");
34172
+ const content = readFileSync3(
34173
+ join2(sandboxDir, "validation.json"),
34174
+ "utf-8"
34175
+ );
34176
+ const manifest = JSON.parse(content);
34177
+ if (manifest.type === "build") {
34178
+ return manifest;
34179
+ }
34180
+ return;
34181
+ } catch {
34182
+ return;
34183
+ }
34184
+ }
34136
34185
  async function* executeInteractiveStreamingBatch(prompt, workspace, questionCallback) {
34137
34186
  const { createSandboxDirectories: createSandboxDirectories2, generateSandboxId: generateSandboxId2 } = await import("./sandbox-XVMNWAJO.js");
34138
34187
  const sandboxId = generateSandboxId2("build");
34188
+ const sandboxDir = join2(workspace, "sandbox", sandboxId);
34139
34189
  createSandboxDirectories2(workspace, sandboxId);
34190
+ createBuildValidationJson(sandboxDir, sandboxId, "untitled");
34191
+ process.env.LOOPLIA_SANDBOX_ID = sandboxId;
34192
+ process.env.LOOPLIA_SANDBOX_ROOT = join2(workspace, "sandbox");
34140
34193
  const promptWithSandbox = `${prompt} --sandbox-id ${sandboxId}`;
34141
- const { executeInteractiveQueryStreaming } = await import("./claude-agent-sdk-IC25DTKL.js");
34194
+ const { executeInteractiveQueryStreaming } = await import("./claude-agent-sdk-W5MXMV4Q.js");
34142
34195
  const schema = {
34143
34196
  type: "object",
34144
34197
  properties: {
@@ -34152,7 +34205,7 @@ async function* executeInteractiveStreamingBatch(prompt, workspace, questionCall
34152
34205
  const generator = executeInteractiveQueryStreaming(
34153
34206
  promptWithSandbox,
34154
34207
  schema,
34155
- { workspace },
34208
+ { workspace, buildHooks: createBuildHooks() },
34156
34209
  questionCallback
34157
34210
  );
34158
34211
  let iterResult = await generator.next();
@@ -34161,6 +34214,19 @@ async function* executeInteractiveStreamingBatch(prompt, workspace, questionCall
34161
34214
  iterResult = await generator.next();
34162
34215
  }
34163
34216
  const executorResult = iterResult.value;
34217
+ if (executorResult.success && !executorResult.data) {
34218
+ const validation = readBuildValidationSync(sandboxDir);
34219
+ if (validation?.workflowValidated && validation.workflowPath) {
34220
+ return {
34221
+ success: true,
34222
+ data: {
34223
+ status: "success",
34224
+ workflowPath: validation.workflowPath,
34225
+ workflowName: validation.workflowName ?? void 0
34226
+ }
34227
+ };
34228
+ }
34229
+ }
34164
34230
  if (executorResult.success) {
34165
34231
  return {
34166
34232
  success: true,
@@ -34789,7 +34855,7 @@ async function runConfigCommand(args) {
34789
34855
 
34790
34856
  // src/commands/init.ts
34791
34857
  init_esm_shims();
34792
- import { dirname, join as join2 } from "path";
34858
+ import { dirname, join as join3 } from "path";
34793
34859
  import { createInterface } from "readline";
34794
34860
  import { fileURLToPath } from "url";
34795
34861
 
@@ -34799,7 +34865,7 @@ init_esm_shims();
34799
34865
  // src/commands/init.ts
34800
34866
  function getCliBundledPluginsPath() {
34801
34867
  const currentFile = typeof __dirname !== "undefined" ? __dirname : dirname(fileURLToPath(import.meta.url));
34802
- return join2(currentFile, "..", "plugins");
34868
+ return join3(currentFile, "..", "plugins");
34803
34869
  }
34804
34870
  function printInitHelp() {
34805
34871
  console.log(`
@@ -35109,10 +35175,10 @@ import {
35109
35175
  existsSync as existsSync4,
35110
35176
  mkdirSync as mkdirSync3,
35111
35177
  readFileSync as readFileSync2,
35112
- writeFileSync as writeFileSync2
35178
+ writeFileSync as writeFileSync3
35113
35179
  } from "fs";
35114
35180
  import { homedir as homedir3 } from "os";
35115
- import { basename, join as join3, resolve as resolve2 } from "path";
35181
+ import { basename, join as join4, resolve as resolve2 } from "path";
35116
35182
  var RUN_COMMAND = COMMANDS.RUN;
35117
35183
  function generateSandboxIdFromFile(filePath) {
35118
35184
  const filename = basename(filePath, ".md");
@@ -35129,8 +35195,8 @@ function createInitialValidationJson(sandboxDir, sandboxId, workflowId) {
35129
35195
  status: "pending",
35130
35196
  steps: {}
35131
35197
  };
35132
- writeFileSync2(
35133
- join3(sandboxDir, "validation.json"),
35198
+ writeFileSync3(
35199
+ join4(sandboxDir, "validation.json"),
35134
35200
  JSON.stringify(validation, null, 2),
35135
35201
  "utf-8"
35136
35202
  );
@@ -35142,7 +35208,7 @@ function createSandbox(workspace, filePath, workflowId) {
35142
35208
  const absolutePath = resolve2(filePath);
35143
35209
  copyFileSync(
35144
35210
  absolutePath,
35145
- join3(sandboxDir, "inputs", SANDBOX_CONTENT_FILENAME)
35211
+ join4(sandboxDir, "inputs", SANDBOX_CONTENT_FILENAME)
35146
35212
  );
35147
35213
  createInitialValidationJson(sandboxDir, sandboxId, workflowId);
35148
35214
  } catch (error) {
@@ -35160,8 +35226,8 @@ function createSandboxWithInputs(workspace, workflowId, inputs) {
35160
35226
  const sandboxDir = createSandboxDirectories(workspace, sandboxId);
35161
35227
  for (const [name, parsedInput] of Object.entries(inputs)) {
35162
35228
  if (parsedInput.type === "json") {
35163
- writeFileSync2(
35164
- join3(sandboxDir, "inputs", `${name}.json`),
35229
+ writeFileSync3(
35230
+ join4(sandboxDir, "inputs", `${name}.json`),
35165
35231
  parsedInput.value,
35166
35232
  "utf-8"
35167
35233
  );
@@ -35170,7 +35236,7 @@ function createSandboxWithInputs(workspace, workflowId, inputs) {
35170
35236
  if (!existsSync4(absolutePath)) {
35171
35237
  throw new Error(`Input file not found: ${parsedInput.value}`);
35172
35238
  }
35173
- copyFileSync(absolutePath, join3(sandboxDir, "inputs", `${name}.md`));
35239
+ copyFileSync(absolutePath, join4(sandboxDir, "inputs", `${name}.md`));
35174
35240
  }
35175
35241
  }
35176
35242
  createInitialValidationJson(sandboxDir, sandboxId, workflowId);
@@ -35343,7 +35409,7 @@ function ensureWorkspace3(mock) {
35343
35409
  const workspace = getWorkspacePath2();
35344
35410
  if (!existsSync4(workspace)) {
35345
35411
  if (mock) {
35346
- mkdirSync3(join3(workspace, "sandbox"), { recursive: true });
35412
+ mkdirSync3(join4(workspace, "sandbox"), { recursive: true });
35347
35413
  } else {
35348
35414
  console.error("Workspace not initialized. Run: looplia init");
35349
35415
  process.exit(1);
@@ -35355,7 +35421,7 @@ function buildRunPrompt(workflowId, sandboxId) {
35355
35421
  return `${RUN_COMMAND} ${workflowId} --sandbox-id ${sandboxId}`;
35356
35422
  }
35357
35423
  function parseWorkflowFile(workspace, workflowId) {
35358
- const workflowPath = join3(workspace, "workflows", `${workflowId}.md`);
35424
+ const workflowPath = join4(workspace, "workflows", `${workflowId}.md`);
35359
35425
  if (!existsSync4(workflowPath)) {
35360
35426
  return null;
35361
35427
  }
@@ -35438,7 +35504,7 @@ async function executeBatch2(prompt, workspace, workflowId, requiredSkills) {
35438
35504
  }
35439
35505
  function resolveSandboxId(workspace, parsed, allowInputless) {
35440
35506
  if (parsed.sandboxId) {
35441
- const sandboxDir = join3(workspace, "sandbox", parsed.sandboxId);
35507
+ const sandboxDir = join4(workspace, "sandbox", parsed.sandboxId);
35442
35508
  if (!existsSync4(sandboxDir)) {
35443
35509
  console.error(`Error: Sandbox not found: ${parsed.sandboxId}`);
35444
35510
  console.error(`Path: ${sandboxDir}`);
@@ -35541,8 +35607,8 @@ function populateValidationManifest(workspace, sandboxId, workflowId, workflowIn
35541
35607
  }
35542
35608
  const manifest = generateValidationManifest(workflowInfo.parsed.definition);
35543
35609
  const finalStepId = getFinalStep(workflowInfo.parsed.definition);
35544
- const sandboxDir = join3(workspace, "sandbox", sandboxId);
35545
- const validationPath = join3(sandboxDir, "validation.json");
35610
+ const sandboxDir = join4(workspace, "sandbox", sandboxId);
35611
+ const validationPath = join4(sandboxDir, "validation.json");
35546
35612
  if (!existsSync4(validationPath)) {
35547
35613
  createInitialValidationJson(sandboxDir, sandboxId, workflowId);
35548
35614
  }
@@ -35554,7 +35620,7 @@ function populateValidationManifest(workspace, sandboxId, workflowId, workflowIn
35554
35620
  );
35555
35621
  existing.steps = manifest.steps;
35556
35622
  existing.finalStepId = finalStepId;
35557
- writeFileSync2(validationPath, JSON.stringify(existing, null, 2), "utf-8");
35623
+ writeFileSync3(validationPath, JSON.stringify(existing, null, 2), "utf-8");
35558
35624
  }
35559
35625
  async function runRunCommand(args) {
35560
35626
  const parsed = parseArgs3(args);
@@ -35573,7 +35639,7 @@ async function runRunCommand(args) {
35573
35639
  const allowInputless = workflowInfo?.isInputless ?? false;
35574
35640
  const sandboxId = resolveSandboxId(workspace, parsed, allowInputless);
35575
35641
  process.env.LOOPLIA_SANDBOX_ID = sandboxId;
35576
- process.env.LOOPLIA_SANDBOX_ROOT = join3(workspace, "sandbox");
35642
+ process.env.LOOPLIA_SANDBOX_ROOT = join4(workspace, "sandbox");
35577
35643
  populateValidationManifest(
35578
35644
  workspace,
35579
35645
  sandboxId,
@@ -35678,7 +35744,7 @@ async function skillAdd(nameOrUrl, from) {
35678
35744
  }
35679
35745
  if (GITHUB_URL_PATTERN.test(nameOrUrl)) {
35680
35746
  console.log(`Installing skill from URL: ${nameOrUrl}...`);
35681
- const { installSkillFromUrl } = await import("./dist-LKL7WJ7K.js");
35747
+ const { installSkillFromUrl } = await import("./dist-3XSIQAV3.js");
35682
35748
  const result2 = await installSkillFromUrl(nameOrUrl, true);
35683
35749
  switch (result2.status) {
35684
35750
  case "installed":
@@ -35915,7 +35981,7 @@ async function runSkillCommand(args) {
35915
35981
  }
35916
35982
 
35917
35983
  // src/index.ts
35918
- var VERSION = "0.7.4";
35984
+ var VERSION = "0.7.5";
35919
35985
  function printHelp5() {
35920
35986
  console.log(`
35921
35987
  looplia - Content intelligence CLI (v${VERSION})
@@ -11,7 +11,7 @@ import {
11
11
  loadCompiledRegistry,
12
12
  removeSkill,
13
13
  updateSkill
14
- } from "./chunk-XKLZXCWO.js";
14
+ } from "./chunk-4TKNQ5RW.js";
15
15
  import {
16
16
  syncRegistrySources,
17
17
  syncSource
@@ -32,7 +32,7 @@ import {
32
32
  CORE_SKILLS,
33
33
  ensureWorkspace,
34
34
  isCoreSkill
35
- } from "./chunk-PXCY2LDE.js";
35
+ } from "./chunk-GIZRTNY3.js";
36
36
  import "./chunk-VRBGWKZ6.js";
37
37
  import "./chunk-Y55L47HC.js";
38
38
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@looplia/looplia-cli",
3
- "version": "0.7.4",
3
+ "version": "0.7.5",
4
4
  "description": "Looplia CLI - AI-powered workflow automation tool",
5
5
  "type": "module",
6
6
  "license": "Elastic-2.0",
@@ -26,6 +26,29 @@ Use this skill when:
26
26
 
27
27
  ---
28
28
 
29
+ ## ⚠️ CRITICAL EXECUTION MODEL - READ FIRST
30
+
31
+ **YOU (the model reading this skill) must execute the step loop directly. DO NOT delegate.**
32
+
33
+ ```
34
+ ┌─────────────────────────────────────────────────────────────────────┐
35
+ │ YOU (main agent) iterate through steps, making ONE Task call each │
36
+ │ │
37
+ │ FOR step IN workflow.steps: │
38
+ │ 1. Call Task(general-purpose) for THIS STEP ONLY │
39
+ │ 2. WAIT for Task to complete │
40
+ │ 3. Validate output │
41
+ │ 4. THEN move to next step │
42
+ │ │
43
+ │ ❌ WRONG: Task("Execute all workflow steps...") │
44
+ │ ✅ RIGHT: Task("Execute step: summary"), Task("Execute step: ideas")│
45
+ └─────────────────────────────────────────────────────────────────────┘
46
+ ```
47
+
48
+ **3 steps = 3 Task calls. You MUST make 3 separate Task tool invocations.**
49
+
50
+ ---
51
+
29
52
  ## CRITICAL: Task Invocation with general-purpose Subagent
30
53
 
31
54
  **v0.6.9:** Using built-in `general-purpose` subagent for ALL workflow steps (all providers).
@@ -76,25 +99,37 @@ Each `Task(general-purpose)` creates a **separate context window**:
76
99
 
77
100
  **NEVER batch multiple steps** - this defeats context isolation.
78
101
 
79
- ### Anti-Patterns
102
+ ### Anti-Patterns (VIOLATIONS = TEST FAILURE)
80
103
 
81
- ❌ **WRONG - Delegating entire workflow:**
104
+ ❌ **FATAL ERROR - Delegating entire workflow to one Task:**
82
105
  ```json
83
106
  {
84
107
  "description": "Execute workflow: writing-kit",
85
108
  "prompt": "Run all workflow steps..."
86
109
  }
87
110
  ```
88
- This pollutes the subagent context with ALL steps.
111
+ **This is WRONG.** You made 1 Task call. Tests expect 3. TEST WILL FAIL.
89
112
 
90
- **CORRECT - One step per Task:**
91
- ```json
92
- {
93
- "description": "Execute step: summary",
94
- "prompt": "Execute skill 'media-reviewer' for step 'summary'..."
95
- }
113
+ **FATAL ERROR - Executing skills inline without Task:**
96
114
  ```
97
- Each step gets a fresh, focused context window.
115
+ Skill("media-reviewer") // NO! You must use Task wrapper
116
+ Skill("idea-synthesis") // NO! You must use Task wrapper
117
+ ```
118
+ **This is WRONG.** Each step MUST be wrapped in a Task call.
119
+
120
+ ✅ **CORRECT - One Task call per step (3 steps = 3 Task calls):**
121
+ ```
122
+ Task("Execute step: summary") // Task #1
123
+ → Subagent invokes Skill("media-reviewer")
124
+
125
+ Task("Execute step: ideas") // Task #2
126
+ → Subagent invokes Skill("idea-synthesis")
127
+
128
+ Task("Execute step: writing-kit") // Task #3
129
+ → Subagent invokes Skill("writing-kit-assembler")
130
+ ```
131
+
132
+ **Verification**: Count your Task tool calls. If workflow has 3 steps, you MUST have 3 Task calls.
98
133
 
99
134
  ---
100
135
 
@@ -243,18 +278,38 @@ Input:
243
278
  Computed order: [analyze-content, generate-ideas, build-writing-kit]
244
279
  ```
245
280
 
246
- ### Phase 5: Step Execution Loop
281
+ ### Phase 5: Step Execution Loop (YOU MUST DO THIS)
282
+
283
+ **YOU execute this loop. DO NOT delegate the loop to a subagent.**
247
284
 
248
- **Execute steps ONE AT A TIME (context isolation):**
285
+ ```
286
+ YOU (main agent) must:
287
+ ┌────────────────────────────────────────────────────────────────┐
288
+ │ for (const step of steps) { │
289
+ │ // 1. YOU call Task tool │
290
+ │ await Task({ │
291
+ │ subagent_type: "general-purpose", │
292
+ │ description: `Execute step: ${step.id}`, │
293
+ │ prompt: `Execute skill '${step.skill}' for step...` │
294
+ │ }); │
295
+ │ │
296
+ │ // 2. YOU wait for Task to complete │
297
+ │ // 3. YOU validate output │
298
+ │ // 4. YOU update validation.json │
299
+ │ // 5. YOU move to next step │
300
+ │ } │
301
+ └────────────────────────────────────────────────────────────────┘
302
+ ```
249
303
 
304
+ **Execution checklist:**
250
305
  1. Get first unvalidated step from dependency order
251
- 2. Make ONE `Task(general-purpose)` call for THIS step only
252
- 3. WAIT for Task completion before proceeding
253
- 4. Validate output, update validation.json
254
- 5. REPEAT for next unvalidated step
255
- 6. STOP when ALL steps are validated
306
+ 2. **YOU** make ONE `Task(general-purpose)` call for THIS step only
307
+ 3. **YOU** WAIT for Task completion before proceeding
308
+ 4. **YOU** validate output, update validation.json
309
+ 5. **YOU** REPEAT for next unvalidated step
310
+ 6. **YOU** STOP when ALL steps are validated
256
311
 
257
- **MANDATORY:** Each step = separate context window = separate Task call.
312
+ **MANDATORY:** 3 steps = 3 Task calls. Count them. If you made fewer, you did it wrong.
258
313
 
259
314
  ```
260
315
  FOR EACH step in dependency order: