kodelyth-ecc 1.7.2 → 1.7.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.
Files changed (46) hide show
  1. package/.github/ISSUE_TEMPLATE/config.yml +8 -0
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +41 -0
  3. package/.github/ISSUE_TEMPLATE/good_first_issue.md +36 -0
  4. package/CHANGELOG.md +59 -0
  5. package/GITHUB_SETUP.md +553 -0
  6. package/README.md +51 -6
  7. package/VERSION +1 -1
  8. package/actions/ecc-review/README.md +7 -7
  9. package/bundles/enterprise.md +1 -1
  10. package/bundles/indie-hacker.md +1 -1
  11. package/bundles/red-team.md +1 -1
  12. package/docs/supply-chain.md +1 -1
  13. package/package.json +4 -1
  14. package/rules/common/memory-protocol.md +35 -4
  15. package/scripts/dashboard/data.js +261 -4
  16. package/scripts/dashboard/server.js +28 -3
  17. package/scripts/dashboard/static/index.html +63 -3
  18. package/social/card-install.svg +1 -1
  19. package/social/card-main.svg +2 -2
  20. package/social/facebook-v150.svg +4 -4
  21. package/social/github-social-preview.svg +3 -3
  22. package/social/hype-compound-learning.svg +117 -0
  23. package/social/hype-devil-mode.svg +228 -0
  24. package/social/hype-mcp-server.svg +136 -0
  25. package/social/hype-parallel-agents.svg +150 -0
  26. package/social/hype-stats-hero.svg +126 -0
  27. package/social/readme-hero.svg +4 -4
  28. package/social/section-mcp.svg +1 -1
  29. package/social/twitter-threads.md +621 -0
  30. package/social/x-card-agents-grid.svg +2 -2
  31. package/social/x-card-free.svg +2 -2
  32. package/social/x-card-hook.svg +5 -5
  33. package/tests/dashboard/data.test.js +156 -0
  34. package/tests/dashboard/server.test.js +17 -0
  35. package/wiki/FAQ.md +1 -1
  36. package/wiki/Home.md +5 -3
  37. package/wiki/Installation-Guide.md +2 -2
  38. package/MARKETING_PLAN.md +0 -893
  39. package/cat +0 -0
  40. package/social/facebook-group/POST.md +0 -121
  41. package/social/facebook-group/fb-1-3am-debug.png +0 -0
  42. package/social/facebook-group/fb-1-3am-debug.svg +0 -97
  43. package/social/facebook-group/fb-2-cpu-upgrade.png +0 -0
  44. package/social/facebook-group/fb-2-cpu-upgrade.svg +0 -132
  45. package/social/facebook-group/fb-3-before-after.png +0 -0
  46. package/social/facebook-group/fb-3-before-after.svg +0 -94
@@ -233,3 +233,159 @@ test('tokenBudgetSnapshot: silently skips malformed budget files', () => {
233
233
  assert.equal(r.total_tokens, 100);
234
234
  } finally { cleanup(dir); }
235
235
  });
236
+
237
+ // ── ide sessions (claude code / windsurf / antigravity) ─────────────────────
238
+
239
+ function emptyIdeOpts(label) {
240
+ // Build a fully-empty IDE options bag so each call only sees what the test feeds it.
241
+ const cc = tmpDir(`kodelyth-cc-${label}-`); cleanup(cc);
242
+ const ws = tmpDir(`kodelyth-ws-${label}-`); cleanup(ws);
243
+ const wn = tmpDir(`kodelyth-wn-${label}-`); cleanup(wn);
244
+ const cu = tmpDir(`kodelyth-cu-${label}-`); cleanup(cu);
245
+ const ag = tmpDir(`kodelyth-ag-${label}-`); cleanup(ag);
246
+ const cwd = tmpDir(`kodelyth-cwd-${label}-`);
247
+ return {
248
+ claudeProjectsDir: cc, windsurfDir: ws, windsurfNextDir: wn,
249
+ cursorDir: cu, antigravityDir: ag, extraDirs: [], cwd,
250
+ _cleanup: () => cleanup(cwd),
251
+ };
252
+ }
253
+
254
+ test('ideSessionsList: missing dirs return []', () => {
255
+ const o = emptyIdeOpts('missing');
256
+ try {
257
+ const list = data.ideSessionsList(o);
258
+ assert.deepEqual(list, []);
259
+ } finally { o._cleanup(); }
260
+ });
261
+
262
+ test('ideSessionsList: surfaces claude-code sessions sorted by mtime desc', async () => {
263
+ const o = emptyIdeOpts('cc-sort');
264
+ o.claudeProjectsDir = tmpDir('kodelyth-cc-');
265
+ try {
266
+ const proj = path.join(o.claudeProjectsDir, '-Users-alice-myproject');
267
+ fs.mkdirSync(proj, { recursive: true });
268
+ fs.writeFileSync(path.join(proj, 'aaa-old.jsonl'), '{"x":1}\n');
269
+ await new Promise(r => setTimeout(r, 20));
270
+ fs.writeFileSync(path.join(proj, 'bbb-new.jsonl'), '{"x":2}\n');
271
+
272
+ const list = data.ideSessionsList({ ...o, limit: 10 });
273
+ assert.equal(list.length, 2);
274
+ assert.equal(list[0].platform, 'claude-code');
275
+ assert.equal(list[0].session_id, 'bbb-new', 'newest first');
276
+ assert.equal(list[1].session_id, 'aaa-old');
277
+ assert.match(list[0].project, /alice/, 'project path is decoded best-effort');
278
+ } finally { cleanup(o.claudeProjectsDir); o._cleanup(); }
279
+ });
280
+
281
+ test('ideSessionsList: detects antigravity .agent/ in cwd', () => {
282
+ const o = emptyIdeOpts('ag-cwd');
283
+ try {
284
+ fs.mkdirSync(path.join(o.cwd, '.agent'), { recursive: true });
285
+ const list = data.ideSessionsList(o);
286
+ assert.equal(list.length, 1);
287
+ assert.equal(list[0].platform, 'antigravity');
288
+ assert.equal(list[0].project, o.cwd);
289
+ } finally { o._cleanup(); }
290
+ });
291
+
292
+ test('ideSessionsList: detects windsurf-next state files', () => {
293
+ const o = emptyIdeOpts('wn');
294
+ o.windsurfNextDir = tmpDir('kodelyth-wn-pop-');
295
+ try {
296
+ fs.writeFileSync(path.join(o.windsurfNextDir, 'state.json'), '{}');
297
+ const list = data.ideSessionsList(o);
298
+ assert.equal(list.length, 1);
299
+ assert.equal(list[0].platform, 'windsurf-next');
300
+ assert.equal(list[0].session_id, 'state.json');
301
+ } finally { cleanup(o.windsurfNextDir); o._cleanup(); }
302
+ });
303
+
304
+ test('ideSessionsList: detects cursor workspace dirs', () => {
305
+ const o = emptyIdeOpts('cu');
306
+ o.cursorDir = tmpDir('kodelyth-cu-pop-');
307
+ try {
308
+ fs.mkdirSync(path.join(o.cursorDir, 'abc123hash'), { recursive: true });
309
+ const list = data.ideSessionsList(o);
310
+ assert.equal(list.length, 1);
311
+ assert.equal(list[0].platform, 'cursor');
312
+ assert.equal(list[0].session_id, 'abc123hash');
313
+ } finally { cleanup(o.cursorDir); o._cleanup(); }
314
+ });
315
+
316
+ test('ideSessionsList: KODELYTH_EXTRA_IDE_WATCH paths surface as custom platform', () => {
317
+ const o = emptyIdeOpts('extra');
318
+ const extra = tmpDir('kodelyth-extra-');
319
+ try {
320
+ fs.writeFileSync(path.join(extra, 'log.txt'), 'hi');
321
+ o.extraDirs = [extra];
322
+ const list = data.ideSessionsList(o);
323
+ const customs = list.filter(s => s.platform === 'custom');
324
+ assert.equal(customs.length, 1);
325
+ assert.equal(customs[0].path, extra);
326
+ } finally { cleanup(extra); o._cleanup(); }
327
+ });
328
+
329
+ test('extraIdeWatchDirs: splits comma/semicolon/colon separated list', () => {
330
+ const oldEnv = process.env.KODELYTH_EXTRA_IDE_WATCH;
331
+ try {
332
+ process.env.KODELYTH_EXTRA_IDE_WATCH = '/a/b , /c/d ; /e/f : /g/h';
333
+ const dirs = data._internals.extraIdeWatchDirs();
334
+ assert.deepEqual(dirs, ['/a/b', '/c/d', '/e/f', '/g/h']);
335
+ } finally {
336
+ if (oldEnv === undefined) delete process.env.KODELYTH_EXTRA_IDE_WATCH;
337
+ else process.env.KODELYTH_EXTRA_IDE_WATCH = oldEnv;
338
+ }
339
+ });
340
+
341
+ test('defaultCursorWorkspaceDir: returns an OS-appropriate path', () => {
342
+ const oldEnv = process.env.KODELYTH_CURSOR_DIR;
343
+ delete process.env.KODELYTH_CURSOR_DIR;
344
+ try {
345
+ const p = data._internals.defaultCursorWorkspaceDir();
346
+ assert.match(p, /Cursor/);
347
+ } finally {
348
+ if (oldEnv !== undefined) process.env.KODELYTH_CURSOR_DIR = oldEnv;
349
+ }
350
+ });
351
+
352
+ test('getMaxIdeMtime: returns 0 when no IDE dirs exist', () => {
353
+ const o = emptyIdeOpts('mtime-zero');
354
+ try {
355
+ const m = data._internals.getMaxIdeMtime(o);
356
+ assert.equal(m, 0);
357
+ } finally { o._cleanup(); }
358
+ });
359
+
360
+ test('getMaxIdeMtime: reflects newest mtime across watched IDE files', async () => {
361
+ const o = emptyIdeOpts('mtime-new');
362
+ o.claudeProjectsDir = tmpDir('kodelyth-cc-mtime-');
363
+ try {
364
+ const proj = path.join(o.claudeProjectsDir, '-tmp-x');
365
+ fs.mkdirSync(proj, { recursive: true });
366
+ fs.writeFileSync(path.join(proj, 'first.jsonl'), 'x');
367
+ await new Promise(r => setTimeout(r, 20));
368
+ fs.writeFileSync(path.join(proj, 'second.jsonl'), 'y');
369
+
370
+ const m = data._internals.getMaxIdeMtime(o);
371
+ const newestStat = fs.statSync(path.join(proj, 'second.jsonl'));
372
+ assert.equal(m, newestStat.mtimeMs);
373
+ } finally { cleanup(o.claudeProjectsDir); o._cleanup(); }
374
+ });
375
+
376
+ test('getMaxIdeMtime: picks up windsurf-next + cursor + extra dirs', () => {
377
+ const o = emptyIdeOpts('mtime-all');
378
+ o.windsurfNextDir = tmpDir('kodelyth-wn-mt-');
379
+ o.cursorDir = tmpDir('kodelyth-cu-mt-');
380
+ const extra = tmpDir('kodelyth-extra-mt-');
381
+ o.extraDirs = [extra];
382
+ try {
383
+ fs.writeFileSync(path.join(o.windsurfNextDir, 's.json'), 'a');
384
+ fs.mkdirSync(path.join(o.cursorDir, 'workspace1'), { recursive: true });
385
+ fs.writeFileSync(path.join(extra, 'note.txt'), 'b');
386
+ const m = data._internals.getMaxIdeMtime(o);
387
+ assert.ok(m > 0, 'should return a positive mtime');
388
+ } finally {
389
+ cleanup(o.windsurfNextDir); cleanup(o.cursorDir); cleanup(extra); o._cleanup();
390
+ }
391
+ });
@@ -150,6 +150,23 @@ test('GET /api/sessions/:nonexistent returns 404', async () => {
150
150
  } finally { await shutdown(server); }
151
151
  });
152
152
 
153
+ test('GET /api/ide-sessions returns array', async () => {
154
+ const server = createServer();
155
+ const port = await listenEphemeral(server);
156
+ try {
157
+ const r = await get(port, '/api/ide-sessions?limit=3');
158
+ assert.equal(r.status, 200);
159
+ const body = JSON.parse(r.body);
160
+ assert.ok(Array.isArray(body.sessions));
161
+ // Each entry, if any, has the expected shape.
162
+ for (const s of body.sessions) {
163
+ assert.ok(['claude-code', 'windsurf', 'antigravity'].includes(s.platform));
164
+ assert.ok(typeof s.session_id === 'string');
165
+ assert.ok(typeof s.modified === 'string');
166
+ }
167
+ } finally { await shutdown(server); }
168
+ });
169
+
153
170
  test('GET /api/token-budget returns aggregate shape', async () => {
154
171
  const server = createServer();
155
172
  const port = await listenEphemeral(server);
package/wiki/FAQ.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  **What is Kodelyth ECC?**
8
8
 
9
- An AI coding toolkit (v1.7.1) that installs into 11 AI coding platforms (13 install targets). It adds 70 specialist agents (including 8 adversarial devil-mode agents), 194 skills, 97 slash commands, 20+ automation hooks, and a compound learning system. Zero cloud, zero telemetry, all local.
9
+ An AI coding toolkit (v1.7.4) that installs into 11 AI coding platforms (13 install targets). It adds 70 specialist agents (including 8 adversarial devil-mode agents), 194 skills, 97 slash commands, 20+ automation hooks, and a compound learning system. Zero cloud, zero telemetry, all local.
10
10
 
11
11
  **Is it free?**
12
12
 
package/wiki/Home.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Kodelyth Enhanced Coding Companion** — production-grade AI coding toolkit for Claude Code, Windsurf, Cursor, Codex CLI, Google Antigravity, and more.
4
4
 
5
- > Version: **v1.7.2** · Agents: **70** (including 8 adversarial) · Skills: **194** · Commands: **97** (including 8 parallel) · Hooks: **22+** · Platforms: **11** · Tests: **336**
5
+ > Version: **v1.7.4** · Agents: **70** (including 8 adversarial) · Skills: **194** · Commands: **97** (including 8 parallel) · Hooks: **22+** · Platforms: **11** · Tests: **348**
6
6
 
7
7
  ---
8
8
 
@@ -56,7 +56,7 @@ After install, type `/kodelyth-quickstart` in your AI tool to begin.
56
56
 
57
57
  ---
58
58
 
59
- ## Key Features (v1.7.0)
59
+ ## Key Features (v1.7.4)
60
60
 
61
61
  ### Semantic Intent Routing
62
62
 
@@ -91,7 +91,7 @@ Fire multiple specialist agents at once and get results in 10-15 minutes instead
91
91
  | `/onboard` | code-explorer + architect + doc-updater | 45 min → 10 min |
92
92
  | `/devil-mode` | prompt-injection-hunter + supply-chain-auditor + secret-hunter + license-violation-finder (or all 8 with `--all`) | 60 min → 15 min |
93
93
 
94
- ### Adversarial Devil-Mode Agents (v1.7.0 new)
94
+ ### Adversarial Devil-Mode Agents (v1.7.0)
95
95
 
96
96
  Dedicated red-team mode fires 4-8 specialized adversarial agents to find vulnerabilities your team missed:
97
97
 
@@ -197,6 +197,8 @@ Kodelyth ECC installs on 11 AI coding platforms. Feature depth varies — hooks
197
197
 
198
198
  | Version | Headline |
199
199
  |---|---|
200
+ | **v1.7.4** | Real-time IDE-aware dashboard (Claude Code + Windsurf + Windsurf-Next + Cursor + Antigravity), cross-IDE memory protocol via MCP tools, `KODELYTH_EXTRA_IDE_WATCH` env var, 3 s SSE realtime, 348 tests |
201
+ | **v1.7.3** | Social hype pack (5 X/Twitter SVGs + 5 thread scripts), full SVG version sync, GitHub issue templates, repo polish |
200
202
  | **v1.7.0** | Adversarial devil-mode (8 agents), MCP server, local dashboard, swarm orchestrator, cost-aware routing, self-evolving memory, SLSA L3 + SBOM, 11 platforms, 194 skills |
201
203
  | **v1.6.0** | 8 adversarial devil-mode agents, power bundles, 6 new IDE platform targets, 97 commands |
202
204
  | **v1.5.3** | Semantic intent routing — intent not keywords, code/trace paste detection, 62 agents, 188 skills |
@@ -276,7 +276,7 @@ export ECC_DISABLED_HOOKS=kodelyth:prompt:recall,kodelyth:post-edit:test-reminde
276
276
  npm test
277
277
  ```
278
278
 
279
- If tests fail, file an issue with the output. Most installs pass all 336 tests.
279
+ If tests fail, file an issue with the output. Most installs pass all 348 tests.
280
280
 
281
281
  ---
282
282
 
@@ -289,6 +289,6 @@ After installing, verify these work:
289
289
  - [ ] `/memory` shows your memory store
290
290
  - [ ] `npx kodelyth-ecc mcp` starts the server
291
291
  - [ ] `npx kodelyth-ecc dashboard` opens the dashboard
292
- - [ ] `npm test` passes all 336 tests (Claude Code only)
292
+ - [ ] `npm test` passes all 348 tests (Claude Code only)
293
293
 
294
294
  If any step fails, re-run the installer or file an issue.