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 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
- Common Commands:
230
- bootstrap <project> First-time setup for a project (full pull)
231
- refresh <project> Incremental refresh + rebuild State/
232
- ask <project> <question> Cited Q&A over Evidence/ (auto-routes; --file-back to save)
233
- status <project> Show run-log for a project
234
- wiki Resolve + scaffold + open the global wiki (one-shot)
235
- doctor Aggregated health check (env, drift, evals, etc.)
236
-
237
- Project Commands:
238
- state <project> Re-render State/ from existing Evidence
239
- references <project> Refresh shared references pool from Evidence URLs
240
- consolidate <project> Merge per-user evidence into _Consolidated
241
- lint <project> Run wiki-lint checks on State/
242
- promote <project> <page> Move a project page into the global wiki (with redaction)
243
- setup [<project>] Run the onboarding wizard / fill missing config
244
-
245
- Global Wiki Commands:
246
- global init Scaffold ~/.kushi-global/State/ (or KUSHI_GLOBAL_ROOT)
247
- global status Page counts + freshness
248
- global ask <question> Search the global wiki specifically
249
- global lint Privacy + freshness scan
250
- global show-root Show the 4-tier resolution chain
251
- global set-root <path> Persist globalRoot (--scope workspace|home)
252
- global migrate <new-path> Copy State/ to a new root + re-persist
253
-
254
- Lifecycle Commands:
255
- upgrade npm i -g kushi-agents@latest then re-seed assets in cwd
256
- uninstall [--keep-config] Remove <cwd>/.kushi/ (preserves Evidence/, State/)
257
-
258
- Authoring Commands:
259
- create-skill <name> Scaffold a new plugin/skills/<name>/ tree
260
- check-skill <name|--all> Lint a skill (or all skills) against the blueprint
261
- optimize-description <s> Rewrite a skill's description per optimizer rules
262
- review-evals <skill> Render an HTML eval-review viewer
263
- explain <topic> Explain a kushi concept (read-only)
264
- remember <rule> Persist a project convention to CLAUDE.md
265
- hooks list|test <project> Inspect or fire hook events
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
- // ── state / refresh / bootstrap verbs (v5.9.0+) ─────────────────────────────
287
- // Thin shells that exec the deterministic runners. Keeps `kushi state HCA` etc.
288
- // runnable from the global bin without users having to know the runner paths.
289
- if (args.length > 0 && ['state', 'refresh-runner', 'bootstrap-runner', 'discover', 'references'].includes(args[0])) {
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: 'pull-state.mjs',
389
+ state: 'pull-state.mjs',
302
390
  references: 'pull-references.mjs',
303
- discover: 'discover.mjs',
304
- 'refresh-runner': 'refresh.mjs',
305
- 'bootstrap-runner': 'bootstrap.mjs',
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
- const r = spawnSync(process.execPath, [runner, '--project', project, ...passthrough], { stdio: 'inherit' });
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'], { stdio: 'inherit' });
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
- console.error('\n npm install failed.\n');
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', 'bootstrap', 'refresh', 'status', 'consolidate', 'tour', 'dashboard',
500
+ 'ask', 'status', 'consolidate', 'tour', 'dashboard',
366
501
  'aggregate', 'fde-intake', 'fde-report', 'fde-triage', 'link-entities',
367
- 'migrate-files', 'pull', 'schema-evolve', 'teach', 'vertex-link',
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): kushi help, kushi wiki, kushi doctor,
383
- kushi upgrade, kushi uninstall, kushi setup,
384
- kushi state, kushi promote, kushi global, kushi lint
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.4",
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.