kushi-agents 5.2.0 → 5.4.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 CHANGED
@@ -154,6 +154,30 @@ Rules stored in `Evidence/<alias>/State/CLAUDE.md`. Read by `build-state`, `ask-
154
154
 
155
155
  ---
156
156
 
157
+ ## Global wiki (v5.3.0+)
158
+
159
+ A per-user **global wiki** at `~/.kushi-global/State/` for cross-engagement knowledge — same Karpathy shape as a project `State/`, marked `scope: global`.
160
+
161
+ ```bash
162
+ kushi global init # scaffold ~/.kushi-global/State/
163
+ kushi global status # counts + last-modified summary
164
+ kushi global ask "what's our confidence ladder pattern?"
165
+ kushi global lint # privacy + structure pass
166
+
167
+ # Project → global is explicit-only:
168
+ kushi promote <project> <answer-page> # refuses if identifiers detected
169
+ kushi promote <project> <answer-page> --force # redacts + writes target + back-link
170
+
171
+ # Routing under ask-project:
172
+ kushi ask <project> "..." # project-first (default)
173
+ kushi ask <project> "..." --global # global-first
174
+ kushi ask <project> "..." --project-only # suppress global
175
+ ```
176
+
177
+ The global root honors `$KUSHI_GLOBAL_ROOT` (used by tests). There is no auto-promotion path — privacy is always your call. See `plugin/instructions/global-wiki.instructions.md` + `plugin/instructions/multi-wiki-routing.instructions.md`.
178
+
179
+ ---
180
+
157
181
  ## Three install profiles
158
182
 
159
183
  Kushi ships in three tiers. Pick how much you take — the default (`standard`) matches v2.x behavior end-to-end.
package/bin/cli.mjs CHANGED
@@ -5,6 +5,63 @@ import { runMultiHost } from '../src/multi-host.mjs';
5
5
 
6
6
  const args = process.argv.slice(2);
7
7
 
8
+ // ── bare invocation (v5.4.0+) → welcome screen ──────────────────────────────
9
+ if (args.length === 0 && !process.env.KUSHI_SKIP_WELCOME) {
10
+ await printWelcome();
11
+ process.exit(0);
12
+ }
13
+
14
+ // ── doctor verb (v5.4.0+) ───────────────────────────────────────────────────
15
+ if (args.length > 0 && args[0] === 'doctor') {
16
+ const { spawnSync } = await import('node:child_process');
17
+ const pathMod = await import('node:path');
18
+ const urlMod = await import('node:url');
19
+ const here = pathMod.dirname(urlMod.fileURLToPath(import.meta.url));
20
+ const script = pathMod.resolve(here, '..', 'plugin', 'skills', 'doctor', 'doctor.ps1');
21
+ const psArgs = ['-NoProfile', '-File', script];
22
+ if (args.includes('--json')) psArgs.push('-Json');
23
+ if (args.includes('--strict')) psArgs.push('-Strict');
24
+ const r = spawnSync('pwsh', psArgs, { stdio: 'inherit' });
25
+ process.exit(r.status ?? 1);
26
+ }
27
+
28
+ // ── setup-wizard flag (v5.4.0+) ─────────────────────────────────────────────
29
+ if (args.includes('--setup-wizard')) {
30
+ const { runSetupWizard } = await import('../src/setup-wizard.mjs');
31
+ await runSetupWizard({ args });
32
+ process.exit(0);
33
+ }
34
+
35
+ async function printWelcome() {
36
+ const pathMod = await import('node:path');
37
+ const urlMod = await import('node:url');
38
+ const fsMod = await import('node:fs');
39
+ const here = pathMod.dirname(urlMod.fileURLToPath(import.meta.url));
40
+ const repoRoot = pathMod.resolve(here, '..');
41
+ let version = 'unknown';
42
+ try { version = JSON.parse(fsMod.readFileSync(pathMod.join(repoRoot, 'package.json'), 'utf-8')).version; } catch {}
43
+ let skillCount = 0;
44
+ try {
45
+ const skillsDir = pathMod.join(repoRoot, 'plugin', 'skills');
46
+ skillCount = fsMod.readdirSync(skillsDir, { withFileTypes: true })
47
+ .filter((d) => d.isDirectory() && !d.name.startsWith('_'))
48
+ .length;
49
+ } catch {}
50
+ console.log(`
51
+ kushi v${version} — multi-source M365 project evidence agent
52
+
53
+ First time? kushi doctor
54
+ Bootstrap a project: kushi setup <project>
55
+ Ask a question: kushi ask <project> "..."
56
+ Wizard install: npx kushi-agents --setup-wizard
57
+
58
+ Docs: https://gim-home.github.io/kushi/
59
+ Skills: ${skillCount} installed in plugin/skills/
60
+
61
+ Run kushi --help for the full verb list.
62
+ `);
63
+ }
64
+
8
65
  // ── skill-authoring verbs (v5.0.4+) ─────────────────────────────────────────
9
66
  // Dispatch directly to the skill-creator / skill-checker pwsh scripts.
10
67
  const SKILL_VERBS = new Set(['create-skill', 'check-skill', 'optimize-description', 'review-evals']);
@@ -17,15 +74,55 @@ if (args.length > 0 && SKILL_VERBS.has(args[0])) {
17
74
 
18
75
  // ── lint verb (v5.1.0+) ──────────────────────────────────────────────────────
19
76
  if (args.length > 0 && args[0] === 'lint') {
77
+ if (args.includes('--global')) {
78
+ const { runGlobalLint } = await import('../src/global-wiki-cli.mjs');
79
+ await runGlobalLint();
80
+ process.exit(0);
81
+ }
20
82
  const project = args[1] || '';
21
83
  if (!project) {
22
- console.error('\n Usage: kushi lint <project>\n');
84
+ console.error('\n Usage: kushi lint <project>\n kushi lint --global\n');
23
85
  process.exit(1);
24
86
  }
25
87
  await dispatchLint(project);
26
88
  process.exit(0);
27
89
  }
28
90
 
91
+ // ── global verb (v5.3.0+) ────────────────────────────────────────────────────
92
+ if (args.length > 0 && args[0] === 'global') {
93
+ const sub = args[1] || '';
94
+ const validSubs = ['init', 'status', 'ask', 'lint'];
95
+ if (!validSubs.includes(sub)) {
96
+ console.error('\n Usage: kushi global init Scaffold ~/.kushi-global/State/');
97
+ console.error(' kushi global status Show counts + freshness');
98
+ console.error(' kushi global ask <question> Ask the global wiki');
99
+ console.error(' kushi global lint Lint the global wiki\n');
100
+ process.exit(1);
101
+ }
102
+ const { runGlobalInit, runGlobalStatus, runGlobalAsk, runGlobalLint } = await import('../src/global-wiki-cli.mjs');
103
+ if (sub === 'init') await runGlobalInit();
104
+ else if (sub === 'status') await runGlobalStatus();
105
+ else if (sub === 'ask') await runGlobalAsk(args.slice(2).join(' '));
106
+ else if (sub === 'lint') await runGlobalLint();
107
+ process.exit(0);
108
+ }
109
+
110
+ // ── promote verb (v5.3.0+) ───────────────────────────────────────────────────
111
+ if (args.length > 0 && args[0] === 'promote') {
112
+ const project = args[1] || '';
113
+ const page = args[2] || '';
114
+ if (!project || !page) {
115
+ console.error('\n Usage: kushi promote <project> <page-path>\n');
116
+ console.error(' Copies a project State page into the global wiki with provenance metadata.');
117
+ console.error(' Refuses by default if customer identifiers are detected; pass --force after review.\n');
118
+ process.exit(1);
119
+ }
120
+ const force = args.includes('--force');
121
+ const { runPromote } = await import('../src/global-wiki-cli.mjs');
122
+ await runPromote(project, page, { force });
123
+ process.exit(0);
124
+ }
125
+
29
126
  // ── hooks verb (v5.2.0+) ─────────────────────────────────────────────────────
30
127
  if (args.length > 0 && args[0] === 'hooks') {
31
128
  const sub = args[1] || '';
@@ -108,6 +205,7 @@ if (args.includes('--help') || args.includes('-h')) {
108
205
 
109
206
  Wiki maintenance (v5.1.0+):
110
207
  lint <project> Run wiki-lint checks on State/ (contradictions, stale claims, orphans).
208
+ lint --global Lint the global wiki at ~/.kushi-global/State/.
111
209
 
112
210
  Hooks & observability (v5.2.0+):
113
211
  hooks list <project> List configured hooks for a project.
@@ -115,6 +213,19 @@ if (args.includes('--help') || args.includes('-h')) {
115
213
  explain <topic> Explain a kushi concept (pedagogical, read-only).
116
214
  remember <rule> Persist a project convention to CLAUDE.md.
117
215
 
216
+ Global wiki (v5.3.0+):
217
+ global init Scaffold ~/.kushi-global/State/ (env: KUSHI_GLOBAL_ROOT)
218
+ global status Show page counts + freshness for the global wiki.
219
+ global ask <question> Search the global wiki specifically.
220
+ global lint Lint the global wiki (alias for 'lint --global').
221
+ promote <project> <page> Move a project State page into global with redaction + back-link.
222
+ Refuses if customer identifiers are detected; --force after review.
223
+
224
+ Stabilization (v5.4.0+):
225
+ doctor Aggregated health check (env, self-check, evals, skill-checker, drift, global).
226
+ --json for CI; --strict to fail on yellow.
227
+ --setup-wizard Interactive first-run flow (engagement root, hosts, global wiki).
228
+
118
229
  After install, talk to Kushi:
119
230
  bootstrap <project> First-time setup
120
231
  refresh <project> Incremental refresh + rebuild State/
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kushi-agents",
3
- "version": "5.2.0",
3
+ "version": "5.4.0",
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": {
@@ -41,7 +41,7 @@
41
41
  },
42
42
  "license": "MIT",
43
43
  "scripts": {
44
- "test": "node --test src/check-workiq.test.mjs src/seed-config.test.mjs src/sanitize-workiq-input.test.mjs src/detect-vertex-repo.test.mjs src/vertex-validate.test.mjs src/emit-vertex.e2e.test.mjs src/config-root-resolve.test.mjs src/forbidden-workiq-phrasings.test.mjs src/multi-host-install.test.mjs src/eval-aggregator.test.mjs src/eval-runner.test.mjs src/skill-creator.test.mjs src/skill-checker.test.mjs src/hooks-dispatcher.test.mjs src/parallel-refresh.test.mjs src/otel-emit.test.mjs src/teach.test.mjs src/schema-evolve.test.mjs",
44
+ "test": "node --test src/check-workiq.test.mjs src/seed-config.test.mjs src/sanitize-workiq-input.test.mjs src/detect-vertex-repo.test.mjs src/vertex-validate.test.mjs src/emit-vertex.e2e.test.mjs src/config-root-resolve.test.mjs src/forbidden-workiq-phrasings.test.mjs src/multi-host-install.test.mjs src/eval-aggregator.test.mjs src/eval-runner.test.mjs src/skill-creator.test.mjs src/skill-checker.test.mjs src/hooks-dispatcher.test.mjs src/parallel-refresh.test.mjs src/otel-emit.test.mjs src/teach.test.mjs src/schema-evolve.test.mjs src/global-wiki.test.mjs src/promote.test.mjs src/doctor.test.mjs src/setup-wizard.test.mjs src/cli-no-args.test.mjs",
45
45
  "test:integration:bootstrap": "node src/bootstrap-dryrun.integration.test.mjs",
46
46
  "smoke": "node scripts/smoke.mjs",
47
47
  "eval": "pwsh plugin/skills/eval/run-evals.ps1 -Skill",