kodelyth-ecc 1.7.5 → 1.8.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.
- package/CHANGELOG.md +16 -3
- package/CLAUDE.md +1 -1
- package/README.md +8 -9
- package/SECURITY.md +5 -6
- package/bundles/enterprise.md +1 -1
- package/bundles/indie-hacker.md +1 -1
- package/bundles/red-team.md +1 -1
- package/hooks/hooks.json +13 -0
- package/hooks/memory/auto-resolve.js +68 -0
- package/hooks/memory/capture-correction.js +16 -0
- package/hooks/memory/capture-stop.js +70 -14
- package/package.json +1 -1
- package/rules/common/agents.md +1 -1
- package/rules/common/self-improvement-workflow.md +2 -2
- package/scripts/dashboard/data.js +1 -1
- package/scripts/dashboard/server.js +1 -1
- package/scripts/memory/instincts.js +282 -0
- package/scripts/memory/store.js +104 -0
- package/social/card-agents.svg +1 -1
- package/social/card-install.svg +1 -1
- package/social/card-main.svg +1 -1
- package/social/facebook-v150.svg +14 -13
- package/social/fb-ad-main.svg +128 -0
- package/social/fb-post-features.svg +118 -0
- package/social/fb-post-launch.svg +144 -0
- package/social/fb-post-platforms.svg +135 -0
- package/social/github-social-preview.svg +119 -28
- package/social/hype-compound-learning.svg +9 -9
- package/social/hype-devil-mode.svg +8 -8
- package/social/hype-mcp-server.svg +8 -8
- package/social/hype-parallel-agents.svg +8 -8
- package/social/hype-stats-hero.svg +3 -3
- package/social/og-image.svg +116 -30
- package/social/readme-hero.svg +4 -4
- package/social/section-mcp.svg +1 -1
- package/social/twitter-threads.md +3 -3
- package/social/x-card-agents-grid.svg +2 -2
- package/social/x-card-free.svg +2 -2
- package/social/x-card-hook.svg +5 -5
- package/tests/memory/instincts.test.js +258 -0
- package/tests/memory/store.test.js +82 -0
- package/wiki/FAQ.md +1 -1
- package/wiki/Home.md +3 -3
- package/wiki/Installation-Guide.md +2 -2
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Kodelyth ECC — Structured Instinct Schema (Improvement B)
|
|
3
|
+
//
|
|
4
|
+
// Stores learned instincts as typed JSON records in:
|
|
5
|
+
// ~/.kodelyth/memory/instincts.jsonl
|
|
6
|
+
//
|
|
7
|
+
// Each instinct has: pattern, trigger, confidence, last_used, outcome, decay.
|
|
8
|
+
// This replaces free-form markdown bullets for machine-readable learning.
|
|
9
|
+
// The lessons.md file is still written for human readability — this runs
|
|
10
|
+
// in parallel, enabling deduplication, conflict detection, and decay.
|
|
11
|
+
//
|
|
12
|
+
// Schema:
|
|
13
|
+
// id — deterministic hash (stable across re-runs)
|
|
14
|
+
// pattern — short slug: "use-pnpm-not-npm", "no-console-logs"
|
|
15
|
+
// rule — full human-readable text of the rule
|
|
16
|
+
// scope — "project" | "global"
|
|
17
|
+
// trigger — keywords/phrases that activate this instinct
|
|
18
|
+
// confidence — 0.0–1.0 (starts at 0.7, confirmed → 1.0, decays with age)
|
|
19
|
+
// source — "correction" | "manual" | "evolved"
|
|
20
|
+
// created — ISO date
|
|
21
|
+
// last_used — ISO date
|
|
22
|
+
// use_count — how many sessions this was applied
|
|
23
|
+
// outcome — null | "success" | "failure"
|
|
24
|
+
// project_path — absolute path of origin project
|
|
25
|
+
// stale — true if unused for 30+ days (set by decay check)
|
|
26
|
+
// =============================================================================
|
|
27
|
+
|
|
28
|
+
'use strict';
|
|
29
|
+
|
|
30
|
+
const fs = require('fs');
|
|
31
|
+
const os = require('os');
|
|
32
|
+
const path = require('path');
|
|
33
|
+
const crypto = require('crypto');
|
|
34
|
+
|
|
35
|
+
const MEMORY_DIR = process.env.KODELYTH_MEMORY_DIR
|
|
36
|
+
|| path.join(os.homedir(), '.kodelyth', 'memory');
|
|
37
|
+
|
|
38
|
+
const INSTINCTS_FILE = path.join(MEMORY_DIR, 'instincts.jsonl');
|
|
39
|
+
const STALE_DAYS = 30;
|
|
40
|
+
|
|
41
|
+
// ── Helpers ──────────────────────────────────────────────────────────────────
|
|
42
|
+
|
|
43
|
+
function ensureDir() {
|
|
44
|
+
if (!fs.existsSync(MEMORY_DIR)) fs.mkdirSync(MEMORY_DIR, { recursive: true });
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function slugify(text) {
|
|
48
|
+
return String(text || '')
|
|
49
|
+
.toLowerCase()
|
|
50
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
51
|
+
.replace(/^-+|-+$/g, '')
|
|
52
|
+
.slice(0, 60) || 'rule';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function deterministicId(rule, projectPath) {
|
|
56
|
+
return crypto
|
|
57
|
+
.createHash('sha256')
|
|
58
|
+
.update(`${rule}::${projectPath || ''}`)
|
|
59
|
+
.digest('hex')
|
|
60
|
+
.slice(0, 12);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function extractTriggers(ruleText) {
|
|
64
|
+
// Heuristic: extract key words that would activate this rule
|
|
65
|
+
const FILLER = new Set(['use','don\'t','never','always','please','stop','avoid',
|
|
66
|
+
'instead','of','not','the','a','an','and','or','in','on','at','to','is',
|
|
67
|
+
'are','was','were','do','does','did','should','would','could']);
|
|
68
|
+
return ruleText
|
|
69
|
+
.toLowerCase()
|
|
70
|
+
.replace(/[^a-z0-9\s]/g, ' ')
|
|
71
|
+
.split(/\s+/)
|
|
72
|
+
.filter(w => w.length >= 3 && !FILLER.has(w))
|
|
73
|
+
.slice(0, 6);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function today() {
|
|
77
|
+
return new Date().toISOString().split('T')[0];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function daysSince(isoDate) {
|
|
81
|
+
if (!isoDate) return 999;
|
|
82
|
+
return Math.floor((Date.now() - new Date(isoDate).getTime()) / 86400000);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// ── Read / Write ──────────────────────────────────────────────────────────────
|
|
86
|
+
|
|
87
|
+
function loadAll() {
|
|
88
|
+
if (!fs.existsSync(INSTINCTS_FILE)) return [];
|
|
89
|
+
return fs.readFileSync(INSTINCTS_FILE, 'utf8')
|
|
90
|
+
.split('\n')
|
|
91
|
+
.filter(Boolean)
|
|
92
|
+
.map(line => { try { return JSON.parse(line); } catch { return null; } })
|
|
93
|
+
.filter(Boolean);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function saveAll(instincts) {
|
|
97
|
+
ensureDir();
|
|
98
|
+
fs.writeFileSync(
|
|
99
|
+
INSTINCTS_FILE,
|
|
100
|
+
instincts.map(i => JSON.stringify(i)).join('\n') + '\n',
|
|
101
|
+
'utf8'
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// ── Public API ────────────────────────────────────────────────────────────────
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Add a new instinct from a correction string.
|
|
109
|
+
* If a record with the same id already exists, increments use_count.
|
|
110
|
+
* Returns the instinct record.
|
|
111
|
+
*/
|
|
112
|
+
function captureFromCorrection(ruleText, projectPath, scope = 'project') {
|
|
113
|
+
ensureDir();
|
|
114
|
+
const id = deterministicId(ruleText, projectPath);
|
|
115
|
+
const all = loadAll();
|
|
116
|
+
|
|
117
|
+
const existing = all.find(i => i.id === id);
|
|
118
|
+
if (existing) {
|
|
119
|
+
existing.use_count = (existing.use_count || 1) + 1;
|
|
120
|
+
existing.last_used = today();
|
|
121
|
+
existing.confidence = Math.min(1.0, (existing.confidence || 0.7) + 0.1);
|
|
122
|
+
existing.stale = false;
|
|
123
|
+
saveAll(all);
|
|
124
|
+
return existing;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const instinct = {
|
|
128
|
+
id,
|
|
129
|
+
pattern: slugify(ruleText),
|
|
130
|
+
rule: ruleText.trim(),
|
|
131
|
+
scope,
|
|
132
|
+
trigger: extractTriggers(ruleText),
|
|
133
|
+
confidence: 0.7,
|
|
134
|
+
source: 'correction',
|
|
135
|
+
created: today(),
|
|
136
|
+
last_used: today(),
|
|
137
|
+
use_count: 1,
|
|
138
|
+
outcome: null,
|
|
139
|
+
project_path: projectPath || null,
|
|
140
|
+
stale: false,
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
fs.appendFileSync(INSTINCTS_FILE, JSON.stringify(instinct) + '\n', 'utf8');
|
|
144
|
+
return instinct;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Record the outcome of an instinct (success/failure) by id.
|
|
149
|
+
* A failure reduces confidence; a success boosts it.
|
|
150
|
+
*/
|
|
151
|
+
function recordOutcome(id, outcome) {
|
|
152
|
+
const all = loadAll();
|
|
153
|
+
const instinct = all.find(i => i.id === id);
|
|
154
|
+
if (!instinct) return null;
|
|
155
|
+
|
|
156
|
+
instinct.outcome = outcome;
|
|
157
|
+
instinct.last_used = today();
|
|
158
|
+
|
|
159
|
+
if (outcome === 'success') {
|
|
160
|
+
instinct.confidence = Math.min(1.0, (instinct.confidence || 0.7) + 0.15);
|
|
161
|
+
} else if (outcome === 'failure') {
|
|
162
|
+
instinct.confidence = Math.max(0.0, (instinct.confidence || 0.7) - 0.3);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
saveAll(all);
|
|
166
|
+
return instinct;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Decay check (Improvement D).
|
|
171
|
+
* Marks instincts unused for STALE_DAYS+ as stale: true.
|
|
172
|
+
* Returns list of newly-stale instincts for review prompting.
|
|
173
|
+
*/
|
|
174
|
+
function runDecayCheck() {
|
|
175
|
+
const all = loadAll();
|
|
176
|
+
const newlyStale = [];
|
|
177
|
+
|
|
178
|
+
for (const instinct of all) {
|
|
179
|
+
const age = daysSince(instinct.last_used);
|
|
180
|
+
const wasStale = instinct.stale;
|
|
181
|
+
instinct.stale = age >= STALE_DAYS;
|
|
182
|
+
if (instinct.stale && !wasStale) {
|
|
183
|
+
newlyStale.push(instinct);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (newlyStale.length > 0) saveAll(all);
|
|
188
|
+
return newlyStale;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Return all instincts, optionally filtered.
|
|
193
|
+
* Filters: { scope, stale, minConfidence, projectPath }
|
|
194
|
+
*/
|
|
195
|
+
function list({ scope, stale, minConfidence, projectPath } = {}) {
|
|
196
|
+
let all = loadAll();
|
|
197
|
+
if (scope !== undefined) all = all.filter(i => i.scope === scope);
|
|
198
|
+
if (stale !== undefined) all = all.filter(i => Boolean(i.stale) === stale);
|
|
199
|
+
if (minConfidence !== undefined) all = all.filter(i => (i.confidence || 0) >= minConfidence);
|
|
200
|
+
if (projectPath !== undefined) all = all.filter(i => i.project_path === projectPath);
|
|
201
|
+
return all;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Prune instincts with confidence below threshold (auto-cleanup of bad patterns).
|
|
206
|
+
*/
|
|
207
|
+
function pruneWeak(threshold = 0.2) {
|
|
208
|
+
const all = loadAll();
|
|
209
|
+
const kept = all.filter(i => (i.confidence || 0.7) >= threshold);
|
|
210
|
+
const pruned = all.length - kept.length;
|
|
211
|
+
if (pruned > 0) saveAll(kept);
|
|
212
|
+
return pruned;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Improvement C: outcome tracking via store.js bridge.
|
|
217
|
+
*
|
|
218
|
+
* Called when a follow-up file edit implies a previous instinct didn't stick.
|
|
219
|
+
* Finds instincts that match both the project_path AND a fragment of the
|
|
220
|
+
* problem text, then records a failure outcome on each match.
|
|
221
|
+
*
|
|
222
|
+
* This is intentionally fuzzy: a partial match (>20% token overlap between
|
|
223
|
+
* problemHint and instinct.rule) is enough to trigger a downgrade. The goal
|
|
224
|
+
* is to surface bad patterns, not to be surgically precise.
|
|
225
|
+
*
|
|
226
|
+
* Returns the list of downgraded instinct ids.
|
|
227
|
+
*/
|
|
228
|
+
function recordOutcomeByProject(projectPath, problemHint, outcome) {
|
|
229
|
+
if (!projectPath && !problemHint) return [];
|
|
230
|
+
const all = loadAll();
|
|
231
|
+
const changed = [];
|
|
232
|
+
|
|
233
|
+
const hintTokens = problemHint
|
|
234
|
+
? new Set(
|
|
235
|
+
String(problemHint)
|
|
236
|
+
.toLowerCase()
|
|
237
|
+
.replace(/[^a-z0-9\s]/g, ' ')
|
|
238
|
+
.split(/\s+/)
|
|
239
|
+
.filter(t => t.length >= 3)
|
|
240
|
+
)
|
|
241
|
+
: null;
|
|
242
|
+
|
|
243
|
+
for (const instinct of all) {
|
|
244
|
+
// Project match (when provided)
|
|
245
|
+
if (projectPath && instinct.project_path && instinct.project_path !== projectPath) continue;
|
|
246
|
+
|
|
247
|
+
// Problem text fuzzy match (when provided)
|
|
248
|
+
if (hintTokens && hintTokens.size > 0) {
|
|
249
|
+
const ruleTokens = String(instinct.rule || '')
|
|
250
|
+
.toLowerCase()
|
|
251
|
+
.replace(/[^a-z0-9\s]/g, ' ')
|
|
252
|
+
.split(/\s+/)
|
|
253
|
+
.filter(t => t.length >= 3);
|
|
254
|
+
const overlap = ruleTokens.filter(t => hintTokens.has(t)).length;
|
|
255
|
+
const ratio = overlap / Math.max(hintTokens.size, 1);
|
|
256
|
+
if (ratio < 0.2) continue; // < 20% overlap — not a match
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
instinct.outcome = outcome;
|
|
260
|
+
instinct.last_used = today();
|
|
261
|
+
if (outcome === 'success') {
|
|
262
|
+
instinct.confidence = Math.min(1.0, (instinct.confidence || 0.7) + 0.15);
|
|
263
|
+
} else if (outcome === false || outcome === 'failure') {
|
|
264
|
+
instinct.confidence = Math.max(0.0, (instinct.confidence || 0.7) - 0.3);
|
|
265
|
+
}
|
|
266
|
+
changed.push(instinct.id);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (changed.length > 0) saveAll(all);
|
|
270
|
+
return changed;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
module.exports = {
|
|
274
|
+
captureFromCorrection,
|
|
275
|
+
recordOutcome,
|
|
276
|
+
recordOutcomeByProject,
|
|
277
|
+
runDecayCheck,
|
|
278
|
+
list,
|
|
279
|
+
pruneWeak,
|
|
280
|
+
INSTINCTS_FILE,
|
|
281
|
+
STALE_DAYS,
|
|
282
|
+
};
|
package/scripts/memory/store.js
CHANGED
|
@@ -257,6 +257,106 @@ function forget(memoryId) {
|
|
|
257
257
|
return found;
|
|
258
258
|
}
|
|
259
259
|
|
|
260
|
+
// ── Improvement C: outcome tracking ──────────────────────────────────────────
|
|
261
|
+
// Mark a memory as resolved:true (success) or resolved:false (failure).
|
|
262
|
+
// Called automatically by the PostToolUse hook when an edited file matches
|
|
263
|
+
// a memory's files[] list — a follow-up fix implies the previous approach
|
|
264
|
+
// didn't fully work, so resolved=false. The user can also call this manually.
|
|
265
|
+
//
|
|
266
|
+
// Side-effect: also propagates to instincts.js if the instinct module exists,
|
|
267
|
+
// so low-confidence instincts sourced from the same session get downgraded.
|
|
268
|
+
function resolveMemory(memoryId, resolved) {
|
|
269
|
+
if (!fs.existsSync(PATHS.log)) return false;
|
|
270
|
+
const lines = fs.readFileSync(PATHS.log, 'utf8').split('\n').filter(Boolean);
|
|
271
|
+
let found = false;
|
|
272
|
+
const updated = lines.map(line => {
|
|
273
|
+
try {
|
|
274
|
+
const m = JSON.parse(line);
|
|
275
|
+
if (m.id === memoryId && !m.deleted) {
|
|
276
|
+
found = true;
|
|
277
|
+
return JSON.stringify({
|
|
278
|
+
...m,
|
|
279
|
+
resolved,
|
|
280
|
+
resolved_at: new Date().toISOString(),
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
return line;
|
|
284
|
+
} catch {
|
|
285
|
+
return line;
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
if (found) {
|
|
289
|
+
fs.writeFileSync(PATHS.log, updated.join('\n') + '\n');
|
|
290
|
+
}
|
|
291
|
+
return found;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Find unresolved memories whose files[] overlap with the given file path.
|
|
295
|
+
// Returns [ { id, problem, files, captured_at } ] — caller decides what to do.
|
|
296
|
+
function findMemoriesForFile(filePath, options = {}) {
|
|
297
|
+
const { projectRoot = null, limit = 5 } = options;
|
|
298
|
+
if (!fs.existsSync(PATHS.log)) return [];
|
|
299
|
+
|
|
300
|
+
const normFile = path.normalize(filePath);
|
|
301
|
+
const lines = fs.readFileSync(PATHS.log, 'utf8').split('\n').filter(Boolean);
|
|
302
|
+
const matches = [];
|
|
303
|
+
|
|
304
|
+
for (const line of lines) {
|
|
305
|
+
let m;
|
|
306
|
+
try { m = JSON.parse(line); } catch { continue; }
|
|
307
|
+
if (m.deleted || m.resolved !== undefined) continue; // skip already resolved
|
|
308
|
+
if (!Array.isArray(m.files) || m.files.length === 0) continue;
|
|
309
|
+
if (projectRoot && m.project_path && m.project_path !== projectRoot) continue;
|
|
310
|
+
|
|
311
|
+
const hit = m.files.some(f => {
|
|
312
|
+
const normF = path.normalize(String(f));
|
|
313
|
+
return normF === normFile || normFile.endsWith(normF) || normF.endsWith(normFile);
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
if (hit) {
|
|
317
|
+
matches.push({
|
|
318
|
+
id: m.id,
|
|
319
|
+
problem: m.problem,
|
|
320
|
+
approach: m.approach,
|
|
321
|
+
files: m.files,
|
|
322
|
+
captured_at: m.captured_at,
|
|
323
|
+
project_path: m.project_path,
|
|
324
|
+
});
|
|
325
|
+
if (matches.length >= limit) break;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
return matches;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Auto-resolve hook: called by PostToolUse (Write|Edit) with the file just edited.
|
|
333
|
+
// Marks any unresolved memory that listed this file as resolved:false, then
|
|
334
|
+
// nudges the instinct schema to downgrade the matching instinct's confidence.
|
|
335
|
+
function autoResolveOnEdit(filePath, projectRoot = null) {
|
|
336
|
+
const affected = findMemoriesForFile(filePath, { projectRoot });
|
|
337
|
+
if (affected.length === 0) return [];
|
|
338
|
+
|
|
339
|
+
const resolved = [];
|
|
340
|
+
for (const m of affected) {
|
|
341
|
+
const ok = resolveMemory(m.id, false);
|
|
342
|
+
if (ok) resolved.push(m);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// Propagate to instinct schema — best-effort only
|
|
346
|
+
try {
|
|
347
|
+
const instinctsPath = path.join(__dirname, 'instincts.js');
|
|
348
|
+
if (fs.existsSync(instinctsPath)) {
|
|
349
|
+
const instincts = require(instinctsPath);
|
|
350
|
+
for (const m of resolved) {
|
|
351
|
+
// Match by project_path + approximate problem text
|
|
352
|
+
instincts.recordOutcomeByProject(m.project_path, m.problem, false);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
} catch { /* never block */ }
|
|
356
|
+
|
|
357
|
+
return resolved;
|
|
358
|
+
}
|
|
359
|
+
|
|
260
360
|
function rebuildIndex() {
|
|
261
361
|
const memories = readMemories();
|
|
262
362
|
let index = { tokens: {}, docCount: 0, avgDocLength: 0, totalLength: 0 };
|
|
@@ -297,4 +397,8 @@ module.exports = {
|
|
|
297
397
|
stats,
|
|
298
398
|
tokenise,
|
|
299
399
|
projectHash,
|
|
400
|
+
// Improvement C
|
|
401
|
+
resolveMemory,
|
|
402
|
+
findMemoriesForFile,
|
|
403
|
+
autoResolveOnEdit,
|
|
300
404
|
};
|
package/social/card-agents.svg
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
<rect width="700" height="420" fill="none" stroke="#21262d" stroke-width="1" rx="12"/>
|
|
15
15
|
|
|
16
16
|
<!-- Header -->
|
|
17
|
-
<text x="28" y="42" font-size="16" font-weight="800" fill="#ffffff">
|
|
17
|
+
<text x="28" y="42" font-size="16" font-weight="800" fill="#ffffff">70 Agents — The Complete Roster</text>
|
|
18
18
|
<rect x="28" y="54" width="644" height="1" fill="#21262d"/>
|
|
19
19
|
|
|
20
20
|
<!-- Row 1 -->
|
package/social/card-install.svg
CHANGED
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
<text x="48" y="200" font-family="'Courier New', Courier, monospace" font-size="12" fill="#e6edf3"> npx kodelyth-ecc --target windsurf-project</text>
|
|
38
38
|
<text x="48" y="216" font-family="'Courier New', Courier, monospace" font-size="11" fill="#484f58"> # or Antigravity:</text>
|
|
39
39
|
<text x="48" y="232" font-family="'Courier New', Courier, monospace" font-size="12" fill="#e6edf3"> npx kodelyth-ecc --target antigravity</text>
|
|
40
|
-
<text x="48" y="256" font-family="'Courier New', Courier, monospace" font-size="11" fill="#10b981"> Installing v1.
|
|
40
|
+
<text x="48" y="256" font-family="'Courier New', Courier, monospace" font-size="11" fill="#10b981"> Installing v1.8.0 — 70 agents, 194 skills, 97 commands...</text>
|
|
41
41
|
<text x="48" y="292" font-family="'Courier New', Courier, monospace" font-size="11" fill="#10b981"> Done. Type /kodelyth-quickstart to begin.</text>
|
|
42
42
|
|
|
43
43
|
<!-- Footer -->
|
package/social/card-main.svg
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
<!-- Badge -->
|
|
19
19
|
<rect x="28" y="24" width="72" height="20" rx="10" fill="#a78bfa" fill-opacity="0.15" stroke="#a78bfa" stroke-opacity="0.4" stroke-width="1"/>
|
|
20
|
-
<text x="64" y="38" font-size="9" fill="#a78bfa" text-anchor="middle" font-weight="700" letter-spacing="0.5">v1.
|
|
20
|
+
<text x="64" y="38" font-size="9" fill="#a78bfa" text-anchor="middle" font-weight="700" letter-spacing="0.5">v1.8.0</text>
|
|
21
21
|
|
|
22
22
|
<!-- Title -->
|
|
23
23
|
<text x="28" y="88" font-size="38" font-weight="900" letter-spacing="-1.5" fill="#ffffff">Kodelyth</text>
|
package/social/facebook-v150.svg
CHANGED
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
|
|
39
39
|
<!-- Version + NEW badges -->
|
|
40
40
|
<rect x="80" y="28" width="76" height="24" rx="12" fill="#a78bfa" fill-opacity="0.15" stroke="#a78bfa" stroke-opacity="0.5" stroke-width="1"/>
|
|
41
|
-
<text x="118" y="44" font-size="11" fill="#a78bfa" text-anchor="middle" font-weight="700" letter-spacing="0.5">v1.
|
|
41
|
+
<text x="118" y="44" font-size="11" fill="#a78bfa" text-anchor="middle" font-weight="700" letter-spacing="0.5">v1.8.0</text>
|
|
42
42
|
|
|
43
43
|
<!-- Title -->
|
|
44
44
|
<text x="80" y="120" font-size="52" font-weight="900" letter-spacing="-2" fill="#ffffff">Kodelyth ECC</text>
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
<!-- Card 1: Compound Learning -->
|
|
51
51
|
<rect x="80" y="250" width="315" height="120" rx="10" fill="url(#card1)" stroke="#059669" stroke-opacity="0.35" stroke-width="1"/>
|
|
52
52
|
<rect x="80" y="250" width="4" height="120" rx="2" fill="#059669"/>
|
|
53
|
-
<text x="100" y="275" font-size="10" font-weight="700" fill="#10b981" letter-spacing="1">COMPOUND LEARNING v1.
|
|
53
|
+
<text x="100" y="275" font-size="10" font-weight="700" fill="#10b981" letter-spacing="1">COMPOUND LEARNING v1.8.0</text>
|
|
54
54
|
<text x="100" y="296" font-size="13" fill="#e6edf3">Corrections → tasks/lessons.md</text>
|
|
55
55
|
<text x="100" y="313" font-size="13" fill="#e6edf3">Next session: never repeats the mistake</text>
|
|
56
56
|
<text x="100" y="334" font-size="11" fill="#484f58">capture-correction.js · read-lessons.js</text>
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
<!-- Card 2: Parallel Agents -->
|
|
60
60
|
<rect x="410" y="250" width="315" height="120" rx="10" fill="#161b22" stroke="#f59e0b" stroke-opacity="0.35" stroke-width="1"/>
|
|
61
61
|
<rect x="410" y="250" width="4" height="120" rx="2" fill="#f59e0b"/>
|
|
62
|
-
<text x="430" y="275" font-size="10" font-weight="700" fill="#f59e0b" letter-spacing="1">PARALLEL AGENTS v1.
|
|
62
|
+
<text x="430" y="275" font-size="10" font-weight="700" fill="#f59e0b" letter-spacing="1">PARALLEL AGENTS v1.8.0</text>
|
|
63
63
|
<text x="430" y="296" font-size="13" fill="#e6edf3">/project-launch → 5 agents, 10 min</text>
|
|
64
64
|
<text x="430" y="313" font-size="13" fill="#e6edf3">/team-review → 4 agents, 15 min</text>
|
|
65
65
|
<text x="430" y="334" font-size="11" fill="#484f58">image-architect: Gemini / DALL-E / SVG</text>
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
<!-- Card 3: Semantic Routing -->
|
|
69
69
|
<rect x="740" y="250" width="380" height="120" rx="10" fill="url(#card2)" stroke="#38bdf8" stroke-opacity="0.4" stroke-width="1"/>
|
|
70
70
|
<rect x="740" y="250" width="4" height="120" rx="2" fill="#38bdf8"/>
|
|
71
|
-
<text x="760" y="275" font-size="10" font-weight="700" fill="#38bdf8" letter-spacing="1">SEMANTIC ROUTING v1.
|
|
71
|
+
<text x="760" y="275" font-size="10" font-weight="700" fill="#38bdf8" letter-spacing="1">SEMANTIC ROUTING v1.8.0</text>
|
|
72
72
|
<text x="760" y="296" font-size="13" fill="#e6edf3">Paste code → auto-routes to code-reviewer</text>
|
|
73
73
|
<text x="760" y="313" font-size="13" fill="#e6edf3">Paste error → auto-routes to debug-detective</text>
|
|
74
74
|
<text x="760" y="334" font-size="11" fill="#484f58">Emotion as signal · 2–3× more patterns</text>
|
|
@@ -76,15 +76,16 @@
|
|
|
76
76
|
|
|
77
77
|
<line x1="80" y1="392" x2="1120" y2="392" stroke="#21262d" stroke-width="1"/>
|
|
78
78
|
|
|
79
|
-
<!-- Stats -->
|
|
80
|
-
<text x="540" y="
|
|
81
|
-
<text x="540" y="
|
|
82
|
-
|
|
83
|
-
<line x1="
|
|
84
|
-
<
|
|
85
|
-
<text x="368" y="
|
|
86
|
-
<text x="
|
|
87
|
-
<text x="712" y="
|
|
79
|
+
<!-- Stats — "70" baseline lowered so cap-top sits below the separator line -->
|
|
80
|
+
<text x="540" y="447" font-size="68" font-weight="900" fill="#ffffff" text-anchor="middle">70</text>
|
|
81
|
+
<text x="540" y="468" font-size="10" fill="#484f58" text-anchor="middle" letter-spacing="3">SPECIALIST AGENTS</text>
|
|
82
|
+
<!-- Divider lines extended up to y=394 to fully contain the tall "70" numeral -->
|
|
83
|
+
<line x1="456" y1="394" x2="456" y2="474" stroke="#21262d" stroke-width="1"/>
|
|
84
|
+
<line x1="624" y1="394" x2="624" y2="474" stroke="#21262d" stroke-width="1"/>
|
|
85
|
+
<text x="368" y="444" font-size="34" font-weight="800" fill="#ffffff" text-anchor="middle">194</text>
|
|
86
|
+
<text x="368" y="464" font-size="10" fill="#484f58" text-anchor="middle" letter-spacing="2">SKILLS</text>
|
|
87
|
+
<text x="712" y="444" font-size="34" font-weight="800" fill="#ffffff" text-anchor="middle">97</text>
|
|
88
|
+
<text x="712" y="464" font-size="10" fill="#484f58" text-anchor="middle" letter-spacing="2">COMMANDS</text>
|
|
88
89
|
|
|
89
90
|
<!-- Benefit pills -->
|
|
90
91
|
<rect x="80" y="490" width="220" height="50" rx="8" fill="#161b22" stroke="#30363d" stroke-width="1"/>
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
<svg width="1200" height="628" viewBox="0 0 1200 628" xmlns="http://www.w3.org/2000/svg" font-family="'Segoe UI', system-ui, -apple-system, sans-serif">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
4
|
+
<stop offset="0%" style="stop-color:#050811"/>
|
|
5
|
+
<stop offset="100%" style="stop-color:#0d1117"/>
|
|
6
|
+
</linearGradient>
|
|
7
|
+
<linearGradient id="accent" x1="0%" y1="0%" x2="100%" y2="0%">
|
|
8
|
+
<stop offset="0%" style="stop-color:#a78bfa"/>
|
|
9
|
+
<stop offset="100%" style="stop-color:#38bdf8"/>
|
|
10
|
+
</linearGradient>
|
|
11
|
+
<linearGradient id="ctaGrad" x1="0%" y1="0%" x2="100%" y2="0%">
|
|
12
|
+
<stop offset="0%" style="stop-color:#7c3aed"/>
|
|
13
|
+
<stop offset="100%" style="stop-color:#0891b2"/>
|
|
14
|
+
</linearGradient>
|
|
15
|
+
</defs>
|
|
16
|
+
|
|
17
|
+
<rect width="1200" height="628" fill="url(#bg)"/>
|
|
18
|
+
|
|
19
|
+
<!-- Ambient glow -->
|
|
20
|
+
<circle cx="1100" cy="80" r="280" fill="#a78bfa" opacity="0.04"/>
|
|
21
|
+
<circle cx="100" cy="550" r="220" fill="#38bdf8" opacity="0.03"/>
|
|
22
|
+
|
|
23
|
+
<!-- Ghost Depth Mark — right-side watermark, scale 0.55, op=0.17 -->
|
|
24
|
+
<g transform="translate(1044, 213) scale(0.55)" opacity="0.17">
|
|
25
|
+
<polyline points="-44,4 12,100 -44,196"
|
|
26
|
+
stroke="#ffffff" stroke-width="10"
|
|
27
|
+
stroke-linecap="round" stroke-linejoin="round"
|
|
28
|
+
fill="none"/>
|
|
29
|
+
<polyline points="0,0 88,100 0,200"
|
|
30
|
+
stroke="#ffffff" stroke-width="32"
|
|
31
|
+
stroke-linecap="round" stroke-linejoin="round"
|
|
32
|
+
fill="none"/>
|
|
33
|
+
</g>
|
|
34
|
+
|
|
35
|
+
<!-- Left vertical accent bar -->
|
|
36
|
+
<rect x="80" y="80" width="4" height="468" rx="2" fill="url(#accent)" opacity="0.6"/>
|
|
37
|
+
|
|
38
|
+
<!-- Category badge -->
|
|
39
|
+
<rect x="102" y="80" width="160" height="26" rx="13" fill="#a78bfa" fill-opacity="0.12" stroke="#a78bfa" stroke-opacity="0.4" stroke-width="1"/>
|
|
40
|
+
<text x="182" y="97" font-size="10" fill="#a78bfa" text-anchor="middle" font-weight="700" letter-spacing="1.5">AI CODING TOOLKIT</text>
|
|
41
|
+
|
|
42
|
+
<!-- Main headline -->
|
|
43
|
+
<text x="102" y="175" font-size="64" font-weight="900" letter-spacing="-2.5" fill="#ffffff">Build 10x faster</text>
|
|
44
|
+
<text x="102" y="250" font-size="64" font-weight="900" letter-spacing="-2.5" fill="url(#accent)">with every session.</text>
|
|
45
|
+
|
|
46
|
+
<!-- Sub-headline -->
|
|
47
|
+
<text x="102" y="305" font-size="20" font-weight="400" fill="#9ca3af">70 specialist AI agents that learn how you work.</text>
|
|
48
|
+
<text x="102" y="332" font-size="20" font-weight="400" fill="#9ca3af">Runs on 11 platforms. Completely free.</text>
|
|
49
|
+
|
|
50
|
+
<!-- Divider -->
|
|
51
|
+
<line x1="102" y1="365" x2="680" y2="365" stroke="#ffffff" stroke-width="1" opacity="0.10"/>
|
|
52
|
+
|
|
53
|
+
<!-- Feature bullets -->
|
|
54
|
+
<circle cx="112" cy="395" r="4" fill="#10b981"/>
|
|
55
|
+
<text x="126" y="400" font-size="15" fill="#e6edf3">Compound learning — improves with every correction you make</text>
|
|
56
|
+
|
|
57
|
+
<circle cx="112" cy="425" r="4" fill="#38bdf8"/>
|
|
58
|
+
<text x="126" y="430" font-size="15" fill="#e6edf3">Semantic routing — paste code or an error, the right agent fires</text>
|
|
59
|
+
|
|
60
|
+
<circle cx="112" cy="455" r="4" fill="#a78bfa"/>
|
|
61
|
+
<text x="126" y="460" font-size="15" fill="#e6edf3">Parallel agents — /team-review runs 4 specialists simultaneously</text>
|
|
62
|
+
|
|
63
|
+
<circle cx="112" cy="485" r="4" fill="#f59e0b"/>
|
|
64
|
+
<text x="126" y="490" font-size="15" fill="#e6edf3">Zero cloud — 100% local files, zero vendor lock-in</text>
|
|
65
|
+
|
|
66
|
+
<!-- CTA Section -->
|
|
67
|
+
<rect x="102" y="526" width="260" height="52" rx="26" fill="url(#ctaGrad)"/>
|
|
68
|
+
<text x="232" y="558" font-size="16" font-weight="700" text-anchor="middle" fill="#ffffff">Get it free — npm</text>
|
|
69
|
+
|
|
70
|
+
<text x="384" y="548" font-size="14" fill="#6b7280">npx kodelyth-ecc</text>
|
|
71
|
+
<text x="384" y="568" font-size="14" fill="#6b7280">github.com/sifxprime/kodelyth-ecc</text>
|
|
72
|
+
|
|
73
|
+
<!-- Right panel — terminal mockup -->
|
|
74
|
+
<rect x="720" y="60" width="440" height="508" rx="12" fill="#0d1117" stroke="#21262d" stroke-width="1.5"/>
|
|
75
|
+
<rect x="720" y="60" width="440" height="34" rx="12" fill="#161b22"/>
|
|
76
|
+
<rect x="720" y="84" width="440" height="10" fill="#161b22"/>
|
|
77
|
+
<circle cx="744" cy="77" r="5" fill="#ff5f57"/>
|
|
78
|
+
<circle cx="760" cy="77" r="5" fill="#febc2e"/>
|
|
79
|
+
<circle cx="776" cy="77" r="5" fill="#28c840"/>
|
|
80
|
+
<text x="940" y="81" font-size="11" fill="#484f58" text-anchor="middle">kodelyth-ecc — terminal</text>
|
|
81
|
+
|
|
82
|
+
<!-- Terminal content -->
|
|
83
|
+
<text x="748" y="122" font-family="'Courier New', Courier, monospace" font-size="12" fill="#10b981">$</text>
|
|
84
|
+
<text x="762" y="122" font-family="'Courier New', Courier, monospace" font-size="12" fill="#e6edf3"> npx kodelyth-ecc</text>
|
|
85
|
+
|
|
86
|
+
<text x="748" y="144" font-family="'Courier New', Courier, monospace" font-size="12" fill="#484f58">Installing v1.8.0...</text>
|
|
87
|
+
|
|
88
|
+
<text x="748" y="176" font-family="'Courier New', Courier, monospace" font-size="12" fill="#e6edf3"> Agents (70) </text>
|
|
89
|
+
<text x="890" y="176" font-family="'Courier New', Courier, monospace" font-size="12" fill="#484f58">→ installed</text>
|
|
90
|
+
|
|
91
|
+
<text x="748" y="198" font-family="'Courier New', Courier, monospace" font-size="12" fill="#e6edf3"> Skills (194) </text>
|
|
92
|
+
<text x="890" y="198" font-family="'Courier New', Courier, monospace" font-size="12" fill="#484f58">→ installed</text>
|
|
93
|
+
|
|
94
|
+
<text x="748" y="220" font-family="'Courier New', Courier, monospace" font-size="12" fill="#e6edf3"> Commands (97) </text>
|
|
95
|
+
<text x="890" y="220" font-family="'Courier New', Courier, monospace" font-size="12" fill="#484f58">→ installed</text>
|
|
96
|
+
|
|
97
|
+
<text x="748" y="242" font-family="'Courier New', Courier, monospace" font-size="12" fill="#e6edf3"> Hooks (22+) </text>
|
|
98
|
+
<text x="890" y="242" font-family="'Courier New', Courier, monospace" font-size="12" fill="#484f58">→ installed</text>
|
|
99
|
+
|
|
100
|
+
<line x1="748" y1="262" x2="1140" y2="262" stroke="#21262d" stroke-width="1"/>
|
|
101
|
+
|
|
102
|
+
<!-- Session simulation -->
|
|
103
|
+
<text x="748" y="286" font-family="'Courier New', Courier, monospace" font-size="11" fill="#10b981">$</text>
|
|
104
|
+
<text x="762" y="286" font-family="'Courier New', Courier, monospace" font-size="11" fill="#e6edf3"> [paste stack trace]</text>
|
|
105
|
+
|
|
106
|
+
<text x="748" y="306" font-family="'Courier New', Courier, monospace" font-size="11" fill="#a78bfa">→ Routing to debug-detective</text>
|
|
107
|
+
|
|
108
|
+
<text x="748" y="326" font-family="'Courier New', Courier, monospace" font-size="11" fill="#484f58">Root cause: null reference in</text>
|
|
109
|
+
<text x="748" y="342" font-family="'Courier New', Courier, monospace" font-size="11" fill="#484f58">getUserById() line 47.</text>
|
|
110
|
+
<text x="748" y="358" font-family="'Courier New', Courier, monospace" font-size="11" fill="#484f58">Fix: add optional chaining.</text>
|
|
111
|
+
|
|
112
|
+
<line x1="748" y1="376" x2="1140" y2="376" stroke="#21262d" stroke-width="1"/>
|
|
113
|
+
|
|
114
|
+
<text x="748" y="400" font-family="'Courier New', Courier, monospace" font-size="11" fill="#10b981">$</text>
|
|
115
|
+
<text x="762" y="400" font-family="'Courier New', Courier, monospace" font-size="11" fill="#e6edf3"> /team-review</text>
|
|
116
|
+
|
|
117
|
+
<text x="748" y="420" font-family="'Courier New', Courier, monospace" font-size="11" fill="#a78bfa">Spawning 4 agents in parallel...</text>
|
|
118
|
+
<text x="748" y="438" font-family="'Courier New', Courier, monospace" font-size="11" fill="#484f58"> code-reviewer · security-reviewer</text>
|
|
119
|
+
<text x="748" y="454" font-family="'Courier New', Courier, monospace" font-size="11" fill="#484f58"> performance-optimizer · api-guardian</text>
|
|
120
|
+
|
|
121
|
+
<rect x="748" y="470" width="396" height="34" rx="6" fill="#0d2b1d" stroke="#059669" stroke-opacity="0.35" stroke-width="1"/>
|
|
122
|
+
<text x="768" y="484" font-size="9" font-weight="700" fill="#10b981" letter-spacing="1">REVIEW COMPLETE — 0 critical · 1 high · 3 medium</text>
|
|
123
|
+
<text x="768" y="498" font-size="10" fill="#6b7280">15 min parallel vs 60 min sequential</text>
|
|
124
|
+
|
|
125
|
+
<!-- Bottom bar -->
|
|
126
|
+
<rect x="0" y="590" width="1200" height="38" fill="#0d1117" stroke="#21262d" stroke-width="0"/>
|
|
127
|
+
<text x="600" y="613" font-size="12" fill="#30363d" text-anchor="middle">kodelyth.com · Works with Claude Code · Windsurf · Cursor · Codex CLI · Antigravity · OpenCode · and 5 more</text>
|
|
128
|
+
</svg>
|