@xelth/eck-snapshot 5.9.0 → 6.6.0

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.
Files changed (37) hide show
  1. package/README.md +321 -190
  2. package/index.js +1 -1
  3. package/package.json +15 -2
  4. package/scripts/mcp-eck-core.js +143 -13
  5. package/setup.json +119 -81
  6. package/src/cli/cli.js +256 -385
  7. package/src/cli/commands/createSnapshot.js +391 -175
  8. package/src/cli/commands/recon.js +308 -0
  9. package/src/cli/commands/setupMcp.js +280 -19
  10. package/src/cli/commands/trainTokens.js +42 -32
  11. package/src/cli/commands/updateSnapshot.js +136 -43
  12. package/src/core/depthConfig.js +54 -0
  13. package/src/core/skeletonizer.js +280 -21
  14. package/src/templates/architect-prompt.template.md +34 -0
  15. package/src/templates/multiAgent.md +68 -15
  16. package/src/templates/opencode/coder.template.md +53 -17
  17. package/src/templates/opencode/junior-architect.template.md +54 -15
  18. package/src/templates/skeleton-instruction.md +1 -1
  19. package/src/templates/update-prompt.template.md +2 -0
  20. package/src/utils/aiHeader.js +57 -27
  21. package/src/utils/claudeMdGenerator.js +182 -88
  22. package/src/utils/fileUtils.js +217 -149
  23. package/src/utils/gitUtils.js +12 -8
  24. package/src/utils/opencodeAgentsGenerator.js +8 -2
  25. package/src/utils/projectDetector.js +66 -21
  26. package/src/utils/tokenEstimator.js +11 -7
  27. package/src/cli/commands/consilium.js +0 -86
  28. package/src/cli/commands/detectProfiles.js +0 -98
  29. package/src/cli/commands/envSync.js +0 -319
  30. package/src/cli/commands/generateProfileGuide.js +0 -144
  31. package/src/cli/commands/pruneSnapshot.js +0 -106
  32. package/src/cli/commands/restoreSnapshot.js +0 -173
  33. package/src/cli/commands/setupGemini.js +0 -149
  34. package/src/cli/commands/setupGemini.test.js +0 -115
  35. package/src/cli/commands/showFile.js +0 -39
  36. package/src/services/claudeCliService.js +0 -626
  37. package/src/services/claudeCliService.test.js +0 -267
@@ -64,14 +64,17 @@ const languages = {
64
64
  * Strips implementation details from code.
65
65
  * @param {string} content - Full file content
66
66
  * @param {string} filePath - File path to determine language
67
+ * @param {object} [options] - Options
68
+ * @param {boolean} [options.preserveDocs=true] - Keep JSDoc/docstrings (depth 6) or strip them (depth 5)
67
69
  * @returns {Promise<string>} - Skeletonized code
68
70
  */
69
- export async function skeletonize(content, filePath) {
71
+ export async function skeletonize(content, filePath, options = {}) {
70
72
  if (!content) return content;
73
+ const preserveDocs = options.preserveDocs !== undefined ? options.preserveDocs : true;
71
74
 
72
75
  // 1. JS/TS Strategy (Babel is better for JS ecosystem)
73
76
  if (/\.(js|jsx|ts|tsx|mjs|cjs)$/.test(filePath)) {
74
- return skeletonizeJs(content);
77
+ return skeletonizeJs(content, preserveDocs);
75
78
  }
76
79
 
77
80
  // 2. Tree-sitter Strategy (Python, Java, Kotlin, C, Rust, Go)
@@ -83,16 +86,17 @@ export async function skeletonize(content, filePath) {
83
86
 
84
87
  // Only attempt tree-sitter if both the parser and the specific language module are ready
85
88
  if (available && Parser && langModule) {
86
- return skeletonizeTreeSitter(content, langModule, ext);
89
+ return skeletonizeTreeSitter(content, langModule, ext, preserveDocs);
87
90
  }
88
- return content; // Fallback: return original content if tree-sitter unavailable
91
+ // Fallback to regex-based skeletonizer when tree-sitter is unavailable
92
+ return skeletonizeRegex(content, ext, preserveDocs);
89
93
  }
90
94
 
91
- // 3. Fallback (Return as is)
92
- return content;
95
+ // 3. Fallback for other languages — try regex if it uses braces
96
+ return skeletonizeRegex(content, filePath.substring(filePath.lastIndexOf('.')), preserveDocs);
93
97
  }
94
98
 
95
- function skeletonizeJs(content) {
99
+ function skeletonizeJs(content, preserveDocs = true) {
96
100
  try {
97
101
  const ast = parse(content, {
98
102
  sourceType: 'module',
@@ -100,27 +104,27 @@ function skeletonizeJs(content) {
100
104
  errorRecovery: true
101
105
  });
102
106
 
103
- traverse(ast, {
104
- Function(path) {
105
- if (path.node.body && path.node.body.type === 'BlockStatement') {
106
- // Preserve leading comments (JSDoc) before emptying body
107
+ const emptyBody = (path) => {
108
+ if (path.node.body && path.node.body.type === 'BlockStatement') {
109
+ if (preserveDocs) {
110
+ // Keep leading comments (JSDoc) before emptying body
107
111
  const leadingComments = path.node.leadingComments || [];
108
112
  path.node.body.body = [];
109
113
  path.node.body.innerComments = leadingComments.length > 0
110
114
  ? leadingComments
111
115
  : [{ type: 'CommentBlock', value: ' ... ' }];
112
- }
113
- },
114
- ClassMethod(path) {
115
- if (path.node.body && path.node.body.type === 'BlockStatement') {
116
- // Preserve leading comments (JSDoc) before emptying body
117
- const leadingComments = path.node.leadingComments || [];
116
+ } else {
117
+ // Strip everything including docs
118
+ path.node.leadingComments = null;
118
119
  path.node.body.body = [];
119
- path.node.body.innerComments = leadingComments.length > 0
120
- ? leadingComments
121
- : [{ type: 'CommentBlock', value: ' ... ' }];
120
+ path.node.body.innerComments = [{ type: 'CommentBlock', value: ' ... ' }];
122
121
  }
123
122
  }
123
+ };
124
+
125
+ traverse(ast, {
126
+ Function: emptyBody,
127
+ ClassMethod: emptyBody
124
128
  });
125
129
 
126
130
  const output = generate(ast, {}, content);
@@ -130,7 +134,7 @@ function skeletonizeJs(content) {
130
134
  }
131
135
  }
132
136
 
133
- function skeletonizeTreeSitter(content, language, ext) {
137
+ function skeletonizeTreeSitter(content, language, ext, preserveDocs = true) {
134
138
  try {
135
139
  const parser = new Parser();
136
140
  parser.setLanguage(language);
@@ -172,6 +176,19 @@ function skeletonizeTreeSitter(content, language, ext) {
172
176
  }
173
177
 
174
178
  if (bodyNode) {
179
+ // For Python with preserveDocs: keep docstring as first statement
180
+ if (preserveDocs && ext === '.py' && bodyNode.childCount > 0) {
181
+ const docstring = extractPythonDocstring(bodyNode);
182
+ if (docstring) {
183
+ replacements.push({
184
+ start: bodyNode.startIndex,
185
+ end: bodyNode.endIndex,
186
+ text: docstring + '\n ...'
187
+ });
188
+ return;
189
+ }
190
+ }
191
+
175
192
  replacements.push({
176
193
  start: bodyNode.startIndex,
177
194
  end: bodyNode.endIndex,
@@ -181,6 +198,16 @@ function skeletonizeTreeSitter(content, language, ext) {
181
198
  }
182
199
  }
183
200
 
201
+ // If not preserveDocs, also strip standalone comment blocks
202
+ if (!preserveDocs && type === 'comment') {
203
+ replacements.push({
204
+ start: node.startIndex,
205
+ end: node.endIndex,
206
+ text: ''
207
+ });
208
+ return;
209
+ }
210
+
184
211
  for (let i = 0; i < node.childCount; i++) {
185
212
  visit(node.child(i));
186
213
  }
@@ -194,8 +221,240 @@ function skeletonizeTreeSitter(content, language, ext) {
194
221
  currentContent = currentContent.substring(0, rep.start) + rep.text + currentContent.substring(rep.end);
195
222
  }
196
223
 
224
+ // Clean up excessive blank lines from stripped comments
225
+ if (!preserveDocs) {
226
+ currentContent = currentContent.replace(/\n{3,}/g, '\n\n');
227
+ }
228
+
197
229
  return currentContent;
198
230
  } catch (e) {
199
231
  return content + `\n// [Skeleton error: ${e.message}]`;
200
232
  }
201
233
  }
234
+
235
+ /**
236
+ * Regex-based fallback skeletonizer for when tree-sitter is unavailable.
237
+ * Works by counting braces to find and hollow out function bodies.
238
+ * Supports: Rust, Go, Java, C/C++, Python, and other brace-based languages.
239
+ */
240
+ function skeletonizeRegex(content, ext, preserveDocs = true) {
241
+ if (ext === '.py') {
242
+ return skeletonizePythonRegex(content, preserveDocs);
243
+ }
244
+ // Brace-based languages (Rust, Go, Java, C, C++, etc.)
245
+ return skeletonizeBraceRegex(content, ext, preserveDocs);
246
+ }
247
+
248
+ /**
249
+ * Skeleton for brace-based languages: finds function/method signatures
250
+ * and replaces their bodies with { /* ... * / }
251
+ */
252
+ function skeletonizeBraceRegex(content, ext, preserveDocs) {
253
+ const lines = content.split('\n');
254
+ const result = [];
255
+ let i = 0;
256
+
257
+ // Patterns that indicate a function/method definition line
258
+ // We look for lines ending with '{' that look like function signatures
259
+ const fnPatterns = {
260
+ '.rs': /^\s*(?:pub\s+)?(?:async\s+)?(?:unsafe\s+)?(?:fn|impl)\s+/,
261
+ '.go': /^\s*func\s+/,
262
+ '.java': /^\s*(?:public|private|protected|static|final|abstract|synchronized|native|\s)*\s+\w+\s*\([^)]*\)\s*(?:throws\s+\w+(?:\s*,\s*\w+)*)?\s*\{?\s*$/,
263
+ '.kt': /^\s*(?:(?:public|private|protected|internal|override|open|abstract|suspend|inline|fun)\s+)+/,
264
+ '.c': null, // use generic detection
265
+ '.h': null,
266
+ '.cpp': null,
267
+ '.hpp': null,
268
+ };
269
+
270
+ const fnPattern = fnPatterns[ext] || null;
271
+
272
+ while (i < lines.length) {
273
+ const line = lines[i];
274
+ const trimmed = line.trimStart();
275
+
276
+ // Skip doc comments if !preserveDocs
277
+ if (!preserveDocs) {
278
+ // Block doc comments: /** ... */ or /// lines
279
+ if (trimmed.startsWith('///') || trimmed.startsWith('//!')) {
280
+ i++;
281
+ continue;
282
+ }
283
+ if (trimmed.startsWith('/**') || trimmed.startsWith('/*!')) {
284
+ while (i < lines.length && !lines[i].includes('*/')) {
285
+ i++;
286
+ }
287
+ i++; // skip the closing */
288
+ continue;
289
+ }
290
+ }
291
+
292
+ // Check if this line starts a function definition
293
+ let isFnLine = false;
294
+ if (fnPattern) {
295
+ isFnLine = fnPattern.test(line);
296
+ } else {
297
+ // Generic C/C++ heuristic: line has parens and ends with or is followed by {
298
+ isFnLine = /\w+\s*\([^;]*\)\s*\{?\s*$/.test(trimmed) && !trimmed.startsWith('if') &&
299
+ !trimmed.startsWith('while') && !trimmed.startsWith('for') &&
300
+ !trimmed.startsWith('switch') && !trimmed.startsWith('#');
301
+ }
302
+
303
+ // For Rust: also handle impl blocks — keep them but skeleton their methods
304
+ if (isFnLine) {
305
+ // Find the opening brace (may be on same line or next line)
306
+ let sigLines = [line];
307
+ let j = i + 1;
308
+
309
+ // If no opening brace on this line, scan ahead for it
310
+ if (!line.includes('{')) {
311
+ while (j < lines.length) {
312
+ sigLines.push(lines[j]);
313
+ if (lines[j].includes('{')) {
314
+ j++;
315
+ break;
316
+ }
317
+ j++;
318
+ }
319
+ } else {
320
+ // Opening brace is on the signature line
321
+ }
322
+
323
+ // Now count braces to find the end of the body
324
+ let braceCount = 0;
325
+ let bodyStart = i;
326
+ let bodyEnd = i;
327
+ let foundOpen = false;
328
+
329
+ for (let k = i; k < (foundOpen ? lines.length : j); k++) {
330
+ for (const ch of lines[k]) {
331
+ if (ch === '{') { braceCount++; foundOpen = true; }
332
+ if (ch === '}') braceCount--;
333
+ }
334
+ bodyEnd = k;
335
+ if (foundOpen && braceCount === 0) break;
336
+ }
337
+
338
+ // If we didn't finish counting, continue from j
339
+ if (foundOpen && braceCount > 0) {
340
+ for (let k = j; k < lines.length; k++) {
341
+ for (const ch of lines[k]) {
342
+ if (ch === '{') braceCount++;
343
+ if (ch === '}') braceCount--;
344
+ }
345
+ bodyEnd = k;
346
+ if (braceCount === 0) break;
347
+ }
348
+ }
349
+
350
+ if (foundOpen && braceCount === 0) {
351
+ // Emit signature (up to opening brace) + skeleton
352
+ const sigText = sigLines.join('\n');
353
+ const braceIdx = sigText.indexOf('{');
354
+ const signature = sigText.substring(0, braceIdx).trimEnd();
355
+ const indent = line.match(/^(\s*)/)[1];
356
+ result.push(signature + ' { /* ... */ }');
357
+ i = bodyEnd + 1;
358
+ continue;
359
+ }
360
+ }
361
+
362
+ result.push(line);
363
+ i++;
364
+ }
365
+
366
+ return result.join('\n');
367
+ }
368
+
369
+ /**
370
+ * Skeleton for Python: finds function/class defs and replaces bodies with ...
371
+ */
372
+ function skeletonizePythonRegex(content, preserveDocs) {
373
+ const lines = content.split('\n');
374
+ const result = [];
375
+ let i = 0;
376
+
377
+ while (i < lines.length) {
378
+ const line = lines[i];
379
+ const trimmed = line.trimStart();
380
+ const indent = line.length - trimmed.length;
381
+
382
+ if (/^(async\s+)?def\s+/.test(trimmed) || /^class\s+/.test(trimmed)) {
383
+ result.push(line);
384
+ i++;
385
+
386
+ // Determine body indent (should be > current indent)
387
+ const bodyIndent = indent + 4; // standard Python indent
388
+
389
+ // Check for docstring
390
+ if (i < lines.length) {
391
+ const nextTrimmed = lines[i].trimStart();
392
+ if (preserveDocs && (nextTrimmed.startsWith('"""') || nextTrimmed.startsWith("'''"))) {
393
+ const quote = nextTrimmed.substring(0, 3);
394
+ // Emit docstring lines
395
+ if (nextTrimmed.indexOf(quote, 3) > 0) {
396
+ // Single-line docstring
397
+ result.push(lines[i]);
398
+ i++;
399
+ } else {
400
+ // Multi-line docstring
401
+ result.push(lines[i]);
402
+ i++;
403
+ while (i < lines.length && !lines[i].trimStart().includes(quote)) {
404
+ result.push(lines[i]);
405
+ i++;
406
+ }
407
+ if (i < lines.length) {
408
+ result.push(lines[i]); // closing quote line
409
+ i++;
410
+ }
411
+ }
412
+ }
413
+ }
414
+
415
+ // Add ... and skip body
416
+ result.push(' '.repeat(bodyIndent) + '...');
417
+
418
+ // Skip remaining body lines (lines with indent > current def indent)
419
+ while (i < lines.length) {
420
+ const bodyLine = lines[i];
421
+ const bodyTrimmed = bodyLine.trimStart();
422
+ const bodyLineIndent = bodyLine.length - bodyTrimmed.length;
423
+ // Empty lines or lines indented more than the def are part of body
424
+ if (bodyTrimmed === '' || bodyLineIndent > indent) {
425
+ i++;
426
+ } else {
427
+ break;
428
+ }
429
+ }
430
+ continue;
431
+ }
432
+
433
+ result.push(line);
434
+ i++;
435
+ }
436
+
437
+ return result.join('\n');
438
+ }
439
+
440
+ /**
441
+ * Extract Python docstring from the first statement of a function body block.
442
+ */
443
+ function extractPythonDocstring(bodyNode) {
444
+ for (let i = 0; i < bodyNode.childCount; i++) {
445
+ const child = bodyNode.child(i);
446
+ // Python docstrings are expression_statement containing a string
447
+ if (child.type === 'expression_statement') {
448
+ const expr = child.child(0);
449
+ if (expr && expr.type === 'string') {
450
+ // Return the indented docstring text
451
+ return '\n ' + expr.text;
452
+ }
453
+ }
454
+ // Skip newline/indent tokens, but stop at first real statement
455
+ if (child.type !== 'newline' && child.type !== 'indent' && child.type !== 'NEWLINE' && child.type !== 'INDENT') {
456
+ if (child.type !== 'expression_statement') break;
457
+ }
458
+ }
459
+ return null;
460
+ }
@@ -19,6 +19,7 @@ You MUST wrap your ENTIRE response (Analysis + Changes + Metadata) in a single `
19
19
  ### Command Format (Wrapped)
20
20
 
21
21
  ````text
22
+ <eck_task id="{{repoName}}:short-task-description">
22
23
  # Analysis
23
24
 
24
25
  [Explain your reasoning: what you're doing and why.
@@ -48,6 +49,7 @@ async function example() {
48
49
  }
49
50
  }
50
51
  ```
52
+ </eck_task id="{{repoName}}:short-task-description">
51
53
  ````
52
54
 
53
55
  ### File Actions Reference
@@ -62,6 +64,7 @@ async function example() {
62
64
  ### Complete Example
63
65
 
64
66
  ````text
67
+ <eck_task id="{{repoName}}:add-user-validation">
65
68
  # Analysis
66
69
 
67
70
  The authentication module needs a null check to prevent crashes when
@@ -111,6 +114,7 @@ export function validateUser(user) {
111
114
  }
112
115
  }
113
116
  ```
117
+ </eck_task id="{{repoName}}:add-user-validation">
114
118
  ````
115
119
 
116
120
  ### Why Eck-Protocol v2?
@@ -133,6 +137,36 @@ To understand the project state, you can command the `eck-snapshot` tool directl
133
137
  - `eck-snapshot query "<question>"`: Search the codebase
134
138
  - `eck-snapshot detect`: Analyze the project structure
135
139
  - `eck-snapshot restore <snapshot_file> --include ...`: View specific files
140
+ - `eck-snapshot link <depth>`: Run inside a related repository to generate a read-only companion snapshot.
141
+
142
+ ## SCOUT & FETCH: Cross-Repository Intelligence
143
+
144
+ When working with multiple repositories, use `scout` and `fetch` to gather context:
145
+
146
+ **CRITICAL:** Both `scout` and `fetch` operate on the **current working directory only**. They scan files relative to `cwd` — absolute paths will NOT work.
147
+
148
+ **Single-repo fetch:**
149
+ ```bash
150
+ cd /path/to/project-a
151
+ eck-snapshot fetch "**/SyncManager.kt" "**/RelayClient.kt"
152
+ ```
153
+
154
+ **Multi-repo fetch (MUST be separate commands):**
155
+ ```bash
156
+ # Fetch from first project
157
+ cd /path/to/project-a
158
+ eck-snapshot fetch "**/SyncManager.kt"
159
+
160
+ # Fetch from second project
161
+ cd /path/to/project-b
162
+ eck-snapshot fetch "**/AppDatabase.kt"
163
+ ```
164
+
165
+ **Rules:**
166
+ - Always use **relative glob patterns**, never absolute paths
167
+ - Always specify which directory to `cd` into before each command
168
+ - Use `**/<filename>` to find files regardless of nesting depth
169
+ - One `fetch` command = one repo. For multiple repos, issue multiple commands.
136
170
 
137
171
  ## CAPABILITIES & DELEGATION PROTOCOL
138
172
 
@@ -1,8 +1,14 @@
1
- # AI Instructions
1
+ # SYSTEM DIRECTIVE FOR THE ACTIVE AI AGENT
2
2
 
3
- ## 1. How to Read This Snapshot
3
+ **CRITICAL:** If you are the AI (LLM) reading this file in the current chat session, you must IMMEDIATELY assume the role defined below. Do not act as an external reviewer or generic assistant. This document is your active operating environment and contract.
4
4
 
5
- This document is a self-contained, single-file snapshot of the **{{repoName}}** software repository, generated by the `eck-snapshot` tool on **{{timestamp}}**. It is designed to provide a Large Language Model (LLM) with the complete context of a project.
5
+ ## 1. Your Role & Identity
6
+
7
+ You are the **Senior Project Manager and Solution Architect AI**. Your primary goal is to translate user requests into technical plans and then generate precise commands for code-execution AI agents.
8
+
9
+ ## 2. How to Read This Snapshot
10
+
11
+ This document is a self-contained, single-file snapshot of the **{{repoName}}** software repository, generated by the `eck-snapshot` tool on **{{timestamp}}**. Treat the file structure and code below as your absolute source of truth for the project state.
6
12
 
7
13
  * **Source of Truth:** Treat this snapshot as the complete and authoritative source code.
8
14
  * **Structure:** The file contains a **Directory Structure** tree, followed by the full content of each file, demarcated by `--- File: /path/to/file ---` headers.
@@ -13,15 +19,13 @@ This document is a self-contained, single-file snapshot of the **{{repoName}}**
13
19
 
14
20
  ---
15
21
 
16
- ## 2. Your Core Operational Workflow
17
-
18
- You are the Project Manager and Solution Architect AI. Your primary goal is to translate user requests into technical plans and then generate precise commands for code-execution AI agents.
22
+ ## 3. Your Core Operational Workflow
19
23
 
20
24
  {{projectOverview}}
21
25
 
22
26
  {{eckManifestSection}}
23
27
 
24
- ### 🛠 MANIFEST MAINTENANCE PROTOCOL (CRITICAL)
28
+ ### MANIFEST MAINTENANCE PROTOCOL (CRITICAL)
25
29
 
26
30
  The `.eck/` directory files are your "Source of Knowledge".
27
31
  1. **Stub Detection:** If a file starts with `# [STUB: ...]`, it means the system failed to auto-generate meaningful content.
@@ -30,6 +34,54 @@ The `.eck/` directory files are your "Source of Knowledge".
30
34
 
31
35
  **Documentation is part of the "Definition of Done". A task is not finished if the relevant manifest files still contain [STUB] warnings.**
32
36
 
37
+ ### 🛑 CROSS-PROJECT CONTAMINATION CHECK (CRITICAL)
38
+
39
+ Before analyzing any new snapshot or incremental update, you MUST perform a sanity check against your current working context.
40
+ Compare the `Project:` name and directory structure in the incoming file against the known architecture of the current task.
41
+ IF you detect files from a completely different repository or domain, **IMMEDIATELY STOP**.
42
+ Alert the user: *"Warning: The snapshot you uploaded belongs to a different project. Our current context is [Current Project]. Did you upload the wrong file?"*
43
+ Do NOT merge the files into your mental model until the user confirms.
44
+
45
+ ### 🧹 CONTEXT HYGIENE PROTOCOL (CRITICAL)
46
+
47
+ You are responsible for keeping your own context window clean and efficient.
48
+ **Mandatory Full Snapshot Evaluation:** Whenever you receive a FULL snapshot, you MUST evaluate the `Directory Structure` and file list for irrelevant bloat (e.g., compiled binaries, DB dumps like .wal, huge logs, decompiled code).
49
+
50
+ If bloat is detected:
51
+ 1. **Report to User:** Briefly tell the user how much garbage was found.
52
+ - *Massive Bloat:* Suggest pausing the main task. Generate an `eck_task` ONLY to create/update `.eckignore`, and ask the user to generate a fresh full snapshot before proceeding.
53
+ - *Minor Bloat:* Append the `.eckignore` creation/update to your current `eck_task` alongside the user's main request. Tell the user it's just a cleanup for the future and you can work with the current context.
54
+ 2. **Execution:** Instruct the Coder to use standard `.gitignore` syntax in `.eckignore` (e.g., `data/surreal_data/`, `*.wal`).
55
+
56
+ **🚨 MANUAL OVERRIDE (THE CODE WORD):**
57
+ If the human user includes the phrase **`[EXECUTE HYGIENE]`** or **`[CLEAN CONTEXT]`**, immediately suspend all feature development and dedicate your response exclusively to cleaning the context via `.eckignore`.
58
+
59
+ ### 📝 PROACTIVE TECH DEBT & TODO PROTOCOL
60
+
61
+ As a Senior Architect, you must actively manage code quality. When analyzing files in this snapshot, do not ignore developer comments:
62
+ 1. **Spot:** Actively look for `TODO`, `FIXME`, `HACK`, or `BUG` comments in the provided source code.
63
+ 2. **Evaluate:** Compare the comment against the actual implementation. Developers often fix things but forget to remove the comment.
64
+ 3. **Resolve (The 3 Actions):**
65
+ - **Obsolete:** If the code already does what the TODO asks, instruct the Coder to **delete the comment**.
66
+ - **Quick Fix:** If it's a small missing piece or an obvious bug, instruct the Coder to **implement the fix and remove the comment**.
67
+ - **Real Debt:** If it requires significant architectural work, instruct the Coder to **document it in `.eck/TECH_DEBT.md`** so it is officially tracked, and leave the comment in the code for now.
68
+
69
+ ### 🏕️ THE BOY SCOUT RULE (Docstrings & Comments)
70
+
71
+ Leave the codebase better than you found it.
72
+ Whenever you instruct the Coder to **modify an existing function/class** or **create a new one**, you MUST explicitly add this requirement to their task:
73
+ > *"Ensure the JSDoc / Docstring for this function is created or updated to accurately reflect its new behavior, parameters, and return types. Explain WHY it exists, not just WHAT it does."*
74
+ Do not rewrite documentation for the entire file—only strictly for the components you are touching.
75
+
76
+ ### 🛡️ RELIABILITY & ZERO-BROKEN-WINDOWS PROTOCOL
77
+
78
+ You are the final gatekeeper of quality. A task is NEVER complete if the code doesn't compile or tests fail.
79
+ Whenever you delegate a task to the Coder, you MUST enforce the following verification steps:
80
+ 1. **Identify the Test Suite:** Check the environment (e.g., `npm test`, `cargo test`, `pytest`).
81
+ 2. **Mandate Verification:** Explicitly instruct the Coder:
82
+ > *"Before calling `eck_finish_task`, you MUST run the project's test suite and ensure all tests pass. If there are no automated tests, you MUST manually verify the core functionality via CLI/Bash. Do NOT finish the task if there are compilation errors or test failures."*
83
+ 3. **No Blind Commits:** Never allow the Coder to commit code blindly. Verification is mandatory.
84
+
33
85
  ### CRITICAL WORKFLOW: Structured Commits via `journal_entry`
34
86
 
35
87
  To ensure proper project history, all code changes **MUST** be committed using the project's built-in structured workflow.
@@ -82,11 +134,8 @@ When generating commands for the Coder agent (Claude Code), you MUST include thi
82
134
 
83
135
  The Coder agent is intelligent and will understand what information they need based on file names.
84
136
 
85
- **Maintain Documentation:** When assigning tasks, instruct the Coder to update relevant `.eck/` documentation files if the changes affect:
86
- - System architecture (update `ARCHITECTURE.md`)
87
- - Operational procedures (update `OPERATIONS.md`)
88
- - Technical debt status (update `TECH_DEBT.md`)
89
- - Project roadmap progress (update `ROADMAP.md`)
137
+ **Maintain Documentation (TOKEN OPTIMIZATION):** When assigning tasks, instruct the Coder to update relevant `.eck/` documentation files.
138
+ **CRITICAL:** Tell the Coder NOT to read `JOURNAL.md` (it auto-updates) and instruct them to use the `eck_manifest_edit` tool to blindly append/edit `ROADMAP.md` and `TECH_DEBT.md` to save thousands of context tokens.
90
139
 
91
140
  ### CORE WORKFLOW: The Interactive Command Cycle
92
141
 
@@ -100,7 +149,12 @@ The Coder agent is intelligent and will understand what information they need ba
100
149
  6. **Review & Report:** After the command is executed, analyze the results and report back to the user in their language.
101
150
  7. **Iterate:** Continue the cycle based on user feedback.
102
151
 
103
- ### 🛡️ ANTI-TRUNCATION PROTOCOL (CRITICAL)
152
+ ### CROSS-CONTEXT DEVELOPMENT (LINKED PROJECTS)
153
+
154
+ If this project interacts with an external backend, frontend, or microservice, you can request its context.
155
+ **Ask the user to run:** `eck-snapshot link [depth 0-9]` inside the related repository and upload the resulting `link_*.md` file. You will receive precise read-only access and fetch commands inside that file.
156
+
157
+ ### ANTI-TRUNCATION PROTOCOL (CRITICAL)
104
158
 
105
159
  Web interfaces (like Gemini or ChatGPT) sometimes silently drop the content of large text files during upload, replacing the file's content with a tiny JSON metadata string (e.g., `{"fileName": "...", "contentFetchId": "..."}`).
106
160
 
@@ -108,7 +162,7 @@ Web interfaces (like Gemini or ChatGPT) sometimes silently drop the content of l
108
162
  1. **Always check the filename:** The exact file size in kilobytes is appended to the end of every snapshot filename (e.g., `..._up7_1250kb.md`).
109
163
  2. **Verify payload length:** If the filename says `1250kb` but the text you actually received for that file is only a few lines long or looks like a system JSON string, **THE CONTENT WAS TRUNCATED BY THE UI**.
110
164
  3. **Alert the User:** DO NOT hallucinate the missing code. Immediately stop and tell the user:
111
- > "🚨 **System Error:** The web interface truncated the file `[FileName]`. I only received the metadata/JSON stub, not the actual `[Size]kb` of code. Please split the snapshot or paste the text directly."
165
+ > "**System Error:** The web interface truncated the file `[FileName]`. I only received the metadata/JSON stub, not the actual `[Size]kb` of code. Please split the snapshot or paste the text directly."
112
166
 
113
167
  {{hierarchicalWorkflow}}
114
168
 
@@ -125,4 +179,3 @@ Web interfaces (like Gemini or ChatGPT) sometimes silently drop the content of l
125
179
  You can command multiple specialized agents. **YOU must choose the most appropriate agent** based on the task requirements and target environment:
126
180
 
127
181
  {{agentDefinitions}}
128
-
@@ -3,27 +3,63 @@
3
3
  ## CORE DIRECTIVE
4
4
  You are an Expert Developer. The architecture is already decided. Your job is to **execute**, **fix**, and **polish**.
5
5
 
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.
6
+ ## HUMAN VS. ARCHITECT (CRITICAL)
7
+ You receive instructions from two sources:
8
+ 1. **The AI Architect:** Sends formal tasks wrapped in `<eck_task id="repo:description">` (e.g., `<eck_task id="ecksnapshot:fix-auth-crash">`) tags.
9
+ 2. **The Human User:** Sends conversational messages, clarifications, or small requests (e.g., "make this red", "fix that typo").
10
+
11
+ ## DEFINITION OF DONE & eck_finish_task
12
+ Your behavior changes based on who you are talking to:
13
+ - **For AI Architect Tasks (`<eck_task>`):** When the task is complete and fully tested, call `eck_finish_task` IMMEDIATELY. Do NOT ask the user for permission. Include the task `id` in your status report.
14
+ - **For Human Requests:** Do NOT call `eck_finish_task`. Just reply to the user naturally and apply the changes. ONLY call `eck_finish_task` if the human explicitly commands you to "Report to architect" or "Finish task".
15
+
16
+ Pass your detailed markdown report into the `status` argument.
17
+ - The tool will automatically write the report, commit, and generate a snapshot.
18
+ - **DO NOT** manually write to `AnswerToSA.md` with your file editing tools.
19
+ - **WARNING: USE ONLY ONCE.** Do not use for intermediate testing.
20
+
21
+ **FALLBACK METHOD (Only if MCP tool is missing):**
22
+ If `eck_finish_task` is NOT in your available tools, you MUST do the following:
23
+ 0. **WARN THE USER:** State clearly in your response: "⚠️ `eck-core` MCP server is not connected. Proceeding with manual fallback."
24
+ 1. **READ:** Read `.eck/lastsnapshot/AnswerToSA.md` using your `Read` tool (REQUIRED before overwriting).
25
+ 2. **WRITE:** Overwrite that file with your report.
26
+ 3. **COMMIT (CRITICAL):** Run `git add .` and `git commit -m "chore: task report"` in the terminal.
27
+ 4. **SNAPSHOT:** Run `eck-snapshot '{"name": "eck_update"}'` in the terminal.
28
+ *(Note: The snapshot compares against the git anchor. If you skip step 3, it will say "No changes detected").*
29
+
30
+ ## PROJECT CONTEXT (.eck DIRECTORY) & TOKEN OPTIMIZATION
31
+ The `.eck/` directory contains critical project documentation.
32
+ 1. **List** the files in `.eck/` to see what exists.
33
+ 2. **Read** files ONLY if you absolutely need architectural context. Do NOT read large files blindly.
34
+ 3. **DO NOT READ `JOURNAL.md`**. It is extremely large and auto-updates when you use `eck_finish_task`.
35
+ 4. **BLIND EDITS:** If you need to check off a TODO in `TECH_DEBT.md` or add an item to `ROADMAP.md`, use the **`eck_manifest_edit`** tool to modify them atomically without reading the whole file into context.
19
36
 
20
37
  ## CONTEXT
21
38
  - The GLM ZAI swarm might have struggled or produced code that needs refinement.
22
39
  - You are here to solve the hard problems manually.
23
40
  - You have full permission to edit files directly.
24
41
 
42
+ ## 🚨 MAGIC WORD: [SYNC MANIFESTS] / [SYNC]
43
+ If the human user types **`[SYNC MANIFESTS]`** or **`[SYNC]`** (or explicitly requests a manifest sync), immediately suspend feature development and switch to Project Manager mode:
44
+ 1. Find all `.eck/*.md` files with `[STUB]` markers. Analyze the codebase to resolve them.
45
+ 2. Review `ROADMAP.md` and `TECH_DEBT.md`. Cross-reference with the actual code and remove/check off completed items.
46
+ 3. Update `CONTEXT.md` and `ARCHITECTURE.md` if the system has evolved.
47
+ 4. Use the **`eck_manifest_edit`** tool to apply these updates atomically. Do not read `JOURNAL.md`.
48
+ 5. Call `eck_finish_task` when the audit is complete.
49
+
50
+ ## 🧠 KNOWLEDGE DISTILLATION (POST-FINISH)
51
+ **ONLY** after tasks that changed the project's architecture, added major features, or revealed non-obvious system behavior (e.g., multi-file refactors, new subsystems, tricky debugging that uncovered hidden dependencies).
52
+ Do NOT offer this for routine fixes, config tweaks, or small edits.
53
+ **Call `eck_finish_task` first** — never delay the finish. Then, in the same response, offer:
54
+ > "I learned some things about the architecture during this task. Want me to update the `.eck/` manifests before I lose this context?"
55
+ > **[DEBUG] Context info available to me:** [state whether you can see any context window usage %, token counts, or compaction warnings — or "none, no context metrics visible"]
56
+ Include this offer in your `eck_finish_task` status so the Architect sees it too.
57
+ If the user says yes — just edit the files and commit. Do NOT call `eck_finish_task` again for it.
58
+
25
59
  ## 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.
60
+ 1. Check the `.eck/RUNTIME_STATE.md` and verify actual running processes.
61
+ 2. Read the code. If the Architect's hypothesis is wrong, discard it and find the real bug.
62
+ 3. Fix the bugs / Implement the feature.
63
+ 4. Verify functionality manually via browser/curl/logs/DB checks.
64
+ 5. **Loop:** If verification fails, fix it immediately. Do not ask for permission.
65
+ 6. **Blocked?** Use the `eck_fail_task` tool to abort safely without committing broken code.