@dev-kosaly/kagents 0.1.0 → 0.2.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/README.md +99 -20
- package/agents/architect.md +84 -116
- package/bin/kagents.js +178 -15
- package/bin/postinstall.js +26 -0
- package/commands/architect-audit.md +17 -0
- package/commands/architect-compare.md +13 -0
- package/commands/architect-decision.md +20 -0
- package/commands/architect-design.md +18 -0
- package/commands/architect-impact.md +16 -0
- package/commands/architect-spec.md +18 -0
- package/commands/architect-status.md +26 -0
- package/commands/architect.md +20 -0
- package/docs/architect-commands.md +52 -0
- package/package.json +5 -2
- package/rules/domains/architect-chat.md +61 -0
- package/rules/domains/architect-invariants.md +22 -0
- package/skills/README.md +17 -20
- package/skills/architect-audit/SKILL.md +31 -0
- package/skills/architect-decision/SKILL.md +40 -0
- package/skills/architect-discovery/SKILL.md +43 -0
- package/skills/architect-impact/SKILL.md +32 -0
- package/skills/architect-index/SKILL.md +31 -0
- package/skills/architect-status/SKILL.md +41 -0
- package/skills/architect-write-output/SKILL.md +49 -0
- package/templates/architect-decision/template.md +47 -0
- package/templates/architect-design/template.md +31 -0
- package/templates/architect-index/INDEX.template.md +47 -0
- package/templates/architect-output/template.md +95 -0
- package/templates/architect-spec/template.md +39 -0
- package/workflows/architect-architecture.md +19 -0
- package/workflows/architect-audit-run.md +14 -0
- package/workflows/architect-decision.md +20 -0
- package/workflows/architect-design.md +15 -0
- package/workflows/architect-impact-levels.yaml +28 -0
- package/workflows/architect-impact.md +20 -0
- package/workflows/architect-spec.md +19 -0
- package/workflows/architect-status.md +21 -0
- package/commands/arch-audit.md +0 -10
- package/commands/arch-design.md +0 -10
- package/commands/arch-feature.md +0 -10
- package/skills/architecture-impact/SKILL.md +0 -68
- package/skills/audit-repository/SKILL.md +0 -53
- package/skills/feature-analysis/SKILL.md +0 -52
- package/skills/write-change-brief/SKILL.md +0 -63
package/bin/kagents.js
CHANGED
|
@@ -5,39 +5,49 @@
|
|
|
5
5
|
|
|
6
6
|
const fs = require('fs');
|
|
7
7
|
const path = require('path');
|
|
8
|
+
const readline = require('readline');
|
|
9
|
+
const tty = require('tty');
|
|
8
10
|
|
|
9
11
|
const PKG_ROOT = path.resolve(__dirname, '..');
|
|
10
12
|
const PKG = JSON.parse(fs.readFileSync(path.join(PKG_ROOT, 'package.json'), 'utf8'));
|
|
11
|
-
const KIT_DIRS = ['agents', 'skills', 'commands', 'templates', 'checklists', 'workflows', 'governance'];
|
|
13
|
+
const KIT_DIRS = ['agents', 'skills', 'commands', 'rules', 'templates', 'checklists', 'workflows', 'governance', 'docs'];
|
|
12
14
|
const SKIP = new Set(['README.md', '.gitkeep']);
|
|
13
15
|
const BLOCK_RE = /<!-- kagents:start -->[\s\S]*?<!-- kagents:end -->/;
|
|
16
|
+
const GITIGNORE_RE = /# kagents:start\n[\s\S]*?# kagents:end\n?/;
|
|
17
|
+
// On ignore le kit (régénérable) mais pas docs/ : livrables et contexte sont à versionner.
|
|
14
18
|
|
|
15
19
|
// Adaptateurs : un outil = une liste [dossier du kit, destination, type].
|
|
16
20
|
// type : files (fichiers), dirs (dossiers), agents (fichiers .md avec `name:`).
|
|
21
|
+
// Les skills ne sont volontairement PAS liées dans .claude/ ni .cursor/ : ces outils les listeraient
|
|
22
|
+
// comme commandes `/`. Les agents et commandes les chargent par chemin depuis .kagents/skills/.
|
|
17
23
|
const ADAPTERS = {
|
|
18
24
|
agents: [['skills', '.agents/skills', 'dirs']],
|
|
19
25
|
claude: [
|
|
20
26
|
['commands', '.claude/commands', 'files'],
|
|
21
|
-
['skills', '.claude/skills', 'dirs'],
|
|
22
27
|
['agents', '.claude/agents', 'agents'],
|
|
23
28
|
],
|
|
24
29
|
cursor: [
|
|
25
30
|
['commands', '.cursor/commands', 'files'],
|
|
26
|
-
['skills', '.cursor/skills', 'dirs'],
|
|
27
31
|
['agents', '.cursor/agents', 'agents'],
|
|
32
|
+
['rules/global', '.cursor/rules', 'files'],
|
|
33
|
+
['rules/domains', '.cursor/rules', 'files'],
|
|
28
34
|
],
|
|
29
35
|
};
|
|
30
36
|
|
|
31
37
|
const HELP = `kagents ${PKG.version}
|
|
32
38
|
|
|
33
|
-
Usage : kagents [install] [--tools claude,cursor,agents|auto] [--copy]
|
|
39
|
+
Usage : kagents [install] [--tools claude,cursor,agents|auto|none] [--yes] [--copy]
|
|
40
|
+
kagents --configure (rechoisir les outils)
|
|
34
41
|
kagents uninstall
|
|
35
42
|
kagents --help | --version
|
|
36
43
|
|
|
37
|
-
À lancer depuis la racine du projet.
|
|
38
|
-
|
|
39
|
-
--
|
|
40
|
-
|
|
44
|
+
À lancer depuis la racine du projet. Dans un terminal, une liste permet de choisir
|
|
45
|
+
les outils à brancher ; le choix est mémorisé dans .kagents/config.json.
|
|
46
|
+
--tools outils à brancher, sans question
|
|
47
|
+
--yes, -y ne pose pas de question (détection automatique)
|
|
48
|
+
--configure pose à nouveau la question
|
|
49
|
+
--copy copies au lieu de liens symboliques (aussi KAGENTS_MODE=copy)
|
|
50
|
+
uninstall retire ce que KAgents a installé (docs/ est conservé)
|
|
41
51
|
`;
|
|
42
52
|
|
|
43
53
|
const log = (m) => console.log(`kagents: ${m}`);
|
|
@@ -49,12 +59,14 @@ const die = (m) => {
|
|
|
49
59
|
|
|
50
60
|
// --- Arguments ----------------------------------------------------------------
|
|
51
61
|
function parseArgs(argv) {
|
|
52
|
-
const o = { cmd: 'install', tools:
|
|
62
|
+
const o = { cmd: 'install', tools: null, yes: false, configure: false, copy: process.env.KAGENTS_MODE === 'copy' };
|
|
53
63
|
for (let i = 0; i < argv.length; i++) {
|
|
54
64
|
const a = argv[i];
|
|
55
65
|
if (a === '-h' || a === '--help') o.cmd = 'help';
|
|
56
66
|
else if (a === '-v' || a === '--version') o.cmd = 'version';
|
|
57
67
|
else if (a === '--copy') o.copy = true;
|
|
68
|
+
else if (a === '-y' || a === '--yes') o.yes = true;
|
|
69
|
+
else if (a === '--configure') o.configure = true;
|
|
58
70
|
else if (a === '--tools') o.tools = argv[++i] || die('--tools attend une valeur');
|
|
59
71
|
else if (a.startsWith('--tools=')) o.tools = a.slice(8);
|
|
60
72
|
else if (a === 'install' || a === 'uninstall') o.cmd = a;
|
|
@@ -100,6 +112,7 @@ class Installer {
|
|
|
100
112
|
this.copy = copy;
|
|
101
113
|
this.kagents = path.join(target, '.kagents');
|
|
102
114
|
this.manifest = path.join(this.kagents, '.installed');
|
|
115
|
+
this.config = path.join(this.kagents, 'config.json');
|
|
103
116
|
this.entries = [];
|
|
104
117
|
}
|
|
105
118
|
|
|
@@ -168,6 +181,7 @@ class Installer {
|
|
|
168
181
|
const docs = frontmatter(path.join(this.kagents, 'agents', f)).docs;
|
|
169
182
|
if (docs) fs.mkdirSync(path.join(this.kagents, 'docs', docs), { recursive: true });
|
|
170
183
|
}
|
|
184
|
+
this.createArchitectDocs();
|
|
171
185
|
const ctx = path.join(this.kagents, 'docs', 'knowledge', 'context.md');
|
|
172
186
|
if (!fs.existsSync(ctx)) {
|
|
173
187
|
fs.writeFileSync(
|
|
@@ -196,6 +210,17 @@ Document partagé, écrit par l'utilisateur. Les agents le lisent, ne l'écriven
|
|
|
196
210
|
}
|
|
197
211
|
}
|
|
198
212
|
|
|
213
|
+
// Espace de l'Architect : livrables, décisions, propositions et INDEX.md (créé une fois, jamais écrasé).
|
|
214
|
+
createArchitectDocs() {
|
|
215
|
+
const root = path.join(this.kagents, 'docs', 'architect-docs');
|
|
216
|
+
if (!fs.existsSync(root)) return;
|
|
217
|
+
for (const d of ['architecture', 'impacts', 'features', 'specs', 'designs', 'audits'].map((n) => `outputs/${n}`).concat(['decisions', 'proposals']))
|
|
218
|
+
fs.mkdirSync(path.join(root, d), { recursive: true });
|
|
219
|
+
const index = path.join(root, 'INDEX.md');
|
|
220
|
+
const tpl = path.join(this.kagents, 'templates', 'architect-index', 'INDEX.template.md');
|
|
221
|
+
if (!fs.existsSync(index) && fs.existsSync(tpl)) fs.copyFileSync(tpl, index);
|
|
222
|
+
}
|
|
223
|
+
|
|
199
224
|
renderBlock() {
|
|
200
225
|
const agentsDir = path.join(this.kagents, 'agents');
|
|
201
226
|
const cmdDir = path.join(this.kagents, 'commands');
|
|
@@ -252,15 +277,49 @@ Document partagé, écrit par l'utilisateur. Les agents le lisent, ne l'écriven
|
|
|
252
277
|
fs.writeFileSync(file, out);
|
|
253
278
|
}
|
|
254
279
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
const
|
|
280
|
+
// Bloc .gitignore : le kit et les liens que l'on a posés, jamais docs/ (sauf les fichiers du kit qui s'y trouvent).
|
|
281
|
+
gitignoreBlock() {
|
|
282
|
+
const extra = this.entries.filter((e) => !e.startsWith('.kagents/') || e.startsWith('.kagents/docs/')).sort();
|
|
283
|
+
return ['# kagents:start', '.kagents/*', '!.kagents/docs/', ...extra, '# kagents:end'].join('\n') + '\n';
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
writeGitignore() {
|
|
287
|
+
const file = path.join(this.target, '.gitignore');
|
|
288
|
+
if (!fs.existsSync(file) && !fs.existsSync(path.join(this.target, '.git'))) return;
|
|
289
|
+
const cur = fs.existsSync(file) ? fs.readFileSync(file, 'utf8') : '';
|
|
290
|
+
const block = this.gitignoreBlock();
|
|
291
|
+
const out = GITIGNORE_RE.test(cur)
|
|
292
|
+
? cur.replace(GITIGNORE_RE, () => block)
|
|
293
|
+
: (cur && !cur.endsWith('\n') ? cur + '\n' : cur) + (cur ? '\n' : '') + block;
|
|
294
|
+
fs.writeFileSync(file, out);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
detectTools() {
|
|
258
298
|
const has = (p) => fs.existsSync(path.join(this.target, p));
|
|
299
|
+
const t = [];
|
|
259
300
|
if (has('.claude') || has('CLAUDE.md')) t.push('claude');
|
|
260
301
|
if (has('.cursor')) t.push('cursor');
|
|
261
302
|
return t;
|
|
262
303
|
}
|
|
263
304
|
|
|
305
|
+
resolveTools(tools) {
|
|
306
|
+
return tools === 'auto' ? ['agents', ...this.detectTools()] : tools;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
loadConfig() {
|
|
310
|
+
try {
|
|
311
|
+
const c = JSON.parse(fs.readFileSync(this.config, 'utf8'));
|
|
312
|
+
return Array.isArray(c.tools) ? c.tools : null;
|
|
313
|
+
} catch {
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
saveConfig(tools) {
|
|
319
|
+
fs.mkdirSync(this.kagents, { recursive: true });
|
|
320
|
+
fs.writeFileSync(this.config, JSON.stringify({ tools }, null, 2) + '\n');
|
|
321
|
+
}
|
|
322
|
+
|
|
264
323
|
runAdapters(tools) {
|
|
265
324
|
for (const tool of this.resolveTools(tools)) {
|
|
266
325
|
if (!ADAPTERS[tool]) {
|
|
@@ -312,6 +371,7 @@ Document partagé, écrit par l'utilisateur. Les agents le lisent, ne l'écriven
|
|
|
312
371
|
this.createDocs();
|
|
313
372
|
this.writeAgentsMd();
|
|
314
373
|
this.runAdapters(tools);
|
|
374
|
+
this.writeGitignore();
|
|
315
375
|
this.saveManifest();
|
|
316
376
|
log(`installé dans ${this.kagents} (${this.copy ? 'copies' : 'liens'})`);
|
|
317
377
|
}
|
|
@@ -327,22 +387,125 @@ Document partagé, écrit par l'utilisateur. Les agents le lisent, ne l'écriven
|
|
|
327
387
|
else fs.rmSync(file);
|
|
328
388
|
}
|
|
329
389
|
}
|
|
390
|
+
const gi = path.join(this.target, '.gitignore');
|
|
391
|
+
if (fs.existsSync(gi) && GITIGNORE_RE.test(fs.readFileSync(gi, 'utf8'))) {
|
|
392
|
+
const out = fs.readFileSync(gi, 'utf8').replace(GITIGNORE_RE, '').replace(/\n{3,}/g, '\n\n').replace(/\s+$/, '');
|
|
393
|
+
if (out) fs.writeFileSync(gi, out + '\n');
|
|
394
|
+
else fs.rmSync(gi);
|
|
395
|
+
}
|
|
330
396
|
fs.rmSync(this.manifest, { force: true });
|
|
397
|
+
fs.rmSync(this.config, { force: true });
|
|
331
398
|
this.prune(removed);
|
|
332
399
|
log('désinstallé (.kagents/docs/ conservé : ce sont vos livrables)');
|
|
333
400
|
}
|
|
334
401
|
}
|
|
335
402
|
|
|
403
|
+
// --- Question interactive -----------------------------------------------------
|
|
404
|
+
// Terminal utilisable : le nôtre, ou /dev/tty quand on est lancé par un postinstall (stdin/stdout détournés).
|
|
405
|
+
function openTTY() {
|
|
406
|
+
if (process.stdin.isTTY && process.stdout.isTTY) return { input: process.stdin, output: process.stdout, close() {} };
|
|
407
|
+
if (process.env.KAGENTS_FROM_POSTINSTALL && process.platform !== 'win32') {
|
|
408
|
+
try {
|
|
409
|
+
const rfd = fs.openSync('/dev/tty', 'r');
|
|
410
|
+
const wfd = fs.openSync('/dev/tty', 'w');
|
|
411
|
+
const input = new tty.ReadStream(rfd);
|
|
412
|
+
const output = new tty.WriteStream(wfd);
|
|
413
|
+
return { input, output, close: () => { input.destroy(); output.destroy(); } };
|
|
414
|
+
} catch {
|
|
415
|
+
return null;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
return null;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// Liste à cocher : ↑↓ déplacer, espace cocher, a tout, entrée valider. Renvoie les ids cochés.
|
|
422
|
+
function multiselect(io, message, items) {
|
|
423
|
+
return new Promise((resolve) => {
|
|
424
|
+
const { input, output } = io;
|
|
425
|
+
const state = items.map((i) => ({ ...i }));
|
|
426
|
+
let cur = 0;
|
|
427
|
+
let drawn = false;
|
|
428
|
+
const draw = () => {
|
|
429
|
+
if (drawn) output.write(`\x1b[${state.length + 1}A`);
|
|
430
|
+
drawn = true;
|
|
431
|
+
output.write(`\x1b[2K\x1b[1m?\x1b[0m ${message}\n`);
|
|
432
|
+
state.forEach((it, i) => {
|
|
433
|
+
const box = it.checked ? '\x1b[32m◉\x1b[0m' : '◯';
|
|
434
|
+
output.write(`\x1b[2K ${i === cur ? '\x1b[36m❯\x1b[0m' : ' '} ${box} ${it.label}\n`);
|
|
435
|
+
});
|
|
436
|
+
};
|
|
437
|
+
const finish = () => {
|
|
438
|
+
input.removeListener('keypress', onKey);
|
|
439
|
+
input.setRawMode(false);
|
|
440
|
+
input.pause();
|
|
441
|
+
output.write('\x1b[?25h');
|
|
442
|
+
io.close();
|
|
443
|
+
resolve(state.filter((i) => i.checked).map((i) => i.id));
|
|
444
|
+
};
|
|
445
|
+
const onKey = (str, key = {}) => {
|
|
446
|
+
if (key.ctrl && key.name === 'c') {
|
|
447
|
+
output.write('\x1b[?25h\n');
|
|
448
|
+
process.exit(130);
|
|
449
|
+
}
|
|
450
|
+
if (key.name === 'up') cur = (cur + state.length - 1) % state.length;
|
|
451
|
+
else if (key.name === 'down') cur = (cur + 1) % state.length;
|
|
452
|
+
else if (key.name === 'space') state[cur].checked = !state[cur].checked;
|
|
453
|
+
else if (key.name === 'a') {
|
|
454
|
+
const all = state.every((i) => i.checked);
|
|
455
|
+
state.forEach((i) => (i.checked = !all));
|
|
456
|
+
} else if (key.name === 'return') {
|
|
457
|
+
draw();
|
|
458
|
+
return finish();
|
|
459
|
+
}
|
|
460
|
+
draw();
|
|
461
|
+
};
|
|
462
|
+
readline.emitKeypressEvents(input);
|
|
463
|
+
input.setRawMode(true);
|
|
464
|
+
input.resume();
|
|
465
|
+
output.write('\x1b[?25l');
|
|
466
|
+
input.on('keypress', onKey);
|
|
467
|
+
draw();
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
async function chooseTools(inst, o) {
|
|
472
|
+
if (o.tools) {
|
|
473
|
+
const t = o.tools === 'auto' ? 'auto' : o.tools === 'none' ? [] : o.tools.split(',').filter(Boolean);
|
|
474
|
+
if (t !== 'auto') inst.chosen = t;
|
|
475
|
+
return t;
|
|
476
|
+
}
|
|
477
|
+
if (!o.configure) {
|
|
478
|
+
const saved = inst.loadConfig();
|
|
479
|
+
if (saved) return saved;
|
|
480
|
+
}
|
|
481
|
+
if (!o.yes && !process.env.KAGENTS_NO_PROMPT && !process.env.CI) {
|
|
482
|
+
const io = openTTY();
|
|
483
|
+
if (io) {
|
|
484
|
+
const detected = inst.detectTools();
|
|
485
|
+
const picked = await multiselect(io, 'Pour quels outils installer KAgents ? (↑↓ espace a entrée)', [
|
|
486
|
+
{ id: 'claude', label: 'Claude Code (.claude/commands, .claude/agents)', checked: detected.includes('claude') },
|
|
487
|
+
{ id: 'cursor', label: 'Cursor (.cursor/commands, .cursor/agents, .cursor/rules)', checked: detected.includes('cursor') },
|
|
488
|
+
{ id: 'agents', label: 'Codex et autres outils AGENTS.md (.agents/skills)', checked: true },
|
|
489
|
+
]);
|
|
490
|
+
inst.chosen = picked;
|
|
491
|
+
return picked;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
return 'auto';
|
|
495
|
+
}
|
|
496
|
+
|
|
336
497
|
// --- Main ---------------------------------------------------------------------
|
|
337
|
-
function main() {
|
|
498
|
+
async function main() {
|
|
338
499
|
const o = parseArgs(process.argv.slice(2));
|
|
339
500
|
if (o.cmd === 'help') return console.log(HELP);
|
|
340
501
|
if (o.cmd === 'version') return console.log(PKG.version);
|
|
341
502
|
const target = process.cwd();
|
|
342
503
|
if (path.resolve(target) === PKG_ROOT) die("à lancer depuis la racine d'un projet, pas depuis le kit.");
|
|
343
504
|
const inst = new Installer(target, o.copy);
|
|
344
|
-
if (o.cmd === 'uninstall') inst.uninstall();
|
|
345
|
-
|
|
505
|
+
if (o.cmd === 'uninstall') return inst.uninstall();
|
|
506
|
+
const tools = await chooseTools(inst, o);
|
|
507
|
+
inst.install(tools);
|
|
508
|
+
if (inst.chosen) inst.saveConfig(inst.chosen);
|
|
346
509
|
}
|
|
347
510
|
|
|
348
511
|
main();
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
// Lancé par npm/pnpm après `add @dev-kosaly/kagents` : installe le kit dans le projet.
|
|
4
|
+
// Ne doit jamais faire échouer l'installation des dépendances.
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const { spawnSync } = require('child_process');
|
|
7
|
+
|
|
8
|
+
const pkgRoot = path.resolve(__dirname, '..');
|
|
9
|
+
const project = process.env.INIT_CWD;
|
|
10
|
+
|
|
11
|
+
const skip = (why) => {
|
|
12
|
+
if (why) console.log(`kagents: installation automatique ignorée (${why}). Lancez : npx kagents`);
|
|
13
|
+
process.exit(0);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
if (process.env.KAGENTS_SKIP_POSTINSTALL) skip();
|
|
17
|
+
if (!project) skip();
|
|
18
|
+
if (process.env.npm_config_global === 'true') skip('installation globale');
|
|
19
|
+
if (!pkgRoot.split(path.sep).includes('node_modules')) skip(); // développement du kit lui-même
|
|
20
|
+
if (path.resolve(project) === pkgRoot) skip();
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
spawnSync(process.execPath, [path.join(__dirname, 'kagents.js')], { cwd: project, stdio: 'inherit', env: { ...process.env, KAGENTS_FROM_POSTINSTALL: '1' } });
|
|
24
|
+
} catch {
|
|
25
|
+
/* jamais bloquant */
|
|
26
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Architect — auditer l'architecture existante
|
|
3
|
+
agent: architect
|
|
4
|
+
mode: Audit
|
|
5
|
+
triggers: audite l'architecture existante
|
|
6
|
+
---
|
|
7
|
+
Lis le role Architect.
|
|
8
|
+
|
|
9
|
+
Commande : **`kagents architect:audit [scope]`**.
|
|
10
|
+
|
|
11
|
+
Identifier incoherences, derives, ecarts doc/code **uniquement si observes**. Ne pas modifier le code.
|
|
12
|
+
|
|
13
|
+
Skills internes : `architect-audit`, `architect-write-output`, `architect-index`.
|
|
14
|
+
|
|
15
|
+
Workflow : `workflows/architect-audit-run.md`.
|
|
16
|
+
|
|
17
|
+
Scope optionnel : $ARGUMENTS
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Architect — comparer des options (extension future)
|
|
3
|
+
agent: architect
|
|
4
|
+
mode: Comparaison (non implémenté)
|
|
5
|
+
triggers: compare ces options d'architecture
|
|
6
|
+
---
|
|
7
|
+
**Extension preparee — non implementee.**
|
|
8
|
+
|
|
9
|
+
Commande prevue : `kagents architect:compare "<question>"`.
|
|
10
|
+
|
|
11
|
+
Voir `docs/architect-commands.md`. Ne pas simuler un workflow complet tant qu'il n'est pas defini.
|
|
12
|
+
|
|
13
|
+
Question : $ARGUMENTS
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Architect — enregistrer une decision humaine explicitement fournie
|
|
3
|
+
agent: architect
|
|
4
|
+
mode: Décision humaine
|
|
5
|
+
triggers: enregistre cette décision d'architecture
|
|
6
|
+
---
|
|
7
|
+
Lis `agents/architect.md`.
|
|
8
|
+
|
|
9
|
+
Commande : **`kagents architect:decision "<decision>"`**.
|
|
10
|
+
|
|
11
|
+
Le argument utilisateur **est** la decision a enregistrer (confirmation humaine implicite via la commande). Ce n'est pas une question a resoudre.
|
|
12
|
+
|
|
13
|
+
Skill : `architect-decision`.
|
|
14
|
+
Workflow : `workflows/architect-decision.md`.
|
|
15
|
+
Template : `templates/architect-decision/template.md`.
|
|
16
|
+
Cible : `.kagents/docs/architect-docs/decisions/DEC-XXX-<slug>.md`
|
|
17
|
+
|
|
18
|
+
Statut par defaut : **VALIDEE**. Ne jamais promouvoir une PROPOSITION agent sans cette commande.
|
|
19
|
+
|
|
20
|
+
Decision a enregistrer : $ARGUMENTS
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Architect — concevoir une architecture cible (proposition)
|
|
3
|
+
agent: architect
|
|
4
|
+
mode: Architecture cible
|
|
5
|
+
triggers: conçois l'architecture cible, propose une architecture
|
|
6
|
+
---
|
|
7
|
+
Lis le role Architect.
|
|
8
|
+
|
|
9
|
+
Commande : **`kagents architect:design "<objectif>"`**.
|
|
10
|
+
|
|
11
|
+
Distinction : `kagents architect` = observe ; `kagents architect:design` = **cible proposee** (PROPOSITION, pas decision).
|
|
12
|
+
|
|
13
|
+
Skills internes : `architect-discovery` (existant), `architect-write-output`, `architect-index`.
|
|
14
|
+
|
|
15
|
+
Workflow : `workflows/architect-design.md`.
|
|
16
|
+
Template : `templates/architect-design/template.md`.
|
|
17
|
+
|
|
18
|
+
Objectif : $ARGUMENTS
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Architect — impact d'une evolution sur l'architecture existante
|
|
3
|
+
agent: architect
|
|
4
|
+
mode: Impact
|
|
5
|
+
triggers: avant de coder, impact d'une évolution, ajouter une fonctionnalité
|
|
6
|
+
---
|
|
7
|
+
Lis le role Architect (chemins ci-dessus).
|
|
8
|
+
|
|
9
|
+
Commande officielle : **`kagents architect:impact "<demande>"`**.
|
|
10
|
+
|
|
11
|
+
Skills internes : `architect-audit` (si besoin), `architect-impact`, `architect-write-output`, `architect-index`.
|
|
12
|
+
|
|
13
|
+
Workflow : `workflows/architect-impact.md`.
|
|
14
|
+
Niveaux : `workflows/architect-impact-levels.yaml`.
|
|
15
|
+
|
|
16
|
+
Demande : $ARGUMENTS
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Architect — formaliser une fonctionnalite en specification
|
|
3
|
+
agent: architect
|
|
4
|
+
mode: Spécification
|
|
5
|
+
triggers: spécifie cette fonctionnalité, rédige la spec
|
|
6
|
+
---
|
|
7
|
+
Lis le role Architect.
|
|
8
|
+
|
|
9
|
+
Commande : **`kagents architect:spec "<fonctionnalite>"`**.
|
|
10
|
+
|
|
11
|
+
Distinction : section **Impact** (ce que ca touche) vs **Spec** (comportement attendu). Ne pas inventer de regles metier.
|
|
12
|
+
|
|
13
|
+
Skills internes : `architect-audit` (si besoin), `architect-impact` (partie impact uniquement), `architect-write-output`, `architect-index`.
|
|
14
|
+
|
|
15
|
+
Workflow : `workflows/architect-spec.md`.
|
|
16
|
+
Template : `templates/architect-spec/template.md`.
|
|
17
|
+
|
|
18
|
+
Fonctionnalite : $ARGUMENTS
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Architect — etat documentaire et architectural connu (read-only)
|
|
3
|
+
agent: architect
|
|
4
|
+
mode: État (lecture seule)
|
|
5
|
+
triggers: où en est-on, état des décisions et propositions
|
|
6
|
+
---
|
|
7
|
+
Lis `agents/architect.md` (ou `.kagents/docs/architect-docs/architect.md`).
|
|
8
|
+
|
|
9
|
+
Commande : **`kagents architect:status`**.
|
|
10
|
+
|
|
11
|
+
Skill interne : `architect-status`.
|
|
12
|
+
Workflow : `workflows/architect-status.md`.
|
|
13
|
+
|
|
14
|
+
**Read-only** : pas de nouveau livrable obligatoire ; pas d'audit repo complet.
|
|
15
|
+
|
|
16
|
+
Sortie chat type :
|
|
17
|
+
|
|
18
|
+
# Architect — Etat du projet
|
|
19
|
+
|
|
20
|
+
**Etat architectural :** ...
|
|
21
|
+
**Derniere activite :** ...
|
|
22
|
+
**Travaux ouverts / Decisions en attente / Blocages** (si presents)
|
|
23
|
+
|
|
24
|
+
Sections adaptatives : Travaux en cours (tableau), Decisions, Handoffs, Points d'attention, Derniers livrables, Prochaine etape.
|
|
25
|
+
|
|
26
|
+
Argument optionnel (filtre domaine) : $ARGUMENTS
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Architect — vue de l'architecture observee du projet
|
|
3
|
+
agent: architect
|
|
4
|
+
mode: Architecture observée
|
|
5
|
+
triggers: explique l'architecture, comment le projet est construit
|
|
6
|
+
---
|
|
7
|
+
Lis le role Architect :
|
|
8
|
+
- projet client : `.kagents/docs/architect-docs/architect.md`
|
|
9
|
+
- harness : `agents/architect.md`
|
|
10
|
+
|
|
11
|
+
Commande officielle : **`kagents architect`** (ne pas utiliser `kagents architecture`).
|
|
12
|
+
|
|
13
|
+
Applique la vue **architecture actuelle observee** — pas une analyse de feature.
|
|
14
|
+
|
|
15
|
+
Skills internes : `architect-discovery`, `architect-write-output`, `architect-index`.
|
|
16
|
+
|
|
17
|
+
Workflow : `workflows/architect-architecture.md`.
|
|
18
|
+
Contrat : `docs/architect-commands.md`.
|
|
19
|
+
|
|
20
|
+
Demande ou focus : $ARGUMENTS
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Contrat des commandes — Architect (public)
|
|
2
|
+
|
|
3
|
+
Racine officielle : **`kagents architect`** (pas `kagents architecture`).
|
|
4
|
+
|
|
5
|
+
Les skills `architect-*` sont **internes** ; l'utilisateur invoque une **commande**, pas une skill.
|
|
6
|
+
|
|
7
|
+
## Priorite 1 — disponibles
|
|
8
|
+
|
|
9
|
+
| Commande | Role | Workflow | Skills internes | Livrable |
|
|
10
|
+
|----------|------|----------|-----------------|----------|
|
|
11
|
+
| `kagents architect` | Architecture **observee** (existant) | `workflows/architect-architecture.md` | discovery, write-output, index | `outputs/architecture/` |
|
|
12
|
+
| `kagents architect:impact "<demande>"` | Impact d'une evolution | `workflows/architect-impact.md` | audit?, impact, write-output, index | `outputs/features/` ou `outputs/impacts/` |
|
|
13
|
+
| `kagents architect:spec "<fonctionnalite>"` | Spec exploitable (comportement attendu) | `workflows/architect-spec.md` | audit?, impact (partie impact), write-output, index | `outputs/specs/` |
|
|
14
|
+
| `kagents architect:design "<objectif>"` | Architecture **cible** proposee | `workflows/architect-design.md` | discovery, write-output, index | `outputs/designs/` |
|
|
15
|
+
| `kagents architect:audit [scope]` | Audit architecture existante | `workflows/architect-audit-run.md` | audit, write-output, index | `outputs/audits/` |
|
|
16
|
+
| `kagents architect:status` | Etat documentaire (read-only) | `workflows/architect-status.md` | architect-status | chat |
|
|
17
|
+
| `kagents architect:decision "<texte>"` | Decision **humaine** enregistree | `workflows/architect-decision.md` | architect-decision | `decisions/DEC-XXX-*.md` |
|
|
18
|
+
|
|
19
|
+
Fichiers entree harness : `commands/architect*.md`.
|
|
20
|
+
|
|
21
|
+
## Distinctions
|
|
22
|
+
|
|
23
|
+
- **Impact** : ce que le changement **touche** (MVC, risques, L0–L3).
|
|
24
|
+
- **Spec** : ce que la fonctionnalite doit **faire** (comportement, cas, criteres) + reference impact si pertinent.
|
|
25
|
+
- **architect** (sans suffixe) : etat **reel** observe.
|
|
26
|
+
- **architect:design** : etat **cible** PROPOSITION (jamais decision automatique).
|
|
27
|
+
- **architect:status** : synthese **read-only** (INDEX, decisions, proposals, travaux ouverts) — pas d’audit repo complet.
|
|
28
|
+
- **architect:decision** : enregistre une decision **explicitement fournie ou confirmee par l’humain** ; statut typique **VALIDEE** ; registre `decisions/DEC-XXX-*.md` + ligne dans INDEX. Une proposition dans `proposals/` ou un livrable n’est **pas** promue en decision sans cette commande.
|
|
29
|
+
|
|
30
|
+
Statuts decision : PROPOSEE, A VALIDER, VALIDEE, REJETEE, REMPLACEE (remplacement sans suppression du fichier historique).
|
|
31
|
+
|
|
32
|
+
## Priorite 2 — extension
|
|
33
|
+
|
|
34
|
+
| Commande | Statut |
|
|
35
|
+
|----------|--------|
|
|
36
|
+
| `kagents architect:compare "<question>"` | Prepare — workflow a creer |
|
|
37
|
+
|
|
38
|
+
Fichier : `commands/architect-compare.md`.
|
|
39
|
+
|
|
40
|
+
## Mode naturel
|
|
41
|
+
|
|
42
|
+
Formulations sans commande → resolver vers la commande la plus proche (souvent `architect:impact` ou `architect`).
|
|
43
|
+
|
|
44
|
+
## Database Architect (Base)
|
|
45
|
+
|
|
46
|
+
**Hors scope.** Commandes inchangees : `commands/base-audit.md`, `base-design.md`, `base-evolve.md`.
|
|
47
|
+
|
|
48
|
+
## Chaine d'execution
|
|
49
|
+
|
|
50
|
+
```text
|
|
51
|
+
Commande → agents/architect.md → rules/architect-* → workflow → skills → template → livrable → INDEX → chat
|
|
52
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dev-kosaly/kagents",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Kit d'agents IA d'ingénierie installable dans un projet (Claude Code, Cursor, AGENTS.md)",
|
|
5
5
|
"bin": {
|
|
6
6
|
"kagents": "bin/kagents.js"
|
|
@@ -10,10 +10,12 @@
|
|
|
10
10
|
"agents",
|
|
11
11
|
"skills",
|
|
12
12
|
"commands",
|
|
13
|
+
"rules",
|
|
13
14
|
"templates",
|
|
14
15
|
"checklists",
|
|
15
16
|
"workflows",
|
|
16
|
-
"governance"
|
|
17
|
+
"governance",
|
|
18
|
+
"docs"
|
|
17
19
|
],
|
|
18
20
|
"engines": {
|
|
19
21
|
"node": ">=18"
|
|
@@ -27,6 +29,7 @@
|
|
|
27
29
|
"access": "public"
|
|
28
30
|
},
|
|
29
31
|
"scripts": {
|
|
32
|
+
"postinstall": "node bin/postinstall.js",
|
|
30
33
|
"test": "node scripts/smoke-test.js",
|
|
31
34
|
"prepublishOnly": "npm test"
|
|
32
35
|
},
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Contrat de sortie chat — Architect
|
|
2
|
+
|
|
3
|
+
Reference adaptative — omettre les sections sans contenu utile.
|
|
4
|
+
|
|
5
|
+
Priorite : **Clarte > Pertinence > Structure > Concision > Esthetique**.
|
|
6
|
+
|
|
7
|
+
```markdown
|
|
8
|
+
# Architect — [titre]
|
|
9
|
+
|
|
10
|
+
**Mode :** Architecture | Impact
|
|
11
|
+
**Niveau :** L0 | L1 | L2 | L3
|
|
12
|
+
**Statut :** ETABLI | A VALIDER | BLOQUANT (selon le cas)
|
|
13
|
+
|
|
14
|
+
## Synthese
|
|
15
|
+
|
|
16
|
+
Quelques paragraphes : conclusion immediate, ce qui a ete analyse, proposition retenue.
|
|
17
|
+
|
|
18
|
+
## Constats principaux
|
|
19
|
+
|
|
20
|
+
Tableau ou liste (elements importants seulement).
|
|
21
|
+
|
|
22
|
+
## Impact architectural
|
|
23
|
+
|
|
24
|
+
Tableau MVC si mode Impact (ou « Pas d'impact identifie » par couche).
|
|
25
|
+
|
|
26
|
+
| Couche | Impact | Element cle |
|
|
27
|
+
|--------|--------|-------------|
|
|
28
|
+
| Modele | | |
|
|
29
|
+
| Controleur | | |
|
|
30
|
+
| Vue | | |
|
|
31
|
+
|
|
32
|
+
## Architecture concernee
|
|
33
|
+
|
|
34
|
+
Diagramme Mermaid ou schema **uniquement** si cela clarifie flux ou composants.
|
|
35
|
+
|
|
36
|
+
## Points a decider
|
|
37
|
+
|
|
38
|
+
Decisions humaines importantes (pas les propositions de l'agent presentees comme decidees).
|
|
39
|
+
|
|
40
|
+
## Incertitudes / points bloquants
|
|
41
|
+
|
|
42
|
+
Ce qui influence la suite (max 5 questions bloquantes).
|
|
43
|
+
|
|
44
|
+
## Handoff
|
|
45
|
+
|
|
46
|
+
### Base (Database Expert)
|
|
47
|
+
Si BDD / donnees concernees : ce que Base doit analyser dans `base-docs/`.
|
|
48
|
+
|
|
49
|
+
### Suite du travail
|
|
50
|
+
Validation humaine, Base, puis implementation (Developer hors scope de ce role).
|
|
51
|
+
|
|
52
|
+
## Prochaine etape
|
|
53
|
+
|
|
54
|
+
Action concrete.
|
|
55
|
+
|
|
56
|
+
## Livrable
|
|
57
|
+
|
|
58
|
+
Chemin exact : `.kagents/docs/architect-docs/outputs/...`
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Le chat **n'est pas** une copie du fichier persistant. Ne pas lister tous les fichiers du repo.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Invariants — Architect / Spec
|
|
2
|
+
|
|
3
|
+
## Non-negociable
|
|
4
|
+
|
|
5
|
+
- Ne pas modifier le code applicatif, migrations, modeles, ni `base-docs/`.
|
|
6
|
+
- Ne pas ecrire SQL ni imposer un schema BDD.
|
|
7
|
+
- Ne pas modifier les commandes, agents ou skills Base.
|
|
8
|
+
- Ne pas lire ni recopier secrets (`.env`, credentials, tokens).
|
|
9
|
+
- Ne pas ecraser un livrable dans `architect-docs/outputs/` sans suffixe version explicite.
|
|
10
|
+
- Ne pas transformer PROPOSITION / DEDUIT en ETABLI sans source.
|
|
11
|
+
|
|
12
|
+
## Qualification
|
|
13
|
+
|
|
14
|
+
Chaque affirmation importante porte un statut : ETABLI, DEDUIT, PROPOSITION, A VALIDER, INCONNU, BLOQUANT.
|
|
15
|
+
|
|
16
|
+
## Repository vs documentation
|
|
17
|
+
|
|
18
|
+
Le code prevaut en cas de divergence avec une doc obsolete ; signaler l'ecart, ne pas trancher silencieusement.
|
|
19
|
+
|
|
20
|
+
## knowledge/context.md
|
|
21
|
+
|
|
22
|
+
Lecture autorisee. Ecriture automatique interdite sauf instruction explicite utilisateur ou politique projet documentee.
|