@xelth/eck-snapshot 5.9.0 → 6.0.1

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.

Potentially problematic release.


This version of @xelth/eck-snapshot might be problematic. Click here for more details.

@@ -1,15 +1,16 @@
1
- import fs from 'fs/promises';
2
- import path from 'path';
3
- import ora from 'ora';
4
- import chalk from 'chalk';
5
- import isBinaryPath from 'is-binary-path';
6
- import { getGitAnchor, getChangedFiles } from '../../utils/gitUtils.js';
7
- import { loadSetupConfig } from '../../config.js';
8
- import { readFileWithSizeCheck, parseSize, formatSize, matchesPattern, loadGitignore, generateTimestamp, getShortRepoName } from '../../utils/fileUtils.js';
9
- import { detectProjectType, getProjectSpecificFiltering } from '../../utils/projectDetector.js';
10
- import { execa } from 'execa';
11
- import { fileURLToPath } from 'url';
12
- import { pushTelemetry } from '../../utils/telemetry.js';
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ import ora from 'ora';
4
+ import chalk from 'chalk';
5
+ import isBinaryPath from 'is-binary-path';
6
+ import { getGitAnchor, getChangedFiles } from '../../utils/gitUtils.js';
7
+ import { loadSetupConfig } from '../../config.js';
8
+ import { readFileWithSizeCheck, parseSize, formatSize, matchesPattern, loadGitignore, generateTimestamp, getShortRepoName } from '../../utils/fileUtils.js';
9
+ import { detectProjectType, getProjectSpecificFiltering } from '../../utils/projectDetector.js';
10
+ import { execa } from 'execa';
11
+ import { fileURLToPath } from 'url';
12
+ import { pushTelemetry } from '../../utils/telemetry.js';
13
+ import { syncTokenWeights } from '../../utils/tokenEstimator.js';
13
14
 
14
15
  // Mirror the same hidden-path guard used in createSnapshot.js
15
16
  function isHiddenPath(filePath) {
@@ -42,52 +43,95 @@ async function generateSnapshotContent(repoPath, changedFiles, anchor, config, g
42
43
  let includedCount = 0;
43
44
  const fileList = [];
44
45
 
45
- // Include Agent Report if it exists and hasn't been embedded yet
46
- let agentReport = null;
47
- const reportPath = path.join(repoPath, '.eck', 'lastsnapshot', 'AnswerToSA.md');
48
- try {
49
- const reportContent = await fs.readFile(reportPath, 'utf-8');
50
- if (!reportContent.includes('[SYSTEM: EMBEDDED]')) {
51
- agentReport = reportContent;
52
- await fs.appendFile(reportPath, '\n\n[SYSTEM: EMBEDDED]\n', 'utf-8');
53
- }
54
- } catch (e) { /* File not found or unreadable */ }
46
+ // Include Agent Report if it exists and hasn't been embedded yet
47
+ let agentReport = null;
48
+ const reportPath = path.join(repoPath, '.eck', 'lastsnapshot', 'AnswerToSA.md');
49
+ const lockPath = path.join(repoPath, '.eck', 'lastsnapshot', 'AnswerToSA.lock');
50
+ try {
51
+ // Use atomic directory creation as a lock to prevent race conditions
52
+ await fs.mkdir(lockPath);
53
+ const reportContent = await fs.readFile(reportPath, 'utf-8');
54
+
55
+ if (!reportContent.includes('[SYSTEM: EMBEDDED]')) {
56
+ agentReport = reportContent;
57
+
58
+ // Immediately mark as embedded to release the race window
59
+ await fs.appendFile(reportPath, '\n\n[SYSTEM: EMBEDDED]\n', 'utf-8');
60
+
61
+ // Auto-Journaling: prepend agent report to JOURNAL.md
62
+ const journalPath = path.join(repoPath, '.eck', 'JOURNAL.md');
63
+ try {
64
+ const dateStr = new Date().toISOString().split('T')[0];
65
+ const journalEntry = `## ${dateStr} — Agent Report\n\n${reportContent.trim()}\n`;
66
+
67
+ let existingJournal = '';
68
+ try {
69
+ existingJournal = await fs.readFile(journalPath, 'utf-8');
70
+ } catch (e) { /* might not exist */ }
71
+
72
+ const insertPos = existingJournal.indexOf('\n## ');
73
+ if (insertPos !== -1) {
74
+ const newJournal = existingJournal.slice(0, insertPos) + '\n\n' + journalEntry + existingJournal.slice(insertPos);
75
+ await fs.writeFile(journalPath, newJournal, 'utf-8');
76
+ } else {
77
+ await fs.writeFile(journalPath, (existingJournal ? existingJournal + '\n\n' : '') + journalEntry + '\n', 'utf-8');
78
+ }
79
+ } catch (je) {
80
+ console.warn('Could not auto-update JOURNAL.md', je.message);
81
+ }
82
+ }
83
+ await fs.rmdir(lockPath);
84
+ } catch (e) {
85
+ // File not found or locked by another process
86
+ try { await fs.rmdir(lockPath); } catch (_) {}
87
+ }
55
88
 
56
89
  const cleanDirsToIgnore = (config.dirsToIgnore || []).map(d => d.replace(/\/$/, ''));
57
90
 
58
- for (const filePath of changedFiles) {
59
- const normalizedPath = filePath.replace(/\\/g, '/');
60
-
61
- // Skip hidden paths (.idea/, .vscode/, etc.) — mirrors createSnapshot.js
62
- if (isHiddenPath(normalizedPath)) continue;
63
-
64
- // Skip binary files — mirrors createSnapshot.js
65
- if (isBinaryPath(filePath)) continue;
66
-
67
- const pathParts = normalizedPath.split('/');
68
- let isIgnoredDir = false;
69
- for (let i = 0; i < pathParts.length - 1; i++) {
70
- if (cleanDirsToIgnore.includes(pathParts[i])) {
71
- isIgnoredDir = true;
72
- break;
73
- }
74
- }
75
- if (isIgnoredDir) continue;
76
-
77
- const fileExt = path.extname(filePath);
78
- // Use matchesPattern (glob support) instead of exact includes() — mirrors createSnapshot.js
79
- if (config.filesToIgnore && matchesPattern(normalizedPath, config.filesToIgnore)) continue;
80
- if (fileExt && config.extensionsToIgnore?.includes(fileExt)) continue;
81
- if (gitignore.ignores(normalizedPath)) continue;
82
-
83
- try {
84
- const fullPath = path.join(repoPath, filePath);
85
- const content = await readFileWithSizeCheck(fullPath, parseSize(config.maxFileSize));
86
- contentOutput += `--- File: /${normalizedPath} ---\n\n${content}\n\n`;
87
- fileList.push(`- ${normalizedPath}`);
88
- includedCount++;
89
- } catch (e) { /* Skip */ }
90
- }
91
+ for (const filePath of changedFiles) {
92
+ const normalizedPath = filePath.replace(/\\/g, '/');
93
+
94
+ // Skip hidden paths (.idea/, .vscode/, etc.) — mirrors createSnapshot.js
95
+ if (isHiddenPath(normalizedPath)) continue;
96
+
97
+ // Skip binary files — mirrors createSnapshot.js
98
+ if (isBinaryPath(filePath)) continue;
99
+
100
+ const pathParts = normalizedPath.split('/');
101
+ let isIgnoredDir = false;
102
+ for (let i = 0; i < pathParts.length - 1; i++) {
103
+ if (cleanDirsToIgnore.includes(pathParts[i])) {
104
+ isIgnoredDir = true;
105
+ break;
106
+ }
107
+ }
108
+ if (isIgnoredDir) continue;
109
+
110
+ const fileExt = path.extname(filePath);
111
+ // Use matchesPattern (glob support) instead of exact includes() — mirrors createSnapshot.js
112
+ if (config.filesToIgnore && matchesPattern(normalizedPath, config.filesToIgnore)) continue;
113
+ if (fileExt && config.extensionsToIgnore?.includes(fileExt)) continue;
114
+ if (gitignore.ignores(normalizedPath)) continue;
115
+
116
+ try {
117
+ const fullPath = path.join(repoPath, filePath);
118
+
119
+ // Explicitly check if file was deleted
120
+ try {
121
+ await fs.access(fullPath);
122
+ } catch (accessErr) {
123
+ contentOutput += `--- File: /${normalizedPath} ---\n\n[FILE DELETED]\n\n`;
124
+ fileList.push(`- ${normalizedPath} (Deleted)`);
125
+ includedCount++;
126
+ continue;
127
+ }
128
+
129
+ const content = await readFileWithSizeCheck(fullPath, parseSize(config.maxFileSize));
130
+ contentOutput += `--- File: /${normalizedPath} ---\n\n${content}\n\n`;
131
+ fileList.push(`- ${normalizedPath} (Modified/Added)`);
132
+ includedCount++;
133
+ } catch (e) { /* Skip */ }
134
+ }
91
135
 
92
136
  // Load Template
93
137
  const templatePath = path.join(__dirname, '../../templates/update-prompt.template.md');
@@ -122,17 +166,22 @@ export async function updateSnapshot(repoPath, options) {
122
166
  }
123
167
 
124
168
  // Auto-commit any uncommitted changes so they appear in the diff
125
- const didCommit = await autoCommit(repoPath);
126
- if (didCommit) {
127
- spinner.info('Auto-committed uncommitted changes.');
128
- spinner.start('Generating update snapshot...');
169
+ let didCommit = false;
170
+ if (!options.fail) {
171
+ didCommit = await autoCommit(repoPath);
172
+ if (didCommit) {
173
+ spinner.info('Auto-committed uncommitted changes.');
174
+ }
175
+ } else {
176
+ spinner.info('Fail flag passed: skipping auto-commit.');
129
177
  }
178
+ spinner.start('Generating update snapshot...');
130
179
 
131
- const changedFiles = await getChangedFiles(repoPath, anchor);
132
- if (changedFiles.length === 0) {
133
- spinner.succeed('No changes detected since last full snapshot.');
134
- return;
135
- }
180
+ const changedFiles = await getChangedFiles(repoPath, anchor, options.fail);
181
+ if (changedFiles.length === 0) {
182
+ spinner.succeed('No changes detected since last full snapshot.');
183
+ return;
184
+ }
136
185
 
137
186
  const setupConfig = await loadSetupConfig();
138
187
  let config = { ...setupConfig.fileFiltering, ...setupConfig.performance, ...options };
@@ -216,7 +265,7 @@ export async function updateSnapshot(repoPath, options) {
216
265
  }
217
266
 
218
267
  // New Silent/JSON command for Agents
219
- export async function updateSnapshotJson(repoPath) {
268
+ export async function updateSnapshotJson(repoPath, options = {}) {
220
269
  try {
221
270
  const anchor = await getGitAnchor(repoPath);
222
271
  if (!anchor) {
@@ -225,9 +274,11 @@ export async function updateSnapshotJson(repoPath) {
225
274
  }
226
275
 
227
276
  // Auto-commit any uncommitted changes
228
- await autoCommit(repoPath);
277
+ if (!options.fail) {
278
+ await autoCommit(repoPath);
279
+ }
229
280
 
230
- const changedFiles = await getChangedFiles(repoPath, anchor);
281
+ const changedFiles = await getChangedFiles(repoPath, anchor, !!options.fail);
231
282
  if (changedFiles.length === 0) {
232
283
  console.log(JSON.stringify({ status: "no_changes", message: "No changes detected" }));
233
284
  return;
@@ -294,15 +345,16 @@ export async function updateSnapshotJson(repoPath) {
294
345
  }
295
346
  // --------------------------------------------
296
347
 
297
- console.log(JSON.stringify({
298
- status: "success",
299
- snapshot_file: `.eck/snapshots/${outputFilename}`,
300
- files_count: includedCount,
301
- timestamp: timestamp
302
- }));
303
-
304
- // Auto-push telemetry (fire and forget so it doesn't break JSON output)
305
- pushTelemetry(repoPath, true).catch(() => {});
348
+ console.log(JSON.stringify({
349
+ status: "success",
350
+ snapshot_file: `.eck/snapshots/${outputFilename}`,
351
+ files_count: includedCount,
352
+ timestamp: timestamp
353
+ }));
354
+
355
+ // Auto-push telemetry and sync weights (fire and forget so it doesn't break JSON output)
356
+ pushTelemetry(repoPath, true).catch(() => {});
357
+ syncTokenWeights(true).catch(() => {});
306
358
 
307
359
  } catch (error) {
308
360
  console.log(JSON.stringify({ status: "error", message: error.message }));
@@ -4,18 +4,25 @@
4
4
  You are an Expert Developer. The architecture is already decided. Your job is to **execute**, **fix**, and **polish**.
5
5
 
6
6
  ## DEFINITION OF DONE (CRITICAL)
7
- When the task is complete:
8
- 1. **WRITE** your report to \`.eck/lastsnapshot/AnswerToSA.md\` (overwrite, not append). Use this exact format:
9
- ```markdown
10
- # Report: [Task Name]
11
- **Executor:** [Your Exact Model Name, e.g., GLM-4.7 (OpenCode)]
12
- **Status:** [SUCCESS / BLOCKED / FAILED]
13
- **Changes:**
14
- - Modified X
15
- ```
16
- 2. **Use the \`eck_finish_task\` tool** to commit and sync context.
17
- - This tool automatically creates a git commit and generates a delta snapshot
18
- 3. **DO NOT** use raw git commands for the final commit.
7
+ When task is complete, you must report back and sync context.
8
+
9
+ **OPTION A: Using MCP Tool (Recommended)**
10
+ Call the \`eck_finish_task\` tool. Pass your detailed markdown report into the \`status\` argument.
11
+ - The tool will automatically write the report to \`AnswerToSA.md\`, commit, and generate a snapshot.
12
+ - **DO NOT** manually write to \`AnswerToSA.md\` with your file editing tools (it will fail safety checks).
13
+ - **WARNING: USE ONLY ONCE.** Do not use \`eck_finish_task\` for intermediate testing. It spams snapshot history.
14
+
15
+ **OPTION B: Manual CLI (Fallback)**
16
+ If the MCP tool is unavailable:
17
+ 1. **READ** \`.eck/lastsnapshot/AnswerToSA.md\` using your \`Read\` tool (REQUIRED by safety rules before overwriting).
18
+ 2. **WRITE** your report to that file.
19
+ 3. Run \`eck-snapshot update\` in terminal.
20
+
21
+ ## PROJECT CONTEXT (.eck DIRECTORY)
22
+ The `.eck/` directory contains critical project documentation. **Before starting your task, you MUST:**
23
+ 1. List the files in the `.eck/` directory.
24
+ 2. Read any files that might be relevant to your task based on their names (e.g., `CONTEXT.md`, `TECH_DEBT.md`, `OPERATIONS.md`).
25
+ 3. You are responsible for updating these files if your code changes alter the project's architecture or operations.
19
26
 
20
27
  ## CONTEXT
21
28
  - The GLM ZAI swarm might have struggled or produced code that needs refinement.
@@ -23,7 +30,9 @@ When the task is complete:
23
30
  - You have full permission to edit files directly.
24
31
 
25
32
  ## WORKFLOW
26
- 1. Read the code.
27
- 2. Fix the bugs / Implement the feature.
28
- 3. Verify functionality (Run tests!).
29
- 4. **Loop:** If verification fails, fix it immediately. Do not ask for permission.
33
+ 1. Check the `.eck/RUNTIME_STATE.md` and verify actual running processes.
34
+ 2. Read the code. If the Architect's hypothesis is wrong, discard it and find the real bug.
35
+ 3. Fix the bugs / Implement the feature.
36
+ 4. Verify functionality manually via browser/curl/logs/DB checks.
37
+ 5. **Loop:** If verification fails, fix it immediately. Do not ask for permission.
38
+ 6. **Blocked?** Use the `eck_fail_task` tool to abort safely without committing broken code.
@@ -3,13 +3,17 @@
3
3
  ## 1. PROJECT MODE ACTIVE
4
4
  You are operating in **Project Mode** inside OpenCode. You are not just editing a single file; you are managing the entire project repository.
5
5
  - **Source of Truth:** The file system is your source of truth.
6
- - **Documentation:** The `.eck/` directory contains project context. READ filenames to understand what is available.
7
6
  - **Directory Structure:**
8
7
  ```
9
8
  {{tree}}
10
9
  ```
11
10
 
12
- ## 2. SWARM DELEGATION PROTOCOL (TOKEN ECONOMY)
11
+ ## 2. PROJECT CONTEXT (.eck DIRECTORY)
12
+ The `.eck/` directory is your brain externalized. **Before taking action:**
13
+ - Read the files in `.eck/` (like `CONTEXT.md`, `ROADMAP.md`, `TECH_DEBT.md`) to understand the rules and current state.
14
+ - Update these manifests if the architecture or roadmap changes.
15
+
16
+ ## 3. SWARM DELEGATION PROTOCOL (TOKEN ECONOMY)
13
17
 
14
18
  ### A. Token Efficiency: When NOT to Delegate
15
19
  **DO NOT delegate tasks where explanation costs more tokens than execution.**
@@ -29,28 +33,37 @@ For bulk work where delegation saves YOUR expensive context window, YOU MUST del
29
33
  - Generating boilerplate code
30
34
  * **Action:** Use `glm_zai_backend`, `glm_zai_frontend`, `glm_zai_qa`, or `glm_zai_refactor`.
31
35
 
32
- ## 3. DEFINITION OF DONE (CRITICAL)
33
- When you have completed your coding task and verified it works:
34
- 1. **DO NOT** run `git commit` manually.
35
- 2. **DO NOT** just say "I'm done".
36
- 3. **Use the `eck_finish_task` tool** to finalize the task.
37
- - This tool automatically:
38
- - Updates `.eck/lastsnapshot/AnswerToSA.md` with your status
39
- - Creates a proper git commit
40
- - Generates a delta snapshot (`eck-snapshot update-auto`) for context sync
36
+ ## 4. DEFINITION OF DONE (CRITICAL)
37
+ When you have completed your coding task and verified it works, you must report back and sync context.
38
+
39
+ **OPTION A: Using MCP Tool (Recommended)**
40
+ Call the \`eck_finish_task\` tool. Pass your detailed markdown report into the \`status\` argument.
41
+ - The tool will automatically write the report to \`AnswerToSA.md\`, commit, and generate a snapshot.
42
+ - **DO NOT** manually write to \`AnswerToSA.md\` with your file editing tools.
43
+ - **WARNING: USE ONLY ONCE.** Do not use \`eck_finish_task\` for intermediate testing. It spams snapshot history.
44
+
45
+ **OPTION B: Manual CLI (Fallback)**
46
+ If the MCP tool is unavailable:
47
+ 1. **READ** \`.eck/lastsnapshot/AnswerToSA.md\` using your \`Read\` tool (REQUIRED by safety rules before overwriting).
48
+ 2. **WRITE** your report to that file.
49
+ 3. Run \`eck-snapshot update\` in terminal.
50
+ 4. If you are entirely blocked, use the \`eck_fail_task\` tool.
41
51
 
42
- ## 4. SWARM ERROR RECOVERY & THE RALPH LOOP
52
+ ## 5. SWARM ERROR RECOVERY & THE RALPH LOOP
43
53
  **Core Directive:** You are "deterministically persistent". Failures are expected, giving up is not.
44
54
 
45
- 1. **Iterative Correction:**
46
- * If a build fails or tests turn red: **DO NOT STOP**.
55
+ 1. **Runtime Context & Critical Thinking:**
56
+ * Always check `.eck/RUNTIME_STATE.md` before coding.
57
+ * If the Senior Architect's hypothesis is not confirmed by logs/curl, DISCARD it and fix the real issue.
58
+ 2. **Iterative Correction:**
59
+ * Verify via browser/curl/logs. If it fails: **DO NOT STOP**.
47
60
  * **Read** the error message, **Think** about the cause, **Fix** the code, and **Retry**.
48
61
  2. **Intelligent Retry (Swarm Supervision):**
49
62
  * If a GLM Z.AI worker produces bad code, **DON'T** repeat the same prompt.
50
63
  * **Analyze WHY** it failed and **Guide** the worker: "Previous attempt failed because X. Try again using pattern Y."
51
64
  * **Takeover:** If the worker fails twice, **DO IT YOURSELF**.
52
65
 
53
- ## 5. REPORTING PROTOCOL
66
+ ## 6. REPORTING PROTOCOL
54
67
  At the end of your task, you **MUST** overwrite `.eck/lastsnapshot/AnswerToSA.md` BEFORE calling `eck_finish_task`.
55
68
 
56
69
  **Format for .eck/lastsnapshot/AnswerToSA.md:**
@@ -516,10 +516,11 @@ Use \`apply_code_changes\` for simple, direct tasks where you provide all detail
516
516
  "agent_environment": "Development environment with full GUI support and development tools",
517
517
  "command_for_agent": "apply_code_changes",
518
518
  "task_id": "unique-task-id",
519
- "payload": {
520
- "objective": "Brief, clear task description",
521
- "context": "Why this change is needed - include relevant .eck manifest context",
522
- "files_to_modify": [
519
+ "payload": {
520
+ "objective": "Brief, clear task description",
521
+ "context": "Why this change is needed - include relevant .eck manifest context",
522
+ "architect_confidence": "high (90%) - I am certain of this plan / low (30%) - Please investigate first",
523
+ "files_to_modify": [
523
524
  {
524
525
  "path": "exact/file/path.js",
525
526
  "action": "specific action (add, modify, replace, delete)",
@@ -1,6 +1,6 @@
1
- import fs from 'fs/promises';
2
- import path from 'path';
3
-
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+
4
4
  /**
5
5
  * Generates the Smart Delegation Protocol based on the specific Architect persona.
6
6
  */
@@ -21,7 +21,12 @@ You are operating in **Project Mode**. You are not just editing a single file; y
21
21
  ${tree}
22
22
  \`\`\`
23
23
 
24
- ## 2. SWARM DELEGATION PROTOCOL (GLM Z.AI)
24
+ ## 2. PROJECT CONTEXT (.eck DIRECTORY)
25
+ The \`.eck/\` directory is your brain externalized. **Before taking action:**
26
+ - Read the files in \`.eck/\` (like \`CONTEXT.md\`, \`ROADMAP.md\`, \`TECH_DEBT.md\`) to understand the rules and current state.
27
+ - Update these manifests if the architecture or roadmap changes.
28
+
29
+ ## 3. SWARM DELEGATION PROTOCOL (GLM Z.AI)
25
30
  You command a fleet of specialist agents (Swarm). Your primary job is to break down the user's request into sub-tasks and delegate the heavy lifting.
26
31
  ${behaviorFocus}
27
32
 
@@ -37,64 +42,66 @@ For bulk work, YOU MUST use your MCP tools to delegate to GLM Z.AI:
37
42
  - \`glm_zai_qa\`: Writing comprehensive test suites (E2E, unit tests).
38
43
  - \`glm_zai_refactor\`: Code cleanup and SOLID principle enforcement.
39
44
 
40
- ## 3. DEFINITION OF DONE (CRITICAL)
41
- Your task is NOT complete until the code works globally.
42
- 1. **Verify:** Run tests or build commands. If they fail, fix the errors iteratively.
43
- 2. **Report:** Overwrite \`.eck/lastsnapshot/AnswerToSA.md\` with your final status. Use this exact format:
44
- \`\`\`markdown
45
- # Report: [Task Name]
46
- **Executor:** [Your Exact Model Name, e.g., Claude 3.5 Sonnet (Claude Code)]
47
- **Status:** [SUCCESS / BLOCKED / FAILED]
48
- **Changes:**
49
- - Modified X
50
- \`\`\`
51
- 3. **Sync Context:** Call the \`eck_finish_task\` MCP tool. This will stage changes, commit them with a descriptive message, and generate an updated delta snapshot for the Senior Architect.
52
-
53
- ## 4. SWARM ERROR RECOVERY
54
- If a GLM Z.AI worker returns bad code:
55
- 1. Do NOT repeat the exact same prompt.
56
- 2. Analyze the failure (e.g., "Worker used wrong import path").
57
- 3. Call the tool again with corrective guidance: *"Previous attempt failed because of X. Try again using pattern Y."*
58
- 4. If the worker fails twice, take over and implement the fix yourself.
59
-
60
- ## 5. OPERATIONAL RULES
45
+ ## 4. DEFINITION OF DONE (CRITICAL)
46
+ Your task is NOT complete until code works globally.
47
+ 1. **Verify:** Verify functionality manually via browser/curl/logs/DB checks. If they fail, fix errors iteratively.
48
+ 2. **Finish & Report:** Use the \`eck_finish_task\` MCP tool.
49
+ - Pass your full markdown report into the \`status\` argument.
50
+ - The tool will automatically write the report to \`.eck/lastsnapshot/AnswerToSA.md\`, commit, and generate a snapshot.
51
+ - **DO NOT** try to manually write to \`.eck/lastsnapshot/AnswerToSA.md\` with the \`Write\` tool (it will fail safety checks).
52
+ - **WARNING:** USE ONLY ONCE PER TASK. Do not use this tool or \`eck-snapshot update\` for intermediate testing.
53
+
54
+ ## 5. SWARM ERROR RECOVERY & ARCHITECT HYPOTHESES
55
+ 1. **Runtime Check:** Always check the \`.eck/RUNTIME_STATE.md\` and running processes before coding.
56
+ 2. **Challenge the Architect:** If the Architect's hypothesis is not confirmed during verification, discard it and look for the real root cause in the runtime.
57
+ 3. If a GLM Z.AI worker returns bad code, do NOT repeat the exact same prompt.
58
+ 4. Analyze the failure (e.g., "Worker used wrong import path").
59
+ 5. Call the tool again with corrective guidance: *"Previous attempt failed because of X. Try again using pattern Y."*
60
+ 6. If the worker fails twice, take over and implement the fix yourself.
61
+
62
+ ## 6. OPERATIONAL RULES
61
63
  - **Manifests:** If you see [STUB] in .eck/ files, update them.
62
64
  `;
63
65
  }
64
-
66
+
65
67
  const CODER_INSTRUCTIONS = `# 🛠️ ROLE: Expert Developer (The Fixer)
66
68
 
67
69
  ## CORE DIRECTIVE
68
70
  You are an Expert Developer. The architecture is already decided. Your job is to **execute**, **fix**, and **polish**.
69
71
 
70
72
  ## DEFINITION OF DONE (CRITICAL)
71
- When the task is complete:
72
- 1. **Write** your report to \`.eck/lastsnapshot/AnswerToSA.md\` (overwrite, not append). Use this exact format:
73
- \`\`\`markdown
74
- # Report: [Task Name]
75
- **Executor:** [Your Exact Model Name, e.g., Claude 3.5 Sonnet]
76
- **Status:** [SUCCESS / BLOCKED / FAILED]
77
- **Changes:**
78
- - Modified X
79
- \`\`\`
80
- 2. **Run** \`eck-snapshot update\` this auto-commits all changes and generates an incremental snapshot.
81
- 3. If \`eck_finish_task\` MCP tool is available, you may use it instead.
82
-
83
- ## CONTEXT
84
- - The GLM Z.AI worker might have struggled or produced code that needs refinement.
85
- - You are here to solve the hard problems manually.
86
- - You have full permission to edit files directly.
73
+ When task is complete, you must report back and sync context.
74
+
75
+ **OPTION A: Using MCP Tool (Recommended)**
76
+ Call the \`eck_finish_task\` tool. Pass your detailed markdown report into the \`status\` argument.
77
+ - The tool will automatically write the report to \`AnswerToSA.md\`, commit, and generate a snapshot.
78
+ - **DO NOT** manually write to \`AnswerToSA.md\` with your file editing tools (it will fail safety checks).
79
+ - **WARNING: USE ONLY ONCE.** Do not use \`eck_finish_task\` for intermediate testing.
80
+
81
+ **OPTION B: Manual CLI (Fallback)**
82
+ If the MCP tool is unavailable:
83
+ 1. **READ** \`.eck/lastsnapshot/AnswerToSA.md\` using your \`Read\` tool (REQUIRED by safety rules before overwriting).
84
+ 2. **WRITE** your report to that file.
85
+ 3. Run \`eck-snapshot update\` in terminal.
86
+
87
+ ## PROJECT CONTEXT (.eck DIRECTORY)
88
+ The \`.eck/\` directory contains critical project documentation. **Before starting your task, you MUST:**
89
+ 1. List the files in the \`.eck/\` directory.
90
+ 2. Read any files that might be relevant to your task based on their names (e.g., \`CONTEXT.md\`, \`TECH_DEBT.md\`, \`OPERATIONS.md\`).
91
+ 3. You are responsible for updating these files if your code changes alter the project's architecture or operations.
87
92
 
88
93
  ## WORKFLOW
89
- 1. Read the code.
90
- 2. Fix the bugs / Implement the feature.
91
- 3. Verify functionality (Run tests!).
92
- 4. **Loop:** If verification fails, fix it immediately. Do not ask for permission.
94
+ 1. Check the \`.eck/RUNTIME_STATE.md\` and verify actual running processes.
95
+ 2. Read the code. If the Architect's hypothesis is wrong, discard it and find the real bug.
96
+ 3. Fix the bugs / Implement the feature.
97
+ 4. Verify functionality manually via browser/curl/logs/DB checks.
98
+ 5. **Loop:** If verification fails, fix it immediately. Do not ask for permission.
99
+ 6. **Blocked?** Use the \`eck_fail_task\` tool to abort safely without committing broken code.
93
100
  `;
94
-
95
- /**
96
- * Generates and writes the CLAUDE.md file based on the selected mode.
97
- */
101
+
102
+ /**
103
+ * Generates and writes the CLAUDE.md file based on the selected mode.
104
+ */
98
105
  export async function updateClaudeMd(repoPath, mode, tree, confidentialFiles = [], options = {}) {
99
106
  let content = '';
100
107
 
@@ -106,30 +113,30 @@ export async function updateClaudeMd(repoPath, mode, tree, confidentialFiles = [
106
113
  // Default coder mode (or if flags are missing)
107
114
  content = CODER_INSTRUCTIONS;
108
115
  }
109
-
110
- // Chinese delegation mode
111
- if (options.zh) {
112
- content += `
113
- ## 🇨🇳 LANGUAGE PROTOCOL
114
- - **With the user:** Communicate in the user's language (auto-detect from their messages).
115
- - **With GLM Z.AI workers:** ALWAYS write the \`instruction\` parameter in **Chinese (中文)**.
116
- This significantly improves output quality for Chinese-trained models.
117
- Translate task descriptions, requirements, and context into Chinese before delegating.
118
- - **Code:** Variable names, comments in code, and commit messages remain in English.
119
- `;
120
- }
121
-
122
- // Append Confidential Files Reference
123
- if (confidentialFiles.length > 0) {
124
- content += '\n\n## 🔐 Access & Credentials\n';
125
- content += 'The following confidential files are available locally but excluded from snapshots/tree:\n';
126
- for (const file of confidentialFiles) {
127
- content += `- \`${file}\`\n`;
128
- }
129
- content += '> **Note:** Read these files only when strictly necessary.\n';
130
- }
131
-
132
- const claudeMdPath = path.join(repoPath, 'CLAUDE.md');
133
- await fs.writeFile(claudeMdPath, content, 'utf-8');
134
- console.log(`📝 Updated CLAUDE.md for role: **${mode.toUpperCase()}** (Ralph Loop + GLM Z.AI Protocol Active)`);
135
- }
116
+
117
+ // Chinese delegation mode
118
+ if (options.zh) {
119
+ content += `
120
+ ## 🇨🇳 LANGUAGE PROTOCOL
121
+ - **With the user:** Communicate in the user's language (auto-detect from their messages).
122
+ - **With GLM Z.AI workers:** ALWAYS write the \`instruction\` parameter in **Chinese (中文)**.
123
+ This significantly improves output quality for Chinese-trained models.
124
+ Translate task descriptions, requirements, and context into Chinese before delegating.
125
+ - **Code:** Variable names, comments in code, and commit messages remain in English.
126
+ `;
127
+ }
128
+
129
+ // Append Confidential Files Reference
130
+ if (confidentialFiles.length > 0) {
131
+ content += '\n\n## 🔐 Access & Credentials\n';
132
+ content += 'The following confidential files are available locally but excluded from snapshots/tree:\n';
133
+ for (const file of confidentialFiles) {
134
+ content += `- \`${file}\`\n`;
135
+ }
136
+ content += '> **Note:** Read these files only when strictly necessary.\n';
137
+ }
138
+
139
+ const claudeMdPath = path.join(repoPath, 'CLAUDE.md');
140
+ await fs.writeFile(claudeMdPath, content, 'utf-8');
141
+ console.log(`📝 Updated CLAUDE.md for role: **${mode.toUpperCase()}** (Ralph Loop + GLM Z.AI Protocol Active)`);
142
+ }