analyzthis_design 2.3.1 → 2.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/HOW-TO-USE.md +2 -1
- package/README.md +14 -3
- package/dist/HOW-TO-USE.md +2 -1
- package/dist/README.md +14 -3
- package/dist/bin/cli.js +15 -3
- package/dist/lib/chunk-run.js +2 -0
- package/dist/lib/install.js +2 -0
- package/dist/lib/knowledge.js +49 -18
- package/dist/lib/mcp-server.js +163 -30
- package/dist/lib/orchestrator/run.js +5 -0
- package/dist/lib/session.js +33 -2
- package/dist/skills/anuj/SKILL.md +7 -0
- package/dist/skills/arjun/SKILL.md +5 -263
- package/dist/skills/arjun/references/lens.md +265 -0
- package/dist/skills/kavi/SKILL.md +7 -0
- package/dist/skills/knowledge-bank/SKILL.md +11 -25
- package/dist/skills/meera/SKILL.md +7 -0
- package/dist/skills/noor/SKILL.md +7 -0
- package/dist/skills/persona-orchestrator/SKILL.md +5 -195
- package/dist/skills/persona-orchestrator/references/lens.md +197 -0
- package/dist/skills/priya/SKILL.md +7 -0
- package/dist/skills/raj/SKILL.md +7 -0
- package/dist/skills/receipt/SKILL.md +17 -0
- package/dist/skills/ux-story-gate/SKILL.md +5 -338
- package/dist/skills/ux-story-gate/references/lens.md +340 -0
- package/dist/skills/zara/SKILL.md +7 -0
- package/package.json +1 -1
- package/skills/anuj/SKILL.md +7 -0
- package/skills/arjun/SKILL.md +5 -263
- package/skills/arjun/references/lens.md +265 -0
- package/skills/kavi/SKILL.md +7 -0
- package/skills/knowledge-bank/SKILL.md +11 -25
- package/skills/meera/SKILL.md +7 -0
- package/skills/noor/SKILL.md +7 -0
- package/skills/persona-orchestrator/SKILL.md +5 -195
- package/skills/persona-orchestrator/references/lens.md +197 -0
- package/skills/priya/SKILL.md +7 -0
- package/skills/raj/SKILL.md +7 -0
- package/skills/receipt/SKILL.md +17 -0
- package/skills/ux-story-gate/SKILL.md +5 -338
- package/skills/ux-story-gate/references/lens.md +340 -0
- package/skills/zara/SKILL.md +7 -0
package/HOW-TO-USE.md
CHANGED
|
@@ -108,7 +108,8 @@ npx analyzthis_design sync --target all
|
|
|
108
108
|
| Review against PRDs and stories | `/ux-story-gate` | Task map + routing before critique |
|
|
109
109
|
| Set visual direction | `/mood-board` | References + design-system patterns + team deliberation |
|
|
110
110
|
| Index the repo for personas | `/kavi` | Kavi → knowledge bank |
|
|
111
|
-
| Get a single-lens opinion | `/arjun`, `/meera`, `/priya`, `/zara`, `/noor`, `/anuj` | Targeted follow-up |
|
|
111
|
+
| Get a single-lens opinion | `/arjun`, `/meera`, `/priya`, `/zara`, `/noor`, `/anuj` | Targeted follow-up. Default is a short verdict — say expand for the full schema |
|
|
112
|
+
| See inferred token spend | `/receipt` | Not a bill. Same as `npx analyzthis_design receipt` |
|
|
112
113
|
|
|
113
114
|
**Important:** do not use `/persona-orchestrator` or `/design-critic` when you want wireframes. They are for critique.
|
|
114
115
|
|
package/README.md
CHANGED
|
@@ -4,6 +4,17 @@ A set of AI design personas and a task-first evaluation framework that plugs int
|
|
|
4
4
|
|
|
5
5
|
Install once. Run structured UX critiques, multi-phase ideation, and task-grounded screen reviews — directly inside your AI chat. **No external LLM API keys required** for CLI orchestrator runs: **`/devi`** voices each persona from your host IDE (Cursor, Claude, etc.).
|
|
6
6
|
|
|
7
|
+
## v2.4.0 — Claude-path efficiency (1 Sep 2026)
|
|
8
|
+
|
|
9
|
+
Same SHIP / REVISE / BLOCK. Fewer tokens on Claude Code and Claude Desktop. Not Caveman-speak. Not a proxy.
|
|
10
|
+
|
|
11
|
+
- **Lite MCP catalog (default):** `analyzthis_design` (router) + `analyzthis_retrieve` + `analyzthis_session` + `analyzthis_receipt`. Old 19-tool list: `ANALYZTHIS_MCP_CATALOG=full` or `npx analyzthis_design mcp --catalog full`.
|
|
12
|
+
- **Receipt:** every MCP result ends with inferred tokens (not a bill). CLI: `npx analyzthis_design receipt`. Slash: `/receipt`.
|
|
13
|
+
- **Slim skill fronts:** Arjun, story-gate, and orchestrator load a short front. Call retrieve (`kind=skill`) for the lens. Personas default to verdict + top 3 + one evidence line; say **expand** for the full schema.
|
|
14
|
+
- **Knowledge bank** is an index. Load one persona slice (`kind=knowledge`, `persona=zara`). Do not inject the whole bank.
|
|
15
|
+
- **Tokens per verdict** prints on `receipt` and CLI `run`.
|
|
16
|
+
- Optional: wrap our stdio MCP through Caveman’s shrink if you already run Caveman. We do not ship a proxy.
|
|
17
|
+
|
|
7
18
|
## v2.3.1 — independently callable personas (31 Aug 2026)
|
|
8
19
|
|
|
9
20
|
After install, type `/noor`, `/anuj`, `/arjun`, `/meera`, `/priya`, `/zara`, `/raj`, `/kavi` even if Claude’s slash menu only lists Getting Started.
|
|
@@ -37,7 +48,7 @@ Pass `--global` to opt into the legacy merged behavior (read `config.sources` an
|
|
|
37
48
|
|
|
38
49
|
Use `npx analyzthis_design run-unchunked` for the legacy single-pass orchestrator.
|
|
39
50
|
|
|
40
|
-
**npm:** [analyzthis_design](https://www.npmjs.com/package/analyzthis_design) · **Current version:** 2.
|
|
51
|
+
**npm:** [analyzthis_design](https://www.npmjs.com/package/analyzthis_design) · **Current version:** 2.4.0 · **Step-by-step guide:** [HOW-TO-USE.md](./HOW-TO-USE.md)
|
|
41
52
|
|
|
42
53
|
---
|
|
43
54
|
|
|
@@ -63,7 +74,7 @@ npx analyzthis_design run-unchunked --task "Review invoice approval screen" --pr
|
|
|
63
74
|
|
|
64
75
|
> **Security:** This package publishes **plain source** — no obfuscation, no minification, no dynamic require. Every file in `dist/` is readable and auditable. The `postinstall` script only prints a welcome message; it does **not** write to any AI-agent directories. Skill installation requires an explicit `npx analyzthis_design install --target <ide>` (or `npx analyzthis_design --target <ide>`).
|
|
65
76
|
>
|
|
66
|
-
> **MCP (universal):** `npx analyzthis_design mcp` starts a local MCP server
|
|
77
|
+
> **MCP (universal):** `npx analyzthis_design mcp` starts a local MCP server. Default catalog is **lite** (router + retrieve + session + receipt). Full 19 named tools: `ANALYZTHIS_MCP_CATALOG=full` or `mcp --catalog full`. Auto-configures for Cursor, Claude Desktop, **Claude Code**, and Windsurf during install. For Lovable, v0, Bolt, Replit, ChatGPT: run `npx analyzthis_design mcp --configure <tool>` for a config snippet.
|
|
67
78
|
|
|
68
79
|
### Install by target IDE
|
|
69
80
|
|
|
@@ -870,7 +881,7 @@ skills/
|
|
|
870
881
|
| **MCP server** | `npx analyzthis_design mcp` starts a local MCP server exposing 19 tools — all 8 individual personas + 6 combination passes + 5 utilities. Any MCP-compatible client can discover and call them. |
|
|
871
882
|
| **Auto-configure MCP** | `npx analyzthis_design mcp --configure cursor` (or `claude`, `windsurf`) writes the MCP config automatically. `--target all` now auto-configures MCP during install. |
|
|
872
883
|
| **Universal IDE support** | Cursor, Claude Desktop, Windsurf auto-configured. Lovable, v0, Bolt, Replit, ChatGPT: run `mcp --configure <tool>` for a copy-paste config snippet. |
|
|
873
|
-
| **
|
|
884
|
+
| **MCP lite + full** | Default: router (`analyzthis_design`) + retrieve + session + receipt. Full 19 named tools behind `--catalog full`. |
|
|
874
885
|
| **System prompt fallback** | `analyzthis_system_prompt` tool generates a consolidated prompt for tools that don't support MCP yet |
|
|
875
886
|
|
|
876
887
|
## What's new in v2.2
|
package/dist/HOW-TO-USE.md
CHANGED
|
@@ -108,7 +108,8 @@ npx analyzthis_design sync --target all
|
|
|
108
108
|
| Review against PRDs and stories | `/ux-story-gate` | Task map + routing before critique |
|
|
109
109
|
| Set visual direction | `/mood-board` | References + design-system patterns + team deliberation |
|
|
110
110
|
| Index the repo for personas | `/kavi` | Kavi → knowledge bank |
|
|
111
|
-
| Get a single-lens opinion | `/arjun`, `/meera`, `/priya`, `/zara`, `/noor`, `/anuj` | Targeted follow-up |
|
|
111
|
+
| Get a single-lens opinion | `/arjun`, `/meera`, `/priya`, `/zara`, `/noor`, `/anuj` | Targeted follow-up. Default is a short verdict — say expand for the full schema |
|
|
112
|
+
| See inferred token spend | `/receipt` | Not a bill. Same as `npx analyzthis_design receipt` |
|
|
112
113
|
|
|
113
114
|
**Important:** do not use `/persona-orchestrator` or `/design-critic` when you want wireframes. They are for critique.
|
|
114
115
|
|
package/dist/README.md
CHANGED
|
@@ -4,6 +4,17 @@ A set of AI design personas and a task-first evaluation framework that plugs int
|
|
|
4
4
|
|
|
5
5
|
Install once. Run structured UX critiques, multi-phase ideation, and task-grounded screen reviews — directly inside your AI chat. **No external LLM API keys required** for CLI orchestrator runs: **`/devi`** voices each persona from your host IDE (Cursor, Claude, etc.).
|
|
6
6
|
|
|
7
|
+
## v2.4.0 — Claude-path efficiency (1 Sep 2026)
|
|
8
|
+
|
|
9
|
+
Same SHIP / REVISE / BLOCK. Fewer tokens on Claude Code and Claude Desktop. Not Caveman-speak. Not a proxy.
|
|
10
|
+
|
|
11
|
+
- **Lite MCP catalog (default):** `analyzthis_design` (router) + `analyzthis_retrieve` + `analyzthis_session` + `analyzthis_receipt`. Old 19-tool list: `ANALYZTHIS_MCP_CATALOG=full` or `npx analyzthis_design mcp --catalog full`.
|
|
12
|
+
- **Receipt:** every MCP result ends with inferred tokens (not a bill). CLI: `npx analyzthis_design receipt`. Slash: `/receipt`.
|
|
13
|
+
- **Slim skill fronts:** Arjun, story-gate, and orchestrator load a short front. Call retrieve (`kind=skill`) for the lens. Personas default to verdict + top 3 + one evidence line; say **expand** for the full schema.
|
|
14
|
+
- **Knowledge bank** is an index. Load one persona slice (`kind=knowledge`, `persona=zara`). Do not inject the whole bank.
|
|
15
|
+
- **Tokens per verdict** prints on `receipt` and CLI `run`.
|
|
16
|
+
- Optional: wrap our stdio MCP through Caveman’s shrink if you already run Caveman. We do not ship a proxy.
|
|
17
|
+
|
|
7
18
|
## v2.3.1 — independently callable personas (31 Aug 2026)
|
|
8
19
|
|
|
9
20
|
After install, type `/noor`, `/anuj`, `/arjun`, `/meera`, `/priya`, `/zara`, `/raj`, `/kavi` even if Claude’s slash menu only lists Getting Started.
|
|
@@ -37,7 +48,7 @@ Pass `--global` to opt into the legacy merged behavior (read `config.sources` an
|
|
|
37
48
|
|
|
38
49
|
Use `npx analyzthis_design run-unchunked` for the legacy single-pass orchestrator.
|
|
39
50
|
|
|
40
|
-
**npm:** [analyzthis_design](https://www.npmjs.com/package/analyzthis_design) · **Current version:** 2.
|
|
51
|
+
**npm:** [analyzthis_design](https://www.npmjs.com/package/analyzthis_design) · **Current version:** 2.4.0 · **Step-by-step guide:** [HOW-TO-USE.md](./HOW-TO-USE.md)
|
|
41
52
|
|
|
42
53
|
---
|
|
43
54
|
|
|
@@ -63,7 +74,7 @@ npx analyzthis_design run-unchunked --task "Review invoice approval screen" --pr
|
|
|
63
74
|
|
|
64
75
|
> **Security:** This package publishes **plain source** — no obfuscation, no minification, no dynamic require. Every file in `dist/` is readable and auditable. The `postinstall` script only prints a welcome message; it does **not** write to any AI-agent directories. Skill installation requires an explicit `npx analyzthis_design install --target <ide>` (or `npx analyzthis_design --target <ide>`).
|
|
65
76
|
>
|
|
66
|
-
> **MCP (universal):** `npx analyzthis_design mcp` starts a local MCP server
|
|
77
|
+
> **MCP (universal):** `npx analyzthis_design mcp` starts a local MCP server. Default catalog is **lite** (router + retrieve + session + receipt). Full 19 named tools: `ANALYZTHIS_MCP_CATALOG=full` or `mcp --catalog full`. Auto-configures for Cursor, Claude Desktop, **Claude Code**, and Windsurf during install. For Lovable, v0, Bolt, Replit, ChatGPT: run `npx analyzthis_design mcp --configure <tool>` for a config snippet.
|
|
67
78
|
|
|
68
79
|
### Install by target IDE
|
|
69
80
|
|
|
@@ -870,7 +881,7 @@ skills/
|
|
|
870
881
|
| **MCP server** | `npx analyzthis_design mcp` starts a local MCP server exposing 19 tools — all 8 individual personas + 6 combination passes + 5 utilities. Any MCP-compatible client can discover and call them. |
|
|
871
882
|
| **Auto-configure MCP** | `npx analyzthis_design mcp --configure cursor` (or `claude`, `windsurf`) writes the MCP config automatically. `--target all` now auto-configures MCP during install. |
|
|
872
883
|
| **Universal IDE support** | Cursor, Claude Desktop, Windsurf auto-configured. Lovable, v0, Bolt, Replit, ChatGPT: run `mcp --configure <tool>` for a copy-paste config snippet. |
|
|
873
|
-
| **
|
|
884
|
+
| **MCP lite + full** | Default: router (`analyzthis_design`) + retrieve + session + receipt. Full 19 named tools behind `--catalog full`. |
|
|
874
885
|
| **System prompt fallback** | `analyzthis_system_prompt` tool generates a consolidated prompt for tools that don't support MCP yet |
|
|
875
886
|
|
|
876
887
|
## What's new in v2.2
|
package/dist/bin/cli.js
CHANGED
|
@@ -75,6 +75,7 @@ Usage:
|
|
|
75
75
|
── Efficiency / cost commands ────────────────────────────────
|
|
76
76
|
metrics Print the last run's cost metrics (--all for every project)
|
|
77
77
|
cost Print the last run's $ cost from config.pricing (--all for every project)
|
|
78
|
+
receipt Inferred token receipt for host (slash/MCP) turns — not a bill
|
|
78
79
|
export-training Write accepted-output JSONL pairs for LoRA prep
|
|
79
80
|
(--persona <id>, --all, --output <path>)
|
|
80
81
|
feedback export Write rejected + correction JSONL pairs (DPO / negative examples)
|
|
@@ -86,9 +87,11 @@ Usage:
|
|
|
86
87
|
── MCP server (for any AI IDE: Cursor, Claude Desktop, Lovable, v0, Bolt) ──
|
|
87
88
|
mcp Start the MCP server on stdio (for MCP client config)
|
|
88
89
|
mcp --configure cursor Write MCP config to ~/.cursor/mcp.json
|
|
89
|
-
mcp --configure claude Write MCP config to Claude Desktop
|
|
90
|
+
mcp --configure claude Write MCP config to Claude Desktop + Claude Code
|
|
90
91
|
mcp --configure windsurf Write MCP config to Windsurf
|
|
91
92
|
mcp --configure <tool> Print manual MCP config for any other tool
|
|
93
|
+
mcp --catalog lite|full Lite (default): router + retrieve + session + receipt
|
|
94
|
+
full: all 19 named tools. Or ANALYZTHIS_MCP_CATALOG=full
|
|
92
95
|
|
|
93
96
|
── Mood board commands ─────────────────────────────────────
|
|
94
97
|
moodboard create --task <text> Build a mood board from web + DS references
|
|
@@ -769,11 +772,12 @@ switch (cmd) {
|
|
|
769
772
|
case 'mcp': {
|
|
770
773
|
const mcpServer = require('../lib/mcp-server');
|
|
771
774
|
const configureTarget = getFlag('configure');
|
|
775
|
+
const catalogVal = getFlag('catalog');
|
|
772
776
|
if (configureTarget) {
|
|
773
|
-
mcpServer.writeMcpConfig(configureTarget);
|
|
777
|
+
mcpServer.writeMcpConfig(configureTarget, { catalog: catalogVal });
|
|
774
778
|
break;
|
|
775
779
|
}
|
|
776
|
-
mcpServer.startStdioServer();
|
|
780
|
+
mcpServer.startStdioServer(catalogVal);
|
|
777
781
|
break;
|
|
778
782
|
}
|
|
779
783
|
|
|
@@ -965,6 +969,8 @@ switch (cmd) {
|
|
|
965
969
|
console.log(` objections_raised: ${m.objections_raised ?? 0}`);
|
|
966
970
|
console.log(` objections_resolved: ${m.objections_resolved ?? 0}`);
|
|
967
971
|
console.log(` raj_escalations: ${m.raj_escalations ?? 0}`);
|
|
972
|
+
console.log(` host_turns: ${(m.host_turns || []).length}`);
|
|
973
|
+
console.log(` tokens_per_verdict: ${m.tokens_per_verdict ?? 'n/a'}`);
|
|
968
974
|
const d = state.deliberation;
|
|
969
975
|
if (d?.mode) {
|
|
970
976
|
console.log(` deliberation_mode: ${d.mode}, consensus=${d.consensus_reached}`);
|
|
@@ -981,6 +987,12 @@ switch (cmd) {
|
|
|
981
987
|
break;
|
|
982
988
|
}
|
|
983
989
|
|
|
990
|
+
case 'receipt': {
|
|
991
|
+
const receipt = require('../lib/receipt');
|
|
992
|
+
console.log('\n' + receipt.report({ project: projectVal }) + '\n');
|
|
993
|
+
break;
|
|
994
|
+
}
|
|
995
|
+
|
|
984
996
|
// ── Persona feedback (v1.16) ────────────────────────────────────────────
|
|
985
997
|
|
|
986
998
|
case 'feedback': {
|
package/dist/lib/chunk-run.js
CHANGED
|
@@ -172,6 +172,8 @@ async function runChunked(opts) {
|
|
|
172
172
|
output_tokens_est: totalOutput,
|
|
173
173
|
cost_usd: Number(totalCost.toFixed(6)),
|
|
174
174
|
mode: 'chunked',
|
|
175
|
+
verdicts_this_run: 1,
|
|
176
|
+
tokens_per_verdict: totalInput || null,
|
|
175
177
|
cache_hits: cacheHits,
|
|
176
178
|
effort_log: results.map(function(r) {
|
|
177
179
|
return {
|
package/dist/lib/install.js
CHANGED
|
@@ -33,6 +33,7 @@ const PROJECT_COMMANDS = [
|
|
|
33
33
|
'design-critic',
|
|
34
34
|
'getting-started',
|
|
35
35
|
'devi',
|
|
36
|
+
'receipt',
|
|
36
37
|
];
|
|
37
38
|
|
|
38
39
|
const SKILLS = [
|
|
@@ -60,6 +61,7 @@ const SKILLS = [
|
|
|
60
61
|
'design-personas',
|
|
61
62
|
'design-reference',
|
|
62
63
|
'knowledge-bank',
|
|
64
|
+
'receipt',
|
|
63
65
|
];
|
|
64
66
|
|
|
65
67
|
function getPackageVersion() {
|
package/dist/lib/knowledge.js
CHANGED
|
@@ -8,12 +8,10 @@ const crypto = require('crypto');
|
|
|
8
8
|
|
|
9
9
|
const CONFIG_DIR = path.join(os.homedir(), '.analyzthis_design');
|
|
10
10
|
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
11
|
-
// When published, this file lives at dist/lib/ — go up two levels to reach package root
|
|
12
|
-
const KNOWLEDGE_SKILL = path.join(__dirname, '..', '..', 'skills', 'knowledge-bank', 'SKILL.md');
|
|
13
|
-
const KNOWLEDGE_SLICE_ROOT = path.join(CONFIG_DIR, 'kb-slices');
|
|
14
|
-
|
|
15
11
|
const { resolvePackageRoot } = require('./platforms');
|
|
16
12
|
const PACKAGE_ROOT = resolvePackageRoot(__dirname);
|
|
13
|
+
const KNOWLEDGE_SKILL = path.join(PACKAGE_ROOT, 'skills', 'knowledge-bank', 'SKILL.md');
|
|
14
|
+
const KNOWLEDGE_SLICE_ROOT = path.join(CONFIG_DIR, 'kb-slices');
|
|
17
15
|
const AGENTS_DIR = path.join(PACKAGE_ROOT, 'agents');
|
|
18
16
|
|
|
19
17
|
// Keywords used to auto-group vault notes into categories
|
|
@@ -326,41 +324,74 @@ function sync({ targets = ['cursor'], project, global = false, cwd } = {}) {
|
|
|
326
324
|
? 'global (merged across projects)'
|
|
327
325
|
: `project: ${scopeInfo.projectId}`;
|
|
328
326
|
|
|
329
|
-
let
|
|
330
|
-
name: knowledge-bank
|
|
331
|
-
description:
|
|
327
|
+
let fullMd = `---
|
|
328
|
+
name: knowledge-bank-full
|
|
329
|
+
description: Full project notes. Do not load this file into chat. Retrieve one persona slice instead.
|
|
332
330
|
disable-model-invocation: true
|
|
333
331
|
---
|
|
334
332
|
|
|
335
|
-
# Knowledge Bank
|
|
333
|
+
# Knowledge Bank (full dump — do not inject)
|
|
336
334
|
|
|
337
335
|
> Last synced: ${date}
|
|
338
336
|
> Scope: ${scopeLabel}
|
|
339
337
|
> Sources: ${sourceList}
|
|
340
338
|
> Files loaded: ${totalFiles}
|
|
341
339
|
|
|
342
|
-
**INSTRUCTION TO ALL PERSONAS:** This knowledge bank contains project-specific context that overrides your built-in defaults. Read every section below before forming any opinion. When this knowledge bank conflicts with your built-in knowledge, this knowledge bank wins.
|
|
343
|
-
|
|
344
|
-
---
|
|
345
|
-
|
|
346
340
|
`;
|
|
347
341
|
|
|
348
342
|
let hasContent = false;
|
|
343
|
+
let indexLines = '';
|
|
349
344
|
for (const { key, heading } of sectionDefs) {
|
|
350
345
|
if (sections[key].length === 0) continue;
|
|
351
346
|
hasContent = true;
|
|
352
|
-
|
|
347
|
+
fullMd += `${heading}\n\n`;
|
|
348
|
+
indexLines += `${heading}\n`;
|
|
353
349
|
for (const note of sections[key]) {
|
|
354
|
-
|
|
350
|
+
fullMd += `### ${note.title}\n\n${note.content}\n\n`;
|
|
351
|
+
indexLines += `- ${note.title}\n`;
|
|
355
352
|
}
|
|
356
|
-
|
|
353
|
+
fullMd += '---\n\n';
|
|
354
|
+
indexLines += '\n';
|
|
357
355
|
}
|
|
358
356
|
|
|
359
357
|
if (!hasContent) {
|
|
360
|
-
|
|
358
|
+
fullMd += `_No matching files found. Check your --tags or --include filters, or remove filters to include all notes._\n`;
|
|
359
|
+
indexLines += `_No notes yet. Run collect/sync first._\n`;
|
|
361
360
|
}
|
|
362
361
|
|
|
363
|
-
|
|
362
|
+
const md = `---
|
|
363
|
+
name: knowledge-bank
|
|
364
|
+
description: Project knowledge index — retrieve one persona slice. Do not load the full bank.
|
|
365
|
+
disable-model-invocation: true
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
# Knowledge Bank
|
|
369
|
+
|
|
370
|
+
> Last synced: ${date}
|
|
371
|
+
> Scope: ${scopeLabel}
|
|
372
|
+
> Sources: ${sourceList}
|
|
373
|
+
> Files loaded: ${totalFiles}
|
|
374
|
+
|
|
375
|
+
**INSTRUCTION TO ALL PERSONAS:** Load your persona slice via retrieve. Do not load the whole bank. When a slice conflicts with built-in defaults, the slice wins.
|
|
376
|
+
|
|
377
|
+
\`\`\`
|
|
378
|
+
npx analyzthis_design retrieve — or MCP analyzthis_retrieve
|
|
379
|
+
kind=knowledge persona=arjun|meera|priya|zara|noor|anuj|raj|kavi
|
|
380
|
+
\`\`\`
|
|
381
|
+
|
|
382
|
+
You cannot know host tokens. Do not invent a dollar figure.
|
|
383
|
+
|
|
384
|
+
## Index (titles only)
|
|
385
|
+
|
|
386
|
+
${indexLines}
|
|
387
|
+
`;
|
|
388
|
+
|
|
389
|
+
// Full dump stays on disk for retrieve; the skill is an index only.
|
|
390
|
+
const projectIdForFull = scopeInfo.projectId || 'default';
|
|
391
|
+
const fullDir = path.join(KNOWLEDGE_SLICE_ROOT, projectIdForFull);
|
|
392
|
+
fs.mkdirSync(fullDir, { recursive: true });
|
|
393
|
+
fs.writeFileSync(path.join(fullDir, 'full.md'), fullMd);
|
|
394
|
+
|
|
364
395
|
fs.mkdirSync(path.dirname(KNOWLEDGE_SKILL), { recursive: true });
|
|
365
396
|
fs.writeFileSync(KNOWLEDGE_SKILL, md);
|
|
366
397
|
|
|
@@ -470,7 +501,7 @@ function buildPersonaSlice(personaId, sections, sectionDefs, projectId) {
|
|
|
470
501
|
}
|
|
471
502
|
|
|
472
503
|
function writePersonaSlices(sections, sectionDefs, projectId) {
|
|
473
|
-
const personas = ['arjun', 'meera', 'priya', 'zara', 'noor', 'anuj', 'raj'];
|
|
504
|
+
const personas = ['arjun', 'meera', 'priya', 'zara', 'noor', 'anuj', 'raj', 'kavi'];
|
|
474
505
|
const dir = path.join(KNOWLEDGE_SLICE_ROOT, projectId || 'default');
|
|
475
506
|
fs.mkdirSync(dir, { recursive: true });
|
|
476
507
|
const written = [];
|
package/dist/lib/mcp-server.js
CHANGED
|
@@ -248,16 +248,18 @@ var TOOLS = [
|
|
|
248
248
|
},
|
|
249
249
|
{
|
|
250
250
|
name: 'analyzthis_retrieve',
|
|
251
|
-
description: 'Retrieve
|
|
251
|
+
description: 'Retrieve on demand: CSV rows, a skill reference file, or one knowledge-bank persona slice. Do not load the full bank.',
|
|
252
252
|
inputSchema: {
|
|
253
253
|
type: 'object',
|
|
254
254
|
properties: {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
255
|
+
kind: { type: 'string', enum: ['csv', 'skill', 'knowledge'], description: 'csv (default), skill (references/*.md), or knowledge (one persona slice)' },
|
|
256
|
+
file: { type: 'string', description: 'CSV filename, or skill id (e.g. arjun), or knowledge/<persona>' },
|
|
257
|
+
column: { type: 'string', description: 'CSV column to filter on' },
|
|
258
|
+
keywords: { type: 'string', description: 'Comma-separated CSV keywords' },
|
|
259
|
+
limit: { type: 'number', description: 'Max CSV rows (default: 3)' },
|
|
260
|
+
persona: { type: 'string', description: 'Persona id for knowledge slice (arjun, zara, …)' },
|
|
261
|
+
ref: { type: 'string', description: 'Skill reference filename without path (e.g. lens.md)' },
|
|
259
262
|
},
|
|
260
|
-
required: ['file'],
|
|
261
263
|
},
|
|
262
264
|
},
|
|
263
265
|
{
|
|
@@ -285,6 +287,43 @@ var TOOLS = [
|
|
|
285
287
|
},
|
|
286
288
|
];
|
|
287
289
|
|
|
290
|
+
var ROUTER_TOOL = {
|
|
291
|
+
name: 'analyzthis_design',
|
|
292
|
+
description: 'Design team router. Set who to zara, arjun, noor, anuj, meera, priya, raj, kavi, orchestrator, ux-ideator, design-critic, ux-story-gate, design-director, or mood-board. Returns a short skill front — call analyzthis_retrieve for the rest.',
|
|
293
|
+
inputSchema: {
|
|
294
|
+
type: 'object',
|
|
295
|
+
properties: {
|
|
296
|
+
who: { type: 'string', description: 'Persona or pass name (e.g. zara, arjun, orchestrator)' },
|
|
297
|
+
task: { type: 'string', description: 'What to design or critique' },
|
|
298
|
+
context: { type: 'string', description: 'Optional extra context' },
|
|
299
|
+
},
|
|
300
|
+
required: ['who', 'task'],
|
|
301
|
+
},
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
var RECEIPT_TOOL = {
|
|
305
|
+
name: 'analyzthis_receipt',
|
|
306
|
+
description: 'Show inferred token receipt for this project. Not a bill. Do not invent a dollar figure.',
|
|
307
|
+
inputSchema: {
|
|
308
|
+
type: 'object',
|
|
309
|
+
properties: {
|
|
310
|
+
project: { type: 'string', description: 'Optional project id override' },
|
|
311
|
+
},
|
|
312
|
+
},
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
function resolveCatalog(explicit) {
|
|
316
|
+
var raw = explicit || process.env.ANALYZTHIS_MCP_CATALOG || 'lite';
|
|
317
|
+
return String(raw).toLowerCase() === 'full' ? 'full' : 'lite';
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function listedTools(catalog) {
|
|
321
|
+
if (resolveCatalog(catalog) === 'full') {
|
|
322
|
+
return TOOLS.concat([ROUTER_TOOL, RECEIPT_TOOL]);
|
|
323
|
+
}
|
|
324
|
+
return [ROUTER_TOOL, TOOLS.find(function (t) { return t.name === 'analyzthis_retrieve'; }), TOOLS.find(function (t) { return t.name === 'analyzthis_session'; }), RECEIPT_TOOL].filter(Boolean);
|
|
325
|
+
}
|
|
326
|
+
|
|
288
327
|
// ── Tool handlers ────────────────────────────────────────────────────────
|
|
289
328
|
|
|
290
329
|
function handleToolCall(name, args) {
|
|
@@ -326,6 +365,10 @@ function handleToolCall(name, args) {
|
|
|
326
365
|
return handleSession(args);
|
|
327
366
|
case 'analyzthis_system_prompt':
|
|
328
367
|
return handleSystemPrompt(args);
|
|
368
|
+
case 'analyzthis_design':
|
|
369
|
+
return handleRouter(args);
|
|
370
|
+
case 'analyzthis_receipt':
|
|
371
|
+
return handleReceipt(args);
|
|
329
372
|
|
|
330
373
|
default:
|
|
331
374
|
return { error: 'Unknown tool: ' + name };
|
|
@@ -333,7 +376,7 @@ function handleToolCall(name, args) {
|
|
|
333
376
|
}
|
|
334
377
|
|
|
335
378
|
function handleSinglePersona(personaId, args) {
|
|
336
|
-
var card =
|
|
379
|
+
var card = readSkillFront(personaId);
|
|
337
380
|
if (!card) return { error: 'Persona not found: ' + personaId };
|
|
338
381
|
|
|
339
382
|
var task = args.task || '';
|
|
@@ -351,11 +394,10 @@ function handleSinglePersona(personaId, args) {
|
|
|
351
394
|
'## Task\n' + task + '\n' +
|
|
352
395
|
(context ? '\n## Context\n' + context : '') +
|
|
353
396
|
extra + '\n\n' +
|
|
354
|
-
'
|
|
355
|
-
'Be specific — cite components, zones, and fixes. '
|
|
356
|
-
'Do not give generic advice.';
|
|
397
|
+
'Use the lite output contract. Call analyzthis_retrieve (kind=skill, file=' + personaId + ') only if you need the full lens. ' +
|
|
398
|
+
'Be specific — cite components, zones, and fixes. Do not give generic advice.';
|
|
357
399
|
|
|
358
|
-
return { prompt: prompt, persona: personaId, task: task };
|
|
400
|
+
return { prompt: prompt, persona: personaId, task: task, verdicts: 1 };
|
|
359
401
|
}
|
|
360
402
|
|
|
361
403
|
function handleCombinationPass(skillId, args) {
|
|
@@ -381,11 +423,11 @@ function handleCombinationPass(skillId, args) {
|
|
|
381
423
|
skill + '\n\n' +
|
|
382
424
|
'## Task\n' + task + '\n' +
|
|
383
425
|
(context ? '\n## Context\n' + context : '') + '\n\n' +
|
|
384
|
-
'Run
|
|
385
|
-
'
|
|
386
|
-
'
|
|
426
|
+
'Run the smallest useful team. Challenge the premise first. ' +
|
|
427
|
+
'Call analyzthis_retrieve (kind=skill, file=' + skillId + ') if the front is not enough. ' +
|
|
428
|
+
'Lite default: verdict + top 3 + one evidence line. Expand only if the user says expand.';
|
|
387
429
|
|
|
388
|
-
return { prompt: prompt, skill: skillId, task: task };
|
|
430
|
+
return { prompt: prompt, skill: skillId, task: task, persona: skillId, verdicts: 1 };
|
|
389
431
|
}
|
|
390
432
|
|
|
391
433
|
function handleMoodBoard(args) {
|
|
@@ -439,10 +481,13 @@ function handleCollect(args) {
|
|
|
439
481
|
}
|
|
440
482
|
|
|
441
483
|
function handleRetrieve(args) {
|
|
484
|
+
var kind = args.kind || 'csv';
|
|
485
|
+
if (kind === 'skill') return handleRetrieveSkill(args);
|
|
486
|
+
if (kind === 'knowledge') return handleRetrieveKnowledge(args);
|
|
442
487
|
try {
|
|
443
488
|
var retrieve = require('./retrieve');
|
|
444
489
|
var file = args.file;
|
|
445
|
-
if (!file) return { error: 'file is required' };
|
|
490
|
+
if (!file) return { error: 'file is required for CSV retrieve' };
|
|
446
491
|
var filters = [];
|
|
447
492
|
if (args.column && args.keywords) {
|
|
448
493
|
filters.push({ column: args.column, anyOf: args.keywords.split(',').map(function(s) { return s.trim(); }) });
|
|
@@ -464,6 +509,70 @@ function handleRetrieve(args) {
|
|
|
464
509
|
}
|
|
465
510
|
}
|
|
466
511
|
|
|
512
|
+
function handleRetrieveSkill(args) {
|
|
513
|
+
var id = String(args.file || args.persona || '').replace(/^skill\//, '');
|
|
514
|
+
if (!id) return { error: 'file (skill id) is required' };
|
|
515
|
+
var refName = args.ref || 'lens.md';
|
|
516
|
+
var refPath = path.join(PACKAGE_ROOT, 'skills', id, 'references', refName);
|
|
517
|
+
if (!fs.existsSync(refPath)) {
|
|
518
|
+
var dir = path.join(PACKAGE_ROOT, 'skills', id, 'references');
|
|
519
|
+
if (fs.existsSync(dir)) {
|
|
520
|
+
var names = fs.readdirSync(dir).filter(function (n) { return n.endsWith('.md'); });
|
|
521
|
+
if (names.length) refPath = path.join(dir, names[0]);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
if (!fs.existsSync(refPath)) {
|
|
525
|
+
var full = readSkill(id);
|
|
526
|
+
if (!full) return { error: 'No skill references for ' + id };
|
|
527
|
+
return { result: full, persona: id };
|
|
528
|
+
}
|
|
529
|
+
return { result: fs.readFileSync(refPath, 'utf8'), persona: id };
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
function handleRetrieveKnowledge(args) {
|
|
533
|
+
var persona = args.persona || String(args.file || '').replace(/^knowledge\//, '');
|
|
534
|
+
if (!persona) return { error: 'persona is required for knowledge retrieve' };
|
|
535
|
+
try {
|
|
536
|
+
var knowledge = require('./knowledge');
|
|
537
|
+
var sessionMod = require('./session');
|
|
538
|
+
var projectId = sessionMod.getProjectId();
|
|
539
|
+
var slicePath = path.join(knowledge.KNOWLEDGE_SLICE_ROOT, projectId, persona + '.md');
|
|
540
|
+
if (!fs.existsSync(slicePath)) {
|
|
541
|
+
return { result: 'No knowledge slice for ' + persona + '. Run collect/sync first. Do not load a full bank.' };
|
|
542
|
+
}
|
|
543
|
+
var text = fs.readFileSync(slicePath, 'utf8');
|
|
544
|
+
var cap = 6000;
|
|
545
|
+
if (text.length > cap) text = text.slice(0, cap) + '\n…[truncated — this is one slice, not the full bank]';
|
|
546
|
+
return { result: text, persona: persona };
|
|
547
|
+
} catch (e) {
|
|
548
|
+
return { error: e.message };
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
var ROUTER_WHO = {
|
|
553
|
+
zara: 'persona', arjun: 'persona', meera: 'persona', priya: 'persona',
|
|
554
|
+
noor: 'persona', anuj: 'persona', raj: 'persona', kavi: 'persona',
|
|
555
|
+
orchestrator: 'persona-orchestrator', 'persona-orchestrator': 'persona-orchestrator',
|
|
556
|
+
'ux-ideator': 'ux-ideator', 'design-critic': 'design-critic',
|
|
557
|
+
'ux-story-gate': 'ux-story-gate', 'design-director': 'design-director',
|
|
558
|
+
'mood-board': 'mood-board',
|
|
559
|
+
};
|
|
560
|
+
|
|
561
|
+
function handleRouter(args) {
|
|
562
|
+
var who = String(args.who || '').toLowerCase().replace(/^analyzthis_/, '').replace(/_/g, '-');
|
|
563
|
+
if (!who) return { error: 'who is required (e.g. zara, arjun, orchestrator)' };
|
|
564
|
+
var mapped = ROUTER_WHO[who];
|
|
565
|
+
if (!mapped) return { error: 'Unknown who: ' + who + '. Use a persona or orchestrator / ux-ideator / design-critic / ux-story-gate / design-director / mood-board.' };
|
|
566
|
+
if (mapped === 'persona') return handleSinglePersona(who, args);
|
|
567
|
+
if (mapped === 'mood-board') return handleMoodBoard(args);
|
|
568
|
+
return handleCombinationPass(mapped, args);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
function handleReceipt(args) {
|
|
572
|
+
var receipt = require('./receipt');
|
|
573
|
+
return { result: receipt.report({ project: args.project }) };
|
|
574
|
+
}
|
|
575
|
+
|
|
467
576
|
function handleSession(args) {
|
|
468
577
|
try {
|
|
469
578
|
var session = require('./session');
|
|
@@ -506,18 +615,16 @@ function handleSystemPrompt(args) {
|
|
|
506
615
|
|
|
507
616
|
// ── Helpers ──
|
|
508
617
|
|
|
509
|
-
function readCard(id) {
|
|
510
|
-
var p = path.join(PACKAGE_ROOT, 'agents', 'cards', id + '.md');
|
|
511
|
-
if (!fs.existsSync(p)) return null;
|
|
512
|
-
return fs.readFileSync(p, 'utf8');
|
|
513
|
-
}
|
|
514
|
-
|
|
515
618
|
function readSkill(id) {
|
|
516
619
|
var p = path.join(PACKAGE_ROOT, 'skills', id, 'SKILL.md');
|
|
517
620
|
if (!fs.existsSync(p)) return null;
|
|
518
621
|
return fs.readFileSync(p, 'utf8');
|
|
519
622
|
}
|
|
520
623
|
|
|
624
|
+
function readSkillFront(id) {
|
|
625
|
+
return readSkill(id);
|
|
626
|
+
}
|
|
627
|
+
|
|
521
628
|
// ── MCP config writer ──
|
|
522
629
|
|
|
523
630
|
function mergeMcpServer(configPath) {
|
|
@@ -532,6 +639,7 @@ function mergeMcpServer(configPath) {
|
|
|
532
639
|
config.mcpServers['analyzthis_design'] = {
|
|
533
640
|
command: 'npx',
|
|
534
641
|
args: ['analyzthis_design', 'mcp'],
|
|
642
|
+
env: { ANALYZTHIS_MCP_CATALOG: process.env.ANALYZTHIS_MCP_CATALOG || 'lite' },
|
|
535
643
|
};
|
|
536
644
|
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
537
645
|
return configPath;
|
|
@@ -542,13 +650,17 @@ function looksLikeProjectCwd() {
|
|
|
542
650
|
return fs.existsSync(path.join(cwd, 'package.json')) || fs.existsSync(path.join(cwd, '.git'));
|
|
543
651
|
}
|
|
544
652
|
|
|
545
|
-
function writeMcpConfig(target) {
|
|
653
|
+
function writeMcpConfig(target, opts) {
|
|
654
|
+
opts = opts || {};
|
|
655
|
+
if (opts.catalog) process.env.ANALYZTHIS_MCP_CATALOG = opts.catalog;
|
|
546
656
|
var home = os.homedir();
|
|
547
657
|
|
|
548
658
|
if (target === 'cursor') {
|
|
549
659
|
var cursorConfigPath = path.join(home, '.cursor', 'mcp.json');
|
|
550
660
|
mergeMcpServer(cursorConfigPath);
|
|
551
661
|
console.log('Cursor MCP config written to ' + cursorConfigPath);
|
|
662
|
+
console.log('Default MCP catalog is lite (router + retrieve + session + receipt).');
|
|
663
|
+
console.log('Full 19-tool list: ANALYZTHIS_MCP_CATALOG=full or mcp --catalog full');
|
|
552
664
|
console.log('Restart Cursor to activate.\n');
|
|
553
665
|
return true;
|
|
554
666
|
}
|
|
@@ -575,6 +687,7 @@ function writeMcpConfig(target) {
|
|
|
575
687
|
console.log('Project MCP config written to ' + projectMcp);
|
|
576
688
|
}
|
|
577
689
|
|
|
690
|
+
console.log('Default MCP catalog is lite. Full list: ANALYZTHIS_MCP_CATALOG=full');
|
|
578
691
|
console.log('Restart Claude Code and Claude Desktop to activate.\n');
|
|
579
692
|
return true;
|
|
580
693
|
}
|
|
@@ -602,7 +715,9 @@ function writeMcpConfig(target) {
|
|
|
602
715
|
|
|
603
716
|
// ── MCP protocol (JSON-RPC 2.0 over stdio) ────────────────────────────────
|
|
604
717
|
|
|
605
|
-
function startStdioServer() {
|
|
718
|
+
function startStdioServer(catalog) {
|
|
719
|
+
var catalogMode = resolveCatalog(catalog);
|
|
720
|
+
var activeTools = listedTools(catalogMode);
|
|
606
721
|
var rl = readline.createInterface({ input: process.stdin, terminal: false });
|
|
607
722
|
var initialized = false;
|
|
608
723
|
|
|
@@ -647,7 +762,7 @@ function startStdioServer() {
|
|
|
647
762
|
jsonrpc: '2.0',
|
|
648
763
|
id: id,
|
|
649
764
|
result: {
|
|
650
|
-
tools:
|
|
765
|
+
tools: activeTools.map(function(t) {
|
|
651
766
|
return {
|
|
652
767
|
name: t.name,
|
|
653
768
|
description: t.description,
|
|
@@ -673,11 +788,17 @@ function startStdioServer() {
|
|
|
673
788
|
});
|
|
674
789
|
} else {
|
|
675
790
|
var text = result.prompt || result.result || result.command || JSON.stringify(result, null, 2);
|
|
791
|
+
var receipt = require('./receipt');
|
|
792
|
+
var wrapped = receipt.wrapPayload(text, {
|
|
793
|
+
path: 'mcp',
|
|
794
|
+
persona: result.persona || result.skill || toolName,
|
|
795
|
+
verdicts: result.verdicts || 0,
|
|
796
|
+
});
|
|
676
797
|
send({
|
|
677
798
|
jsonrpc: '2.0',
|
|
678
799
|
id: id,
|
|
679
800
|
result: {
|
|
680
|
-
content: [{ type: 'text', text:
|
|
801
|
+
content: [{ type: 'text', text: wrapped }],
|
|
681
802
|
},
|
|
682
803
|
});
|
|
683
804
|
}
|
|
@@ -711,24 +832,32 @@ function startStdioServer() {
|
|
|
711
832
|
|
|
712
833
|
if (process.env.MCP_DEBUG) {
|
|
713
834
|
process.stderr.write('analyzthis_design MCP server v' + VERSION + ' running on stdio\n');
|
|
714
|
-
process.stderr.write('Tools: ' +
|
|
835
|
+
process.stderr.write('Tools: ' + activeTools.length + ' (' + catalogMode + ' catalog)\n');
|
|
715
836
|
}
|
|
716
837
|
}
|
|
717
838
|
|
|
718
839
|
// ── Entry point ──
|
|
719
840
|
|
|
841
|
+
function parseCatalogFlag(args) {
|
|
842
|
+
var eq = args.filter(function (a) { return a.indexOf('--catalog=') === 0; })[0];
|
|
843
|
+
if (eq) return eq.split('=').slice(1).join('=');
|
|
844
|
+
var idx = args.indexOf('--catalog');
|
|
845
|
+
if (idx !== -1 && args[idx + 1] && args[idx + 1].indexOf('--') !== 0) return args[idx + 1];
|
|
846
|
+
return null;
|
|
847
|
+
}
|
|
848
|
+
|
|
720
849
|
function main() {
|
|
721
850
|
var args = process.argv.slice(2);
|
|
851
|
+
var catalog = parseCatalogFlag(args);
|
|
722
852
|
|
|
723
853
|
// --configure <target>
|
|
724
854
|
var configureIdx = args.indexOf('--configure');
|
|
725
855
|
if (configureIdx !== -1 && args[configureIdx + 1]) {
|
|
726
|
-
writeMcpConfig(args[configureIdx + 1]);
|
|
856
|
+
writeMcpConfig(args[configureIdx + 1], { catalog: catalog });
|
|
727
857
|
return;
|
|
728
858
|
}
|
|
729
859
|
|
|
730
|
-
|
|
731
|
-
startStdioServer();
|
|
860
|
+
startStdioServer(catalog);
|
|
732
861
|
}
|
|
733
862
|
|
|
734
863
|
if (require.main === module) {
|
|
@@ -737,6 +866,10 @@ if (require.main === module) {
|
|
|
737
866
|
|
|
738
867
|
module.exports = {
|
|
739
868
|
TOOLS: TOOLS,
|
|
869
|
+
ROUTER_TOOL: ROUTER_TOOL,
|
|
870
|
+
RECEIPT_TOOL: RECEIPT_TOOL,
|
|
871
|
+
listedTools: listedTools,
|
|
872
|
+
resolveCatalog: resolveCatalog,
|
|
740
873
|
handleToolCall: handleToolCall,
|
|
741
874
|
startStdioServer: startStdioServer,
|
|
742
875
|
writeMcpConfig: writeMcpConfig,
|