kushi-agents 5.9.4 → 5.9.7
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/bin/cli.mjs +190 -53
- package/package.json +1 -1
- package/plugin/agents/kushi.agent.md +3 -0
package/bin/cli.mjs
CHANGED
|
@@ -5,6 +5,62 @@ import { runMultiHost } from '../src/multi-host.mjs';
|
|
|
5
5
|
|
|
6
6
|
const args = process.argv.slice(2);
|
|
7
7
|
|
|
8
|
+
// ── verb aliases (v5.9.6+) ──────────────────────────────────────────────────
|
|
9
|
+
// Natural-language synonyms for the canonical verbs. Keeps `kushi update HCA`
|
|
10
|
+
// / `kushi pull HCA` / `kushi sync HCA` / etc. from confusing humans + agents.
|
|
11
|
+
const VERB_ALIASES = {
|
|
12
|
+
// refresh-equivalents
|
|
13
|
+
'update': 'refresh',
|
|
14
|
+
'pull': 'refresh',
|
|
15
|
+
'sync': 'refresh',
|
|
16
|
+
'regenerate': 'refresh',
|
|
17
|
+
'refresh-runner': 'refresh', // back-compat with v5.9.0–v5.9.5 internal name
|
|
18
|
+
// bootstrap-equivalents
|
|
19
|
+
'init': 'bootstrap',
|
|
20
|
+
'new': 'bootstrap',
|
|
21
|
+
'bootstrap-runner': 'bootstrap', // back-compat
|
|
22
|
+
};
|
|
23
|
+
if (args.length > 0 && VERB_ALIASES[args[0]]) {
|
|
24
|
+
args[0] = VERB_ALIASES[args[0]];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// ── alias resolution (v5.9.7+) ──────────────────────────────────────────────
|
|
28
|
+
// Mirrors `instructions/identity-resolution.instructions.md`: read alias from
|
|
29
|
+
// <cwd>/.kushi/config/user/project-evidence.yml, with KUSHI_ALIAS env override.
|
|
30
|
+
// No silent git-email derivation, no Graph fallback — same rules as chat.
|
|
31
|
+
async function resolveAlias() {
|
|
32
|
+
if (process.env.KUSHI_ALIAS && process.env.KUSHI_ALIAS.trim()) {
|
|
33
|
+
return { alias: process.env.KUSHI_ALIAS.trim(), source: 'env' };
|
|
34
|
+
}
|
|
35
|
+
const fs = await import('node:fs');
|
|
36
|
+
const path = await import('node:path');
|
|
37
|
+
const cfgPath = path.resolve(process.cwd(), '.kushi', 'config', 'user', 'project-evidence.yml');
|
|
38
|
+
if (!fs.existsSync(cfgPath)) return { alias: null, source: 'missing-config' };
|
|
39
|
+
try {
|
|
40
|
+
const txt = fs.readFileSync(cfgPath, 'utf-8');
|
|
41
|
+
const m = txt.match(/^\s*alias:\s*([^\s#]+)/m);
|
|
42
|
+
if (!m) return { alias: null, source: 'no-alias-key' };
|
|
43
|
+
const v = m[1].trim();
|
|
44
|
+
if (!v || v === '<auto>' || v.startsWith('<') || v === 'your-alias') {
|
|
45
|
+
return { alias: null, source: 'placeholder' };
|
|
46
|
+
}
|
|
47
|
+
return { alias: v, source: 'project-evidence.yml' };
|
|
48
|
+
} catch {
|
|
49
|
+
return { alias: null, source: 'read-error' };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function printAliasError(verb, project) {
|
|
54
|
+
console.error(`\n Couldn't resolve your alias — needed for the deterministic runner.`);
|
|
55
|
+
console.error(`\n The runner writes evidence into Evidence/<alias>/, so it must know who you are.`);
|
|
56
|
+
console.error(`\n Fix one of these (any works):`);
|
|
57
|
+
console.error(` • cd to a workspace that already has .kushi/ installed (run from there)`);
|
|
58
|
+
console.error(` • Run \`kushi setup\` to seed your identity in this workspace`);
|
|
59
|
+
console.error(` • Set the env var: $env:KUSHI_ALIAS = '<your-alias>' (PowerShell)`);
|
|
60
|
+
console.error(` export KUSHI_ALIAS=<your-alias> (bash)`);
|
|
61
|
+
console.error(` • Run from VS Code Copilot Chat instead: @Kushi ${verb} ${project}\n`);
|
|
62
|
+
}
|
|
63
|
+
|
|
8
64
|
// ── bare invocation ──────────────────────────────────────────────────────────
|
|
9
65
|
// Two bins share this cli (via thin wrappers in bin/kushi.mjs and
|
|
10
66
|
// bin/kushi-agents.mjs that set KUSHI_BIN_NAME). Behavior diverges on no-args:
|
|
@@ -33,6 +89,22 @@ if (args.length === 0) {
|
|
|
33
89
|
process.exit(0);
|
|
34
90
|
}
|
|
35
91
|
|
|
92
|
+
// ── version flag (v5.9.5+) ──────────────────────────────────────────────────
|
|
93
|
+
// `kushi --version` / `-v` / `version` → print version and exit. Previously
|
|
94
|
+
// these fell through to the installer's main() which printed the banner and
|
|
95
|
+
// started the install flow.
|
|
96
|
+
if (args.length > 0 && (args[0] === '--version' || args[0] === '-v' || args[0] === 'version')) {
|
|
97
|
+
const pathMod = await import('node:path');
|
|
98
|
+
const urlMod = await import('node:url');
|
|
99
|
+
const fsMod = await import('node:fs');
|
|
100
|
+
const here = pathMod.dirname(urlMod.fileURLToPath(import.meta.url));
|
|
101
|
+
const repoRoot = pathMod.resolve(here, '..');
|
|
102
|
+
let version = 'unknown';
|
|
103
|
+
try { version = JSON.parse(fsMod.readFileSync(pathMod.join(repoRoot, 'package.json'), 'utf-8')).version; } catch {}
|
|
104
|
+
console.log(version);
|
|
105
|
+
process.exit(0);
|
|
106
|
+
}
|
|
107
|
+
|
|
36
108
|
// ── doctor verb (v5.4.0+) ───────────────────────────────────────────────────
|
|
37
109
|
if (args.length > 0 && args[0] === 'doctor') {
|
|
38
110
|
const { spawnSync } = await import('node:child_process');
|
|
@@ -226,43 +298,56 @@ Usage: kushi [COMMAND] [ARGS...]
|
|
|
226
298
|
|
|
227
299
|
Kushi v${version} — multi-source M365 project evidence + Q&A agent.
|
|
228
300
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
301
|
+
CLI Commands (run from your shell):
|
|
302
|
+
|
|
303
|
+
Project pipeline (deterministic runners):
|
|
304
|
+
bootstrap <project> First-time pull for a project (alias: init, new)
|
|
305
|
+
refresh <project> Incremental refresh (alias: update, pull, sync, regenerate)
|
|
306
|
+
state <project> Re-render State/ from existing Evidence
|
|
307
|
+
references <project> Refresh shared references pool from Evidence URLs
|
|
308
|
+
discover <project> Discover M365 hints (sections, chats) for a project
|
|
309
|
+
|
|
310
|
+
Project lifecycle:
|
|
311
|
+
setup [<project>] Run the onboarding wizard / fill missing config
|
|
312
|
+
promote <project> <page> Move a project page into the global wiki (with redaction)
|
|
313
|
+
lint <project> Run wiki-lint checks on State/
|
|
314
|
+
|
|
315
|
+
Global wiki:
|
|
316
|
+
wiki Resolve + scaffold + open the global wiki (one-shot)
|
|
317
|
+
global init|status|ask|lint|show-root|set-root|migrate
|
|
318
|
+
|
|
319
|
+
Install / lifecycle:
|
|
320
|
+
upgrade npm i -g kushi-agents@latest then re-seed assets in cwd
|
|
321
|
+
uninstall [--keep-config] Remove <cwd>/.kushi/ (preserves Evidence/, State/)
|
|
322
|
+
doctor Aggregated health check (env, drift, evals, etc.)
|
|
323
|
+
--version | -v Print kushi version and exit
|
|
324
|
+
help | --help Show this help
|
|
325
|
+
|
|
326
|
+
Skill authoring (full profile):
|
|
327
|
+
create-skill <name> Scaffold a new plugin/skills/<name>/ tree
|
|
328
|
+
check-skill <name> Lint a skill against the blueprint
|
|
329
|
+
optimize-description <s> Rewrite a skill's description per optimizer rules
|
|
330
|
+
review-evals <skill> Render an HTML eval-review viewer
|
|
331
|
+
explain <topic> Explain a kushi concept (read-only)
|
|
332
|
+
remember <rule> Persist a project convention to CLAUDE.md
|
|
333
|
+
hooks list|test <project> Inspect or fire hook events
|
|
334
|
+
|
|
335
|
+
Chat Verbs (run from VS Code Copilot Chat with @Kushi <verb>):
|
|
336
|
+
@Kushi ask <project> <q> Cited Q&A over Evidence/ (auto-routes)
|
|
337
|
+
@Kushi status <project> Run-log + freshness summary
|
|
338
|
+
@Kushi consolidate <project> Merge per-user evidence into _Consolidated
|
|
339
|
+
@Kushi tour <project> [--top N] Auto-generated week-in-review walkthrough
|
|
340
|
+
@Kushi dashboard <project> Status dashboard
|
|
341
|
+
@Kushi aggregate <project> Multi-week aggregate
|
|
342
|
+
@Kushi fde-intake | fde-report | fde-triage <project>
|
|
343
|
+
@Kushi link-entities <project> Cross-link entities across projects
|
|
344
|
+
@Kushi teach <topic> Teach kushi a doctrine fact
|
|
345
|
+
@Kushi explain <topic> Recall a taught fact
|
|
346
|
+
@Kushi vertex-link | emit-vertex <project>
|
|
347
|
+
|
|
348
|
+
These verbs need the LLM-driven orchestrator that only Copilot Chat
|
|
349
|
+
provides (interactive clarifications + cited narrative). Typing them in
|
|
350
|
+
the shell prints a redirect to the chat path.
|
|
266
351
|
|
|
267
352
|
Install (run via npx — first-time / host install):
|
|
268
353
|
npx kushi-agents --clawpilot Install to ~/.copilot/m-skills/kushi/
|
|
@@ -276,6 +361,7 @@ Install (run via npx — first-time / host install):
|
|
|
276
361
|
WorkIQ: --with-workiq | --workiq-path <abs> | --skip-workiq-check
|
|
277
362
|
|
|
278
363
|
Run 'kushi <command> --help' for more information on a command (where supported).
|
|
364
|
+
Run 'kushi --version' to print the installed version.
|
|
279
365
|
Docs: https://gim-home.github.io/kushi/
|
|
280
366
|
|
|
281
367
|
In VS Code Chat the prefix is "@Kushi". In Clawpilot just say "kushi <verb>".
|
|
@@ -283,10 +369,12 @@ In VS Code Chat the prefix is "@Kushi". In Clawpilot just say "kushi <verb>".
|
|
|
283
369
|
}
|
|
284
370
|
|
|
285
371
|
|
|
286
|
-
// ──
|
|
287
|
-
// Thin shells that exec the deterministic runners.
|
|
288
|
-
//
|
|
289
|
-
|
|
372
|
+
// ── deterministic runner verbs (v5.9.0+, renamed in v5.9.6) ─────────────────
|
|
373
|
+
// Thin shells that exec the deterministic runners. `kushi refresh HCA` /
|
|
374
|
+
// `kushi bootstrap HCA` / `kushi state HCA` etc. all run from the global bin
|
|
375
|
+
// without users having to know the runner paths. Chat orchestrator
|
|
376
|
+
// `@Kushi refresh` adds narrative + interactive clarification on top.
|
|
377
|
+
if (args.length > 0 && ['state', 'refresh', 'bootstrap', 'discover', 'references'].includes(args[0])) {
|
|
290
378
|
const verb = args[0];
|
|
291
379
|
const project = args[1];
|
|
292
380
|
if (!project) {
|
|
@@ -298,15 +386,29 @@ if (args.length > 0 && ['state', 'refresh-runner', 'bootstrap-runner', 'discover
|
|
|
298
386
|
const urlMod = await import('node:url');
|
|
299
387
|
const here = pathMod.dirname(urlMod.fileURLToPath(import.meta.url));
|
|
300
388
|
const runnerMap = {
|
|
301
|
-
state:
|
|
389
|
+
state: 'pull-state.mjs',
|
|
302
390
|
references: 'pull-references.mjs',
|
|
303
|
-
discover:
|
|
304
|
-
|
|
305
|
-
|
|
391
|
+
discover: 'discover.mjs',
|
|
392
|
+
refresh: 'refresh.mjs',
|
|
393
|
+
bootstrap: 'bootstrap.mjs',
|
|
306
394
|
};
|
|
307
395
|
const runner = pathMod.resolve(here, '..', 'plugin', 'runners', runnerMap[verb]);
|
|
308
396
|
const passthrough = args.slice(2);
|
|
309
|
-
|
|
397
|
+
// v5.9.7: resolve alias the same way chat does, unless caller already passed --alias
|
|
398
|
+
const hasAliasFlag = passthrough.some((a, i) => a === '--alias' && passthrough[i + 1]);
|
|
399
|
+
let aliasArgs = [];
|
|
400
|
+
if (!hasAliasFlag) {
|
|
401
|
+
const { alias, source } = await resolveAlias();
|
|
402
|
+
if (!alias) {
|
|
403
|
+
printAliasError(verb, project);
|
|
404
|
+
process.exit(1);
|
|
405
|
+
}
|
|
406
|
+
aliasArgs = ['--alias', alias];
|
|
407
|
+
if (source === 'env') {
|
|
408
|
+
process.stderr.write(`\n Using alias='${alias}' from KUSHI_ALIAS env var.\n`);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
const r = spawnSync(process.execPath, [runner, '--project', project, ...aliasArgs, ...passthrough], { stdio: 'inherit' });
|
|
310
412
|
process.exit(r.status ?? 1);
|
|
311
413
|
}
|
|
312
414
|
|
|
@@ -338,12 +440,43 @@ if (args.length > 0 && args[0] === 'uninstall' && !args.includes('--clawpilot')
|
|
|
338
440
|
|
|
339
441
|
if (args.length > 0 && args[0] === 'upgrade') {
|
|
340
442
|
// Upgrade: npm i -g @latest, then re-seed assets in cwd preserving config.
|
|
443
|
+
// v5.9.5: capture stderr so users see WHY npm failed; detect Windows
|
|
444
|
+
// self-replacement (kushi.cmd locked because it's the running shell) and
|
|
445
|
+
// print a clear "rerun from a fresh shell" hint.
|
|
341
446
|
const { spawnSync } = await import('node:child_process');
|
|
342
447
|
console.log('\n Upgrading kushi-agents globally via npm...\n');
|
|
343
448
|
const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
344
|
-
const r1 = spawnSync(npm, ['install', '-g', 'kushi-agents@latest'], {
|
|
449
|
+
const r1 = spawnSync(npm, ['install', '-g', 'kushi-agents@latest'], {
|
|
450
|
+
stdio: ['inherit', 'inherit', 'pipe'],
|
|
451
|
+
encoding: 'utf-8',
|
|
452
|
+
});
|
|
345
453
|
if (r1.status !== 0) {
|
|
346
|
-
|
|
454
|
+
const stderr = (r1.stderr || '').toString();
|
|
455
|
+
if (stderr) {
|
|
456
|
+
console.error(stderr);
|
|
457
|
+
}
|
|
458
|
+
const looksLikeSelfReplace = process.platform === 'win32' && (
|
|
459
|
+
/EPERM|EBUSY|operation not permitted|kushi\.cmd|kushi-agents\.cmd|in use/i.test(stderr)
|
|
460
|
+
);
|
|
461
|
+
if (looksLikeSelfReplace) {
|
|
462
|
+
console.error([
|
|
463
|
+
'',
|
|
464
|
+
' npm could not overwrite the running kushi.cmd shim.',
|
|
465
|
+
' This is a known Windows limitation when `kushi upgrade` is launched from kushi itself.',
|
|
466
|
+
'',
|
|
467
|
+
' Fix: open a NEW PowerShell window and run:',
|
|
468
|
+
'',
|
|
469
|
+
' npm i -g kushi-agents@latest',
|
|
470
|
+
'',
|
|
471
|
+
' Then re-seed your workspace:',
|
|
472
|
+
'',
|
|
473
|
+
' cd ' + process.cwd(),
|
|
474
|
+
' npx kushi-agents@latest --force',
|
|
475
|
+
'',
|
|
476
|
+
].join('\n'));
|
|
477
|
+
} else if (!stderr) {
|
|
478
|
+
console.error('\n npm install failed (no stderr captured). Try:\n npm i -g kushi-agents@latest --foreground-scripts --loglevel=verbose\n');
|
|
479
|
+
}
|
|
347
480
|
process.exit(r1.status ?? 1);
|
|
348
481
|
}
|
|
349
482
|
console.log('\n Refreshing assets in cwd (config preserved)...\n');
|
|
@@ -361,10 +494,12 @@ if (args.length > 0 && args[0] === 'upgrade') {
|
|
|
361
494
|
// These verbs are dispatched by Copilot Chat (`@Kushi <verb>`), not the CLI.
|
|
362
495
|
// If a user types e.g. `kushi ask HCA "..."` in PowerShell, fall through to
|
|
363
496
|
// installer used to silently run. Now we print a friendly redirect.
|
|
497
|
+
// v5.9.6: refresh/bootstrap removed — they now route to the deterministic
|
|
498
|
+
// runners directly (see runner-verbs block above).
|
|
364
499
|
const CHAT_ONLY_VERBS = new Set([
|
|
365
|
-
'ask', '
|
|
500
|
+
'ask', 'status', 'consolidate', 'tour', 'dashboard',
|
|
366
501
|
'aggregate', 'fde-intake', 'fde-report', 'fde-triage', 'link-entities',
|
|
367
|
-
'migrate-files', '
|
|
502
|
+
'migrate-files', 'schema-evolve', 'teach', 'vertex-link',
|
|
368
503
|
'emit-vertex',
|
|
369
504
|
]);
|
|
370
505
|
if (args.length > 0 && CHAT_ONLY_VERBS.has(args[0])) {
|
|
@@ -379,9 +514,11 @@ if (args.length > 0 && CHAT_ONLY_VERBS.has(args[0])) {
|
|
|
379
514
|
In Clawpilot:
|
|
380
515
|
kushi ${verb}${rest ? ' ' + rest : ' <project> [args]'}
|
|
381
516
|
|
|
382
|
-
CLI verbs (run from PowerShell):
|
|
383
|
-
|
|
384
|
-
|
|
517
|
+
CLI verbs (deterministic, run from PowerShell):
|
|
518
|
+
kushi bootstrap | refresh | state | references | discover <project>
|
|
519
|
+
kushi promote | lint <project>
|
|
520
|
+
kushi wiki | global | doctor | upgrade | uninstall | setup
|
|
521
|
+
kushi help | --version
|
|
385
522
|
See: kushi help
|
|
386
523
|
`);
|
|
387
524
|
process.exit(2);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kushi-agents",
|
|
3
|
-
"version": "5.9.
|
|
3
|
+
"version": "5.9.7",
|
|
4
4
|
"description": "Install Kushi — multi-source project evidence agent with Comprehensive Structured Capture (CSC) into weekly-only files across Email, Teams, OneNote, Loop, SharePoint, Meetings, CRM, ADO. Meetings retain a sibling verbatim/ audit folder. WorkIQ-only for M365 sources (Graph / m365_* FORBIDDEN as fallbacks; user-paste is first-class). Host-agnostic.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -103,6 +103,9 @@ When a user message arrives:
|
|
|
103
103
|
|
|
104
104
|
1. Identify the **verb** (setup / aggregate / bootstrap / refresh / state / consolidate / status / pull / **ask** / fde-intake / fde-report / fde-triage).
|
|
105
105
|
- If the message starts with an explicit producer verb → use it.
|
|
106
|
+
- **Natural-language verb synonyms** auto-route to canonical verbs:
|
|
107
|
+
- "update <X>" / "pull <X>" / "sync <X>" / "regenerate <X>" / "do it all for <X>" / "weekly extract for <X>" / "bring <X> up to date" → `refresh <X>`
|
|
108
|
+
- "init <X>" / "new <X>" / "set up project evidence for <X>" / "add me to project <X>" / "add contributor to <X>" → `bootstrap <X>`
|
|
106
109
|
- **setup** dispatches immediately on `setup`, `setup --reconfigure`, `verify workiq`, `who am I to kushi`, `fix my install`, `setup kushi`.
|
|
107
110
|
- Else if the message contains a known project name AND a question shape (interrogative, "status of", "summarize", bare `<project> <topic>`) → `ask`.
|
|
108
111
|
- Else → ask the user to clarify.
|