analyzthis_design 2.0.1 → 2.1.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 +10 -5
- package/agents/cards/evolve-check.md +38 -0
- package/agents/manifests/evolve-check.json +16 -0
- package/dist/README.md +10 -5
- package/dist/agents/cards/evolve-check.md +38 -0
- package/dist/agents/manifests/evolve-check.json +16 -0
- package/dist/bin/cli.js +1225 -1
- package/dist/lib/cache.js +111 -1
- package/dist/lib/chunk-executor.js +219 -1
- package/dist/lib/chunk-models.js +228 -1
- package/dist/lib/chunk-planner.js +328 -1
- package/dist/lib/chunk-router.js +66 -1
- package/dist/lib/chunk-run.js +199 -1
- package/dist/lib/chunk-synthesis.js +176 -1
- package/dist/lib/chunk-telemetry.js +88 -1
- package/dist/lib/collect.js +858 -1
- package/dist/lib/cost.js +119 -1
- package/dist/lib/dedup.js +167 -1
- package/dist/lib/deliberation.js +721 -1
- package/dist/lib/design-spec.js +236 -1
- package/dist/lib/evolution-metrics.js +197 -0
- package/dist/lib/evolve.js +361 -1
- package/dist/lib/export.js +77 -1
- package/dist/lib/feedback-submit.js +324 -1
- package/dist/lib/feedback.js +182 -1
- package/dist/lib/host-llm.js +251 -1
- package/dist/lib/install.js +301 -1
- package/dist/lib/knowledge.js +384 -1
- package/dist/lib/lessons.js +217 -1
- package/dist/lib/moodboard.js +563 -1
- package/dist/lib/orchestrator/run.js +935 -1
- package/dist/lib/outcome.js +193 -1
- package/dist/lib/platforms.js +166 -1
- package/dist/lib/provider.js +57 -1
- package/dist/lib/query-expander.js +83 -1
- package/dist/lib/ranker.js +105 -1
- package/dist/lib/reference-pack.js +221 -1
- package/dist/lib/research.js +143 -1
- package/dist/lib/retrieve.js +131 -1
- package/dist/lib/session.js +185 -1
- package/dist/lib/source-discovery.js +486 -1
- package/dist/lib/synthesis.js +155 -1
- package/dist/lib/token-gate.js +46 -1
- package/dist/skills/evolve-check/SKILL.md +106 -0
- package/package.json +3 -6
- package/skills/evolve-check/SKILL.md +106 -0
package/dist/bin/cli.js
CHANGED
|
@@ -1,2 +1,1226 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
'use strict';const path=require('path'),os=require('os'),fs=require('fs'),{install,remove,SKILLS,TARGET_DIRS,printWelcomeBanner}=require('../lib/install'),{resolveTargets,ALL_TARGET_IDS}=require('../lib/platforms'),{connect,disconnect,sync,status}=require('../lib/knowledge'),session=require('../lib/session'),research=require('../lib/research'),retrieve=require('../lib/retrieve'),{exportTraining}=require('../lib/export'),feedback=require('../lib/feedback'),feedbackSubmit=require('../lib/feedback-submit'),cost=require('../lib/cost'),{collect}=require('../lib/collect'),designSpec=require('../lib/design-spec'),{run:orchestratorRun}=require('../lib/orchestrator/run'),hostLlm=require('../lib/host-llm'),moodboard=require('../lib/moodboard'),HELP='\x0aAnalyzthis_Design\x20—\x208\x20AI\x20design\x20personas\x20with\x20a\x20personal\x20knowledge\x20bank\x0a\x0aUsage:\x0a\x20\x20npx\x20analyzthis_design\x20[command]\x20[options]\x0a\x0a──\x20Skill\x20commands\x20───────────────────────────────────────────\x0a\x20\x20install\x20\x20\x20\x20Copy\x20all\x20skills\x20to\x20the\x20target\x20AI\x20tool\x27s\x20directory\x20\x20(default)\x0a\x20\x20remove\x20\x20\x20\x20\x20Delete\x20installed\x20skills\x20from\x20the\x20target\x20AI\x20tool\x27s\x20directory\x0a\x20\x20list\x20\x20\x20\x20\x20\x20\x20Show\x20installed\x20skills\x20for\x20a\x20target\x0a\x20\x20welcome\x20\x20\x20\x20Print\x20getting-started\x20banner\x20for\x20your\x20AI\x20tool\x20(--target)\x0a\x0a──\x20Knowledge\x20bank\x20commands\x20──────────────────────────────────\x0a\x20\x20connect\x20\x20\x20\x20Register\x20a\x20vault\x20or\x20knowledge\x20folder\x20as\x20a\x20source\x0a\x20\x20sync\x20\x20\x20\x20\x20\x20\x20Read\x20all\x20sources\x20and\x20build\x20the\x20knowledge-bank\x20skill\x0a\x20\x20disconnect\x20Remove\x20a\x20source\x20from\x20the\x20registry\x0a\x20\x20status\x20\x20\x20\x20\x20Show\x20connected\x20sources\x20and\x20last\x20sync\x20time\x0a\x20\x20collect\x20\x20\x20\x20Kavi:\x20scan\x20codebase\x20→\x20Obsidian\x20vault\x20→\x20enrich\x20→\x20sync\x20knowledge\x20bank\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20(--vault\x20path,\x20--dry-run,\x20--no-enrich,\x20--no-web,\x20--no-discover,\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20--web-limit\x20N,\x20--target\x20cursor|claude|codex|grok|windsurf|agents|all)\x0a\x0a──\x20Design\x20spec\x20commands\x20─────────────────────────────────────\x0a\x20\x20spec\x20show\x20\x20\x20\x20\x20\x20Print\x20design_spec\x20from\x20session\x20state\x0a\x20\x20spec\x20validate\x20\x20Validate\x20a\x20DesignSpec\x20JSON\x20file\x20(--file)\x20or\x20session\x0a\x20\x20spec\x20save\x20\x20\x20\x20\x20\x20Save\x20DesignSpec\x20JSON\x20to\x20session\x20(--file\x20required)\x0a\x20\x20spec\x20template\x20\x20Print\x20empty\x20DesignSpec\x20template\x20block\x0a\x0a──\x20Session\x20commands\x20(agentic\x20orchestrator)\x20──────────────────\x0a\x20\x20session\x20init\x20\x20\x20\x20Create\x20a\x20fresh\x20session-state.json\x20for\x20this\x20project\x0a\x20\x20session\x20show\x20\x20\x20\x20Print\x20the\x20current\x20session-state.json\x0a\x20\x20session\x20reset\x20\x20\x20Delete\x20the\x20session\x20state\x20for\x20this\x20project\x20(--all\x20for\x20every\x20project)\x0a\x20\x20session\x20accept\x20\x20Mark\x20a\x20persona\x27s\x20last\x20output\x20accepted,\x20for\x20training\x20export\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20(--persona\x20<id>,\x20optional\x20--reject\x20to\x20unmark)\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20Optional\x20feedback:\x20--comment,\x20--correction,\x20--rating\x201-5,\x20--tags\x20a,b\x0a\x0a──\x20Persona\x20feedback\x20commands\x20─────────────────────────────────\x0a\x20\x20feedback\x20record\x20\x20\x20Record\x20unhappiness\x20or\x20a\x20correction\x20for\x20a\x20persona\x20output\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20(--persona\x20<id>,\x20--comment,\x20--correction,\x20--rating\x201-5,\x20--tags)\x0a\x20\x20feedback\x20list\x20\x20\x20\x20\x20List\x20feedback\x20entries\x20for\x20this\x20project\x20(--all\x20for\x20every\x20project)\x0a\x20\x20feedback\x20export\x20\x20\x20Export\x20rejected\x20+\x20correction\x20JSONL\x20pairs\x20for\x20training\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20(--persona\x20<id>,\x20--all,\x20--output\x20<path>,\x20--include-positive)\x0a\x20\x20feedback\x20submit\x20\x20\x20Opt-in:\x20send\x20anonymized\x20corrections\x20to\x20community\x20store\x20(Supabase)\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20(--yes\x20skip\x20prompt,\x20--dry-run\x20preview,\x20--all\x20unsent\x20across\x20projects)\x0a\x20\x20feedback\x20status\x20\x20\x20Show\x20submit\x20consent,\x20endpoint\x20config,\x20unsent\x20count\x0a\x20\x20feedback\x20revoke\x20\x20\x20Revoke\x20opt-in\x20consent\x20for\x20community\x20submit\x0a\x0a──\x20Efficiency\x20/\x20cost\x20commands\x20────────────────────────────────\x0a\x20\x20metrics\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20Print\x20the\x20last\x20run\x27s\x20cost\x20metrics\x20(--all\x20for\x20every\x20project)\x0a\x20\x20cost\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20Print\x20the\x20last\x20run\x27s\x20$\x20cost\x20from\x20config.pricing\x20(--all\x20for\x20every\x20project)\x0a\x20\x20export-training\x20\x20\x20\x20\x20Write\x20accepted-output\x20JSONL\x20pairs\x20for\x20LoRA\x20prep\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20(--persona\x20<id>,\x20--all,\x20--output\x20<path>)\x0a\x20\x20feedback\x20export\x20\x20\x20\x20\x20Write\x20rejected\x20+\x20correction\x20JSONL\x20pairs\x20(DPO\x20/\x20negative\x20examples)\x0a\x0a──\x20Research\x20commands\x20────────────────────────────────────────\x0a\x20\x20research\x20--url\x20<url>\x20\x20\x20\x20\x20\x20\x20Fetch\x20a\x20URL\x20and\x20append\x20to\x20session\x20web-context.md\x0a\x20\x20research\x20--query\x20<text>\x20\x20\x20\x20Search\x20stub\x20(or\x20provider)\x20appended\x20to\x20web-context.md\x0a\x0a──\x20Mood\x20board\x20commands\x20─────────────────────────────────────\x0a\x20\x20moodboard\x20create\x20--task\x20<text>\x20\x20\x20Build\x20a\x20mood\x20board\x20from\x20web\x20+\x20DS\x20references\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20[--url\x20<url>\x20...]\x20[--auto]\x0a\x20\x20moodboard\x20critique\x20--board\x20<id>\x20\x20Run\x20team\x20deliberation\x20over\x20a\x20board\x0a\x20\x20moodboard\x20add\x20--board\x20<id>\x20\x20\x20\x20\x20\x20\x20Add\x20a\x20user\x20reference\x20and\x20rerun\x20critique\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20[--url\x20<url>]\x20[--title\x20<t>]\x20[--desc\x20<d>]\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20[--tags\x20a,b]\x20[--note\x20<text>]\x0a\x20\x20moodboard\x20list\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20List\x20mood\x20boards\x20for\x20this\x20project\x0a\x0a──\x20Reference\x20data\x20(retrieve-on-demand)\x20───────────────────────\x0a\x20\x20retrieve\x20--file\x20<csv>\x20--column\x20<col>\x20--keywords\x20a,b\x20\x20\x20Filtered,\x20citation-ready\x20rows\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20--limit\x20N\x20\x20\x20(default\x203)\x0a\x0a──\x20Orchestrator\x20(standalone\x20runtime)\x20────────────────────────\x0a\x20\x20run\x20--task\x20<text>\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20DEFAULT\x20v2.0:\x20frontier\x20planner\x20→\x20cheap\x20chunk\x20models\x20→\x20synthesis\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20--budget\x20free\x20\x20\x20\x20only\x20zero-cost\x20models\x20(Ollama,\x20free\x20APIs)\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20--budget\x20cheap\x20\x20\x20include\x20cheap\x20cloud\x20models\x20with\x20user\x20keys\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20--sequential\x20\x20\x20\x20\x20run\x20chunks\x20sequentially\x20(default)\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20--max-chunks\x20N\x20\x20\x20cap\x20chunks\x20(default\x206)\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20--dry-run\x20\x20\x20\x20\x20\x20\x20\x20show\x20planner\x20output\x20without\x20executing\x20chunks\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20--unchunked\x20\x20\x20\x20\x20\x20use\x20the\x20legacy\x20single-pass\x20orchestrator\x0a\x0a\x20\x20run-unchunked\x20--task\x20<text>\x20\x20Legacy\x20non-chunked\x20orchestrator\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20--continue\x20\x20\x20\x20\x20resume\x20after\x20/devi\x20fills\x20pending\x20responses\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20--lite\x20(default)\x20MoE\x20subset\x20only\x20|\x20--full\x20allow\x20full\x20chain\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20--experts\x20a,b\x20\x20\x20\x20explicit\x20override,\x20skips\x20the\x20router\x20entirely\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20--deliberate\x20\x20\x20\x20\x20adversarial\x20satisfaction\x20loops\x20(default\x20on)\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20--no-deliberate\x20\x20legacy\x20sequential\x20pass-the-parcel\x20mode\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20--max-rounds\x20N\x20\x20\x20cap\x20deliberation\x20rounds\x20(default\x203)\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20--satisfaction\x20X\x20satisfaction\x20threshold\x200.0-1.0\x20(default\x200.4)\x0a\x0a──\x20Devi\x20(host\x20LLM\x20—\x20no\x20API\x20keys)\x20────────────────────────────\x0a\x20\x20devi\x20status\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20List\x20pending\x20persona\x20prompts\x20awaiting\x20host\x20LLM\x20responses\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20(--run\x20path\x20to\x20a\x20specific\x20run\x20directory)\x0a\x20\x20devi\x20respond\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20Submit\x20a\x20persona\x20response\x20file\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20(--run\x20path,\x20--step\x20001-arjun,\x20--file\x20response.md)\x0a\x0a──\x20Options\x20──────────────────────────────────────────────────\x0a\x20\x20--target\x20\x20\x20Platform:\x20cursor\x20|\x20claude\x20|\x20codex\x20|\x20grok\x20|\x20windsurf\x20|\x20agents\x20|\x20all\x20\x20(default:\x20cursor)\x0a\x20\x20--force\x20\x20\x20\x20Overwrite\x20existing\x20skills\x20on\x20install\x0a\x20\x20--vault\x20\x20\x20\x20Path\x20to\x20Obsidian\x20vault\x20or\x20markdown\x20folder\x20(connect\x20command)\x0a\x20\x20--tags\x20\x20\x20\x20\x20Comma-separated\x20tags\x20to\x20filter\x20by,\x20e.g.\x20design,brand,ux\x0a\x20\x20--include\x20\x20Comma-separated\x20sub-folder\x20names\x20to\x20include,\x20e.g.\x20Design,Brand\x0a\x20\x20--project\x20\x20Project\x20id\x20override\x20for\x20session/research/run\x20commands\x20(default:\x20derived\x20from\x20cwd)\x0a\x20\x20--all\x20\x20\x20\x20\x20\x20With\x20\x22session\x20reset\x22,\x20clear\x20every\x20project\x27s\x20session\x20state\x0a\x20\x20--url\x20\x20\x20\x20\x20\x20URL\x20to\x20fetch\x20(research\x20command)\x0a\x20\x20--query\x20\x20\x20\x20Search\x20query\x20(research\x20command)\x0a\x20\x20--task\x20\x20\x20\x20\x20Task\x20description\x20(run\x20command)\x0a\x20\x20--figma\x20\x20\x20\x20Figma\x20URL\x20(run\x20command)\x0a\x20\x20--provider\x20anthropic\x20|\x20openai\x20|\x20google\x20|\x20zai\x20|\x20ollama\x20|\x20groq\x20|\x20together\x20|\x20openrouter\x20|\x20deepseek\x20|\x20host\x20(default:\x20auto)\x0a\x20\x20--model\x20\x20\x20\x20Model\x20override\x20(run\x20/\x20run-unchunked\x20command)\x0a\x20\x20--continue\x20With\x20\x22run-unchunked\x22,\x20resume\x20host-mode\x20run\x20after\x20devi\x20respond\x0a\x20\x20--dry-run\x20\x20Print\x20routing\x20+\x20chain\x20without\x20calling\x20any\x20LLM\x20(run\x20/\x20run-unchunked\x20command);\x20or\x20show\x20planner\x20output\x0a\x20\x20--lite\x20\x20\x20\x20\x20Force\x20MoE\x20subset\x20only,\x20even\x20for\x20full_screen_review\x20(run-unchunked\x20command;\x20default)\x0a\x20\x20--full\x20\x20\x20\x20\x20Allow\x20the\x20full\x20design-critic\x20chain\x20for\x20full_screen_review\x20(run-unchunked\x20command)\x0a\x20\x20--experts\x20\x20Comma-separated\x20persona\x20ids,\x20bypasses\x20the\x20router\x20entirely\x20(run-unchunked\x20command)\x0a\x20\x20--budget\x20\x20\x20free\x20|\x20cheap\x20|\x20auto\x20—\x20chunk\x20model\x20budget\x20(run\x20command;\x20default:\x20auto)\x0a\x20\x20--sequential\x20\x20Run\x20chunks\x20sequentially\x20(run\x20command;\x20default\x20on)\x0a\x20\x20--max-chunks\x20\x20Cap\x20number\x20of\x20planner\x20chunks\x20(run\x20command;\x20default\x206)\x0a\x20\x20--unchunked\x20\x20\x20Force\x20legacy\x20single-pass\x20orchestrator\x20(run\x20command)\x0a\x20\x20--output\x20\x20\x20Write\x20final\x20session-state.json\x20to\x20this\x20path\x20(run\x20/\x20run-unchunked\x20command);\x20or\x20JSONL\x20path\x20(export-training)\x0a\x20\x20--persona\x20\x20Persona\x20id\x20(session\x20accept;\x20export-training;\x20feedback\x20commands)\x0a\x20\x20--reject\x20\x20\x20With\x20\x22session\x20accept\x22,\x20mark\x20the\x20output\x20rejected\x20instead\x20of\x20accepted\x0a\x20\x20--comment\x20\x20What\x20was\x20wrong\x20or\x20what\x20you\x20liked\x20(session\x20accept\x20/\x20feedback\x20record)\x0a\x20\x20--correction\x20\x20How\x20you\x20fixed\x20it\x20or\x20what\x20you\x20wanted\x20instead\x20(session\x20accept\x20/\x20feedback\x20record)\x0a\x20\x20--rating\x20\x20\x201\x20(very\x20unhappy)\x20to\x205\x20(very\x20happy)\x20—\x20feedback\x20record\x20/\x20session\x20accept\x0a\x20\x20--include-positive\x20\x20With\x20\x22feedback\x20export\x22,\x20include\x20satisfied\x20entries\x20too\x0a\x20\x20--yes\x20\x20\x20\x20\x20\x20With\x20\x22feedback\x20submit\x22,\x20accept\x20consent\x20prompt\x20without\x20asking\x20again\x0a\x20\x20--deliberate\x20\x20With\x20\x22run\x22,\x20force\x20adversarial\x20deliberation\x20loops\x0a\x20\x20--no-deliberate\x20\x20With\x20\x22run\x22,\x20legacy\x20sequential\x20handoff\x20(no\x20objection\x20rounds)\x0a\x20\x20--max-rounds\x20\x20With\x20\x22run\x22,\x20cap\x20deliberation\x20rounds\x20(default\x203)\x0a\x20\x20--satisfaction\x20\x20With\x20\x22run\x22,\x20satisfaction\x20threshold\x200.0-1.0\x20(default\x200.4)\x0a\x20\x20--no-enrich\x20\x20With\x20\x22collect\x22,\x20write\x20draft\x20vault\x20+\x20sync\x20without\x20LLM\x20enrichment\x0a\x20\x20--no-web\x20\x20\x20\x20\x20With\x20\x22collect\x22,\x20skip\x20fetching\x20URLs\x20from\x20config/PRDs/README\x0a\x20\x20--no-discover\x20With\x20\x22collect\x22,\x20skip\x20Obsidian/vault/knowledge-graph\x20discovery\x0a\x20\x20--web-limit\x20\x20Cap\x20external\x20URLs\x20fetched\x20during\x20collect\x20(default:\x2010)\x0a\x20\x20--limit\x20\x20\x20\x20Cap\x20notes\x20enriched\x20(collect)\x20or\x20retrieve\x20rows\x20(retrieve)\x0a\x20\x20--board\x20\x20\x20\x20Mood\x20board\x20id\x20(moodboard\x20critique\x20/\x20add)\x0a\x20\x20--title\x20\x20\x20\x20Reference\x20title\x20(moodboard\x20add)\x0a\x20\x20--desc\x20\x20\x20\x20\x20Reference\x20description\x20(moodboard\x20add)\x0a\x20\x20--auto\x20\x20\x20\x20\x20With\x20moodboard\x20create,\x20discover\x20references\x20without\x20explicit\x20URLs\x0a\x20\x20--help\x20\x20\x20\x20\x20Show\x20this\x20help\x20message\x0a\x0a──\x20Examples\x20─────────────────────────────────────────────────\x0a\x20\x20npx\x20analyzthis_design\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20#\x20install\x20for\x20Cursor\x0a\x20\x20npx\x20analyzthis_design\x20--target\x20all\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20#\x20install\x20for\x20all\x20tools\x0a\x20\x20npx\x20analyzthis_design\x20welcome\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20#\x20re-print\x20getting-started\x20help\x0a\x20\x20npx\x20analyzthis_design\x20welcome\x20--target\x20claude\x0a\x0a\x20\x20npx\x20analyzthis_design\x20collect\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20#\x20Kavi:\x20scan\x20→\x20vault\x20→\x20enrich\x20→\x20sync\x0a\x20\x20npx\x20analyzthis_design\x20collect\x20--dry-run\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20#\x20preview\x20classification\x20+\x20web\x20URLs\x0a\x20\x20npx\x20analyzthis_design\x20collect\x20--no-enrich\x20--limit\x2050\x0a\x20\x20npx\x20analyzthis_design\x20collect\x20--no-web\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20#\x20skip\x20external\x20URL\x20fetch\x0a\x20\x20npx\x20analyzthis_design\x20collect\x20--vault\x20~/Documents/MyVault\x20--target\x20all\x0a\x0a\x20\x20npx\x20analyzthis_design\x20connect\x20--vault\x20~/Documents/MyVault\x0a\x20\x20npx\x20analyzthis_design\x20connect\x20--vault\x20~/docs\x20--tags\x20design,brand,product\x0a\x20\x20npx\x20analyzthis_design\x20connect\x20--vault\x20~/vault\x20--include\x20Design,Research\x0a\x20\x20npx\x20analyzthis_design\x20sync\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20#\x20sync\x20to\x20Cursor\x0a\x20\x20npx\x20analyzthis_design\x20sync\x20--target\x20all\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20#\x20sync\x20to\x20all\x20tools\x0a\x20\x20npx\x20analyzthis_design\x20status\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20#\x20show\x20sources\x0a\x20\x20npx\x20analyzthis_design\x20disconnect\x20--vault\x20~/Documents/MyVault\x0a\x0a\x20\x20npx\x20analyzthis_design\x20session\x20init\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20#\x20start\x20a\x20new\x20session\x20for\x20this\x20repo\x0a\x20\x20npx\x20analyzthis_design\x20session\x20show\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20#\x20inspect\x20current\x20session\x20state\x0a\x20\x20npx\x20analyzthis_design\x20session\x20reset\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20#\x20clear\x20session\x20state\x20for\x20this\x20repo\x0a\x0a\x20\x20npx\x20analyzthis_design\x20research\x20--url\x20https://example.com/design-tokens\x0a\x20\x20npx\x20analyzthis_design\x20research\x20--query\x20\x22EY\x20design\x20system\x20tokens\x22\x0a\x0a\x20\x20npx\x20analyzthis_design\x20moodboard\x20create\x20--task\x20\x22B2B\x20fintech\x20dashboard,\x20trustworthy,\x20high-contrast\x22\x20--auto\x0a\x20\x20npx\x20analyzthis_design\x20moodboard\x20critique\x20--board\x20<boardId>\x0a\x20\x20npx\x20analyzthis_design\x20moodboard\x20add\x20--board\x20<boardId>\x20--url\x20https://dribbble.com/shots/example\x20--title\x20\x22Alt\x20hero\x22\x20--tags\x20\x22landing,trust\x22\x0a\x0a\x20\x20npx\x20analyzthis_design\x20retrieve\x20--file\x20colors.csv\x20--column\x20\x22Product\x20Type\x22\x20--keywords\x20saas,dashboard\x0a\x20\x20npx\x20analyzthis_design\x20retrieve\x20--file\x20styles.csv\x20--column\x20\x22Best\x20For\x22\x20--keywords\x20b2b\x20--limit\x203\x0a\x0a\x20\x20npx\x20analyzthis_design\x20run\x20--task\x20\x22Fix\x20contrast\x20on\x20landing\x20page\x22\x20--dry-run\x0a\x20\x20npx\x20analyzthis_design\x20run\x20--task\x20\x22Review\x20this\x20screen\x22\x20--budget\x20free\x0a\x20\x20npx\x20analyzthis_design\x20run\x20--task\x20\x22Review\x20this\x20screen\x22\x20--budget\x20cheap\x20--sequential\x0a\x20\x20npx\x20analyzthis_design\x20run-unchunked\x20--task\x20\x22Just\x20check\x20spacing\x22\x20--experts\x20arjun\x0a\x20\x20npx\x20analyzthis_design\x20devi\x20status\x0a\x20\x20npx\x20analyzthis_design\x20devi\x20respond\x20--run\x20~/.analyzthis_design/runs/...\x20--step\x20001-arjun\x20--file\x20out.md\x0a\x20\x20npx\x20analyzthis_design\x20run-unchunked\x20--task\x20\x22Review\x20this\x20screen\x22\x20--provider\x20anthropic\x0a\x0a\x20\x20npx\x20analyzthis_design\x20session\x20accept\x20--persona\x20arjun\x0a\x20\x20npx\x20analyzthis_design\x20session\x20accept\x20--persona\x20arjun\x20--reject\x20\x5c\x0a\x20\x20\x20\x20--comment\x20\x22Invented\x20tokens\x20not\x20in\x20our\x20DS\x22\x20\x5c\x0a\x20\x20\x20\x20--correction\x20\x22Use\x20--color-primary\x20and\x20spacing-4\x20from\x20tokens.css\x22\x20\x5c\x0a\x20\x20\x20\x20--rating\x202\x20--tags\x20invented_tokens,missed_ds\x0a\x20\x20npx\x20analyzthis_design\x20feedback\x20record\x20--persona\x20arjun\x20--rating\x202\x20--comment\x20\x22...\x22\x20--correction\x20\x22...\x22\x0a\x20\x20npx\x20analyzthis_design\x20feedback\x20list\x0a\x20\x20npx\x20analyzthis_design\x20feedback\x20export\x20--persona\x20arjun\x20--all\x0a\x20\x20npx\x20analyzthis_design\x20feedback\x20submit\x20--dry-run\x0a\x20\x20npx\x20analyzthis_design\x20feedback\x20submit\x20--all\x20--yes\x0a\x20\x20npx\x20analyzthis_design\x20feedback\x20status\x0a\x20\x20npx\x20analyzthis_design\x20metrics\x0a\x20\x20npx\x20analyzthis_design\x20cost\x0a\x20\x20npx\x20analyzthis_design\x20export-training\x20--persona\x20arjun\x20--all\x0a\x0a──\x20Install\x20paths\x20────────────────────────────────────────────\x0a\x20\x20Cursor\x20\x20\x20\x20\x20→\x20~/.cursor/skills/\x0a\x20\x20Claude\x20\x20\x20\x20\x20→\x20~/.claude/skills/\x20(+\x20legacy\x20~/.claude/commands/)\x0a\x20\x20Codex\x20\x20\x20\x20\x20\x20→\x20~/.codex/skills/\x0a\x20\x20Grok\x20\x20\x20\x20\x20\x20\x20→\x20~/.grok/skills/\x0a\x20\x20Windsurf\x20\x20\x20→\x20~/.codeium/windsurf/skills/\x0a\x20\x20agents\x20\x20\x20\x20\x20→\x20~/.agents/skills/\x20\x20(cross-tool\x20discovery)\x0a\x0a──\x20Knowledge\x20bank\x20config\x20────────────────────────────────────\x0a\x20\x20Config\x20\x20→\x20~/.analyzthis_design/config.json\x0a\x0aDocs:\x20https://github.com/rishikeshjoshi/analyzthis_design\x0a',[,,cmd,...flags]=process['argv'];function getFlag(a){const c=flags['find'](g=>g['startsWith']('--'+a+'='));if(c)return c['split']('=')['slice'](0x1)['join']('=');const f=flags['indexOf']('--'+a);if(f!==-0x1&&flags[f+0x1]&&!flags[f+0x1]['startsWith']('--'))return flags[f+0x1];return null;}function parseFeedbackTags(a){if(!a)return[];return a['split'](',')['map'](c=>c['trim']()['toLowerCase']())['filter'](Boolean);}const force=flags['includes']('--force'),targetVal=getFlag('target')||'cursor',vaultVal=getFlag('vault'),tagsVal=getFlag('tags'),includeVal=getFlag('include'),projectVal=getFlag('project'),allFlag=flags['includes']('--all'),urlVal=getFlag('url'),queryVal=getFlag('query'),taskVal=getFlag('task'),figmaVal=getFlag('figma'),providerVal=getFlag('provider'),modelVal=getFlag('model'),outputVal=getFlag('output'),dryRunFlag=flags['includes']('--dry-run'),liteFlag=flags['includes']('--lite'),fullFlag=flags['includes']('--full'),expertsVal=getFlag('experts'),fileVal=getFlag('file'),columnVal=getFlag('column'),keywordsVal=getFlag('keywords'),limitVal=getFlag('limit'),personaVal=getFlag('persona'),rejectFlag=flags['includes']('--reject'),commentVal=getFlag('comment'),correctionVal=getFlag('correction'),ratingVal=getFlag('rating'),includePositiveFlag=flags['includes']('--include-positive'),yesFlag=flags['includes']('--yes'),deliberateFlag=flags['includes']('--deliberate'),noDeliberateFlag=flags['includes']('--no-deliberate'),maxRoundsVal=getFlag('max-rounds'),satisfactionVal=getFlag('satisfaction'),continueFlag=flags['includes']('--continue'),runDirVal=getFlag('run'),stepVal=getFlag('step'),noEnrichFlag=flags['includes']('--no-enrich'),noWebFlag=flags['includes']('--no-web'),noDiscoverFlag=flags['includes']('--no-discover'),webLimitVal=getFlag('web-limit'),boardVal=getFlag('board'),titleVal=getFlag('title'),descVal=getFlag('desc'),autoFlag=flags['includes']('--auto'),budgetVal=getFlag('budget'),sequentialFlag=flags['includes']('--sequential'),maxChunksVal=getFlag('max-chunks'),unchunkedFlag=flags['includes']('--unchunked');switch(cmd){case undefined:case'install':install({'force':force,'target':targetVal});break;case'remove':case'uninstall':remove({'target':targetVal});break;case'welcome':{const targets=resolveTargets(targetVal)||['cursor'];for(const tId of targets)printWelcomeBanner(tId);break;}case'list':{const {TARGETS}=require('../lib/platforms'),targets=resolveTargets(targetVal);!targets&&(console['error']('\x0a\x20\x20✗\x20\x20Unknown\x20target\x20\x22'+targetVal+'\x22.\x20Choose:\x20'+ALL_TARGET_IDS['join'](',\x20')+',\x20all\x0a'),process['exit'](0x1));for(const tId of targets){const t=TARGETS[tId];console['log']('\x0aInstalled\x20Analyzthis_Design\x20skills\x20['+t['label']+']\x20('+t['root']+'):\x0a');for(const skill of SKILLS){const asDir=path['join'](t['root'],skill),asFile=path['join'](t['root'],skill+'.md');let exists=fs['existsSync'](asDir)||fs['existsSync'](asFile);!exists&&t['also']&&(exists=fs['existsSync'](path['join'](t['also']['root'],skill))||fs['existsSync'](path['join'](t['also']['root'],skill+'.md'))),console['log']('\x20\x20'+(exists?'✅':'✗\x20')+'\x20'+skill);}}console['log']('');break;}case'connect':{!vaultVal&&(console['error']('\x0a\x20\x20✗\x20\x20--vault\x20is\x20required.\x20\x20Example:\x20npx\x20analyzthis_design\x20connect\x20--vault\x20~/Documents/MyVault\x0a'),process['exit'](0x1));try{const tags=tagsVal?tagsVal['split'](',')['map'](a=>a['trim']()):[],include=includeVal?includeVal['split'](',')['map'](a=>a['trim']()):[],abs=connect({'vaultPath':vaultVal,'tags':tags,'include':include});console['log']('\x0a✅\x20Connected:\x20'+abs);if(tags['length'])console['log']('\x20\x20\x20Tags\x20filter:\x20\x20\x20\x20'+tags['join'](',\x20'));if(include['length'])console['log']('\x20\x20\x20Folder\x20filter:\x20\x20'+include['join'](',\x20'));console['log']('\x0a\x20\x20\x20Run\x20\x22npx\x20analyzthis_design\x20sync\x22\x20to\x20build\x20the\x20knowledge\x20bank.\x0a');}catch(h){console['error']('\x0a\x20\x20✗\x20\x20'+h['message']+'\x0a'),process['exit'](0x1);}break;}case'disconnect':{!vaultVal&&(console['error']('\x0a\x20\x20✗\x20\x20--vault\x20is\x20required.\x20\x20Example:\x20npx\x20analyzthis_design\x20disconnect\x20--vault\x20~/Documents/MyVault\x0a'),process['exit'](0x1));disconnect(vaultVal),console['log']('\x0a🗑\x20\x20Disconnected:\x20'+path['resolve'](vaultVal)+'\x0a');break;}case'sync':{const {resolveTargets,ALL_TARGET_IDS}=require('../lib/platforms'),targets=resolveTargets(targetVal);!targets&&(console['error']('\x0a\x20\x20✗\x20\x20Unknown\x20target\x20\x22'+targetVal+'\x22.\x20Choose:\x20'+ALL_TARGET_IDS['join'](',\x20')+',\x20all\x0a'),process['exit'](0x1));console['log']('\x0a⏳\x20Syncing\x20knowledge\x20bank...\x0a');try{const result=sync({'targets':targets});if(result['message'])console['log']('\x20\x20⚠\x20\x20'+result['message']+'\x0a');else{console['log']('✅\x20Synced\x20'+result['synced']+'\x20note(s)\x20into\x20the\x20knowledge\x20bank.');for(const t of result['copiedTo'])console['log']('\x20\x20\x20•\x20'+t);console['log']('\x0a💡\x20The\x20knowledge\x20bank\x20is\x20now\x20active.\x20All\x20personas\x20will\x20read\x20it\x20first.\x0a');}}catch(i){console['error']('\x0a\x20\x20✗\x20\x20Sync\x20failed:\x20'+i['message']+'\x0a'),process['exit'](0x1);}break;}case'status':{const cfg=status();if(!cfg['sources']||cfg['sources']['length']===0x0)console['log']('\x0a\x20\x20No\x20knowledge\x20sources\x20connected.\x0a\x20\x20Run:\x20npx\x20analyzthis_design\x20connect\x20--vault\x20/path/to/vault\x0a');else{console['log']('\x0a📚\x20Knowledge\x20bank\x20sources\x20('+cfg['sources']['length']+'):\x0a');for(const s of cfg['sources']){console['log']('\x20\x20•\x20'+s['path']);if(s['tags']['length'])console['log']('\x20\x20\x20\x20Tags:\x20\x20\x20\x20'+s['tags']['join'](',\x20'));if(s['include']['length'])console['log']('\x20\x20\x20\x20Folders:\x20'+s['include']['join'](',\x20'));console['log']('\x20\x20\x20\x20Added:\x20\x20\x20'+s['addedAt']);}if(cfg['lastSync'])console['log']('\x0a\x20\x20Last\x20sync:\x20'+cfg['lastSync']);console['log']('');}break;}case'session':{const sub=flags['find'](a=>!a['startsWith']('--'));switch(sub){case'init':{const {projectId,filePath}=session['init']({'project':projectVal});console['log']('\x0a✅\x20Session\x20initialized\x20for\x20project\x20\x22'+projectId+'\x22'),console['log']('\x20\x20\x20'+filePath+'\x0a');break;}case'show':{const state=session['show']({'project':projectVal});!state?console['log']('\x0a\x20\x20No\x20session\x20found.\x20Run:\x20npx\x20analyzthis_design\x20session\x20init\x0a'):console['log'](JSON['stringify'](state,null,0x2));break;}case'reset':{const result=session['reset']({'project':projectVal,'all':allFlag});console['log']('\x0a🗑\x20\x20Session\x20reset:\x20'+result['removed']+'\x0a');break;}case'accept':{!personaVal&&(console['error']('\x0a\x20\x20✗\x20\x20--persona\x20is\x20required.\x20\x20Example:\x20npx\x20analyzthis_design\x20session\x20accept\x20--persona\x20arjun\x0a'),process['exit'](0x1));if(commentVal||correctionVal||ratingVal)try{const fb=feedback['recordFeedback']({'project':projectVal,'persona':personaVal,'satisfied':!rejectFlag,'rating':ratingVal!=null?Number(ratingVal):undefined,'comment':commentVal||'','correction':correctionVal||'','tags':parseFeedbackTags(tagsVal),'markRejected':!![]});console['log']('\x0a✅\x20Marked\x20\x22'+personaVal+'\x22\x20as\x20'+(rejectFlag?'rejected':'accepted')+'\x20with\x20feedback\x20('+fb['entry']['id']+').\x0a');}catch(j){console['error']('\x0a\x20\x20✗\x20\x20'+j['message']+'\x0a'),process['exit'](0x1);}else{const result=session['markAccepted']({'project':projectVal,'persona':personaVal,'accepted':!rejectFlag});!result['updated']?console['log']('\x0a\x20\x20⚠\x20\x20'+result['reason']+'\x0a'):console['log']('\x0a✅\x20Marked\x20\x22'+personaVal+'\x22\x20output\x20as\x20'+(rejectFlag?'rejected':'accepted')+'.\x0a');}break;}default:console['error']('\x0aUnknown\x20session\x20subcommand:\x20\x22'+(sub||'')+'\x22.\x20Use:\x20init\x20|\x20show\x20|\x20reset\x20|\x20accept\x0a'),process['exit'](0x1);}break;}case'spec':{const sub=flags[0x0]||'show';if(sub==='template'){console['log']('\x0a'+designSpec['templateMarkdown']()+'\x0a');break;}if(sub==='show'){const row=designSpec['showFromSession']({'project':projectVal});if(!row){console['log']('\x0a\x20\x20No\x20design_spec\x20in\x20session.\x20Run\x20/design-director\x20or\x20/ux-ideator\x20Phase\x207\x20first.\x0a');break;}console['log']('\x0a──\x20design_spec\x20──────────────────────────────────────'),console['log'](JSON['stringify'](row['design_spec'],null,0x2)),console['log']('');break;}if(sub==='save'){!fileVal&&(console['error']('\x0a\x20\x20✗\x20\x20spec\x20save\x20requires\x20--file\x20<path.json>\x0a'),process['exit'](0x1));try{const raw=fs['readFileSync'](path['resolve'](fileVal),'utf8'),spec=JSON['parse'](raw),validation=designSpec['validateDesignSpec'](spec);if(!validation['valid']){console['log']('\x0a✗\x20\x20Cannot\x20save\x20invalid\x20spec:\x0a');for(const e of validation['errors'])console['log']('\x20\x20\x20•\x20'+e);console['log'](''),process['exit'](0x1);}const saved=designSpec['saveToSession'](spec,{'project':projectVal,'merge':![]});console['log']('\x0a✅\x20Saved\x20design_spec\x20to\x20session\x20('+saved['projectId']+')\x0a');}catch(l){console['error']('\x0a\x20\x20✗\x20\x20'+l['message']+'\x0a'),process['exit'](0x1);}break;}if(sub==='validate'){try{let result;if(fileVal)result=designSpec['validateFile'](fileVal);else{const row=designSpec['showFromSession']({'project':projectVal});!row&&(console['error']('\x0a\x20\x20✗\x20\x20No\x20design_spec\x20in\x20session\x20and\x20no\x20--file\x20provided.\x0a'),process['exit'](0x1)),result={'spec':row['design_spec'],...designSpec['validateDesignSpec'](row['design_spec'])};}if(result['valid'])console['log']('\x0a✅\x20DesignSpec\x20is\x20valid.\x0a'),result['spec']&&!fileVal&&console['log']('\x20\x20\x20status:\x20'+result['spec']['status']+'\x20|\x20screen:\x20'+result['spec']['screen_name']+'\x0a');else{console['log']('\x0a✗\x20\x20DesignSpec\x20validation\x20failed:\x0a');for(const e of result['errors'])console['log']('\x20\x20\x20•\x20'+e);console['log'](''),process['exit'](0x1);}}catch(n){console['error']('\x0a\x20\x20✗\x20\x20'+n['message']+'\x0a'),process['exit'](0x1);}break;}console['error']('\x0a\x20\x20✗\x20\x20Unknown\x20spec\x20subcommand.\x20Use:\x20spec\x20show\x20|\x20validate\x20|\x20save\x20|\x20template\x0a'),process['exit'](0x1);}case'collect':{collect({'project':projectVal,'vault':vaultVal||undefined,'dryRun':dryRunFlag,'enrich':!noEnrichFlag,'web':!noWebFlag,'discoverSources':!noDiscoverFlag,'webLimit':webLimitVal?parseInt(webLimitVal,0xa):null,'limit':limitVal?parseInt(limitVal,0xa):null,'target':targetVal,'provider':providerVal,'model':modelVal})['catch'](a=>{console['error']('\x0a\x20\x20✗\x20\x20Collect\x20failed:\x20'+a['message']+'\x0a'),process['exit'](0x1);});break;}case'research':{((async()=>{try{if(urlVal){console['log']('\x0a⏳\x20Fetching\x20'+urlVal+'...\x0a');const a=await research['researchUrl']({'url':urlVal,'project':projectVal});console['log']('✅\x20Wrote\x20'+a['chars']+'\x20chars\x20to\x20'+a['filePath']+'\x0a');}else{if(queryVal){console['log']('\x0a⏳\x20Researching\x20\x22'+queryVal+'\x22...\x0a');const c=await research['researchQuery']({'query':queryVal,'project':projectVal});c['mode']==='stub'?(console['log']('⚠\x20\x20No\x20research.provider\x20configured\x20—\x20wrote\x20a\x20stub\x20for\x20the\x20host\x20IDE\x20to\x20fill.'),console['log']('\x20\x20\x20'+c['filePath']),console['log']('\x20\x20\x20Tip:\x20set\x20research.provider\x20in\x20~/.analyzthis_design/config.json,\x20or\x20use\x20WebSearch\x20in\x20Cursor.\x0a')):console['log']('✅\x20Wrote\x20'+c['chars']+'\x20chars\x20to\x20'+c['filePath']+'\x0a');}else console['error']('\x0a\x20\x20✗\x20\x20Provide\x20--url\x20<url>\x20or\x20--query\x20<text>\x0a'),process['exit'](0x1);}}catch(f){console['error']('\x0a\x20\x20✗\x20\x20Research\x20failed:\x20'+f['message']+'\x0a'),process['exit'](0x1);}})());break;}case'moodboard':{const msub=flags['find'](a=>!a['startsWith']('--'))||'create';if(msub==='create'){!taskVal&&(console['error']('\x0a\x20\x20✗\x20\x20--task\x20is\x20required.\x20\x20Example:\x20npx\x20analyzthis_design\x20moodboard\x20create\x20--task\x20\x22B2B\x20fintech\x20dashboard\x22\x20--auto\x0a'),process['exit'](0x1));((async()=>{try{const a=[],c=flags['filter'](g=>g['startsWith']('--url='))['map'](g=>g['split']('=')['slice'](0x1)['join']('='));for(let g=0x0;g<flags['length'];g++){if(flags[g]==='--url'&&flags[g+0x1]&&!flags[g+0x1]['startsWith']('--'))a['push'](flags[g+0x1]);}for(const o of c)if(a['indexOf'](o)===-0x1)a['push'](o);const f=await moodboard['buildMoodBoard']({'project':projectVal,'task':taskVal,'urls':a,'discover':autoFlag||a['length']>0x0,'dryRun':dryRunFlag});console['log']('\x0a✅\x20Mood\x20board\x20created:\x20'+f['board']['board_id']),console['log']('\x20\x20\x20References:\x20'+f['board']['references']['length']),console['log']('\x20\x20\x20Board\x20dir:\x20\x20'+f['boardDir']),console['log']('\x20\x20\x20Workspace:\x20\x20'+f['workspacePath']+'\x0a'),dryRunFlag&&(console['log'](JSON['stringify'](f['board'],null,0x2)['slice'](0x0,0x7d0)),console['log'](''));}catch(q){console['error']('\x0a\x20\x20✗\x20\x20Mood\x20board\x20create\x20failed:\x20'+q['message']+'\x0a'),process['exit'](0x1);}})());break;}if(msub==='critique'){!boardVal&&(console['error']('\x0a\x20\x20✗\x20\x20--board\x20is\x20required.\x20\x20Example:\x20npx\x20analyzthis_design\x20moodboard\x20critique\x20--board\x20<id>\x0a'),process['exit'](0x1));((async()=>{try{const a=await moodboard['critiqueMoodBoard']({'project':projectVal,'boardId':boardVal,'provider':providerVal,'model':modelVal,'dryRun':dryRunFlag,'noDeliberate':noDeliberateFlag,'maxRounds':maxRoundsVal,'satisfaction':satisfactionVal});console['log']('\x0a✅\x20Mood\x20board\x20critique\x20complete:\x20'+a['board']['board_id']),console['log']('\x20\x20\x20Verdict:\x20'+(a['board']['synthesis']?.['verdict']||'n/a')),console['log']('\x20\x20\x20Rounds:\x20\x20'+(a['board']['deliberation']?.['round']||0x0)),console['log']('\x20\x20\x20Board:\x20\x20\x20'+(a['boardDir']||path['join'](session['sessionDir'](projectVal||session['getProjectId']()),'moodboard',boardVal))),console['log']('\x20\x20\x20Workspace:\x20'+a['workspacePath']+'\x0a');}catch(c){c['name']==='HostLlmPendingError'&&(hostLlm['printDeviInstructions'](c),process['exit'](0x2)),console['error']('\x0a\x20\x20✗\x20\x20Mood\x20board\x20critique\x20failed:\x20'+c['message']+'\x0a'),process['exit'](0x1);}})());break;}if(msub==='add'){!boardVal&&(console['error']('\x0a\x20\x20✗\x20\x20--board\x20is\x20required.\x20\x20Example:\x20npx\x20analyzthis_design\x20moodboard\x20add\x20--board\x20<id>\x20--url\x20<url>\x0a'),process['exit'](0x1));((async()=>{try{const a=tagsVal?tagsVal['split'](',')['map'](f=>f['trim']())['filter'](Boolean):[],c=await moodboard['addUserReferenceAndRerun']({'project':projectVal,'boardId':boardVal,'reference':{'url':urlVal||'','title':titleVal||'','description':descVal||'','tags':a,'note':commentVal||''},'provider':providerVal,'model':modelVal,'dryRun':dryRunFlag,'noDeliberate':noDeliberateFlag,'maxRounds':maxRoundsVal,'satisfaction':satisfactionVal});console['log']('\x0a✅\x20Added\x20reference\x20to\x20board\x20'+c['board']['board_id']+':\x20'+c['added']['id']),console['log']('\x20\x20\x20Total\x20references:\x20'+c['board']['references']['length']),console['log']('\x20\x20\x20Verdict:\x20'+(c['board']['synthesis']?.['verdict']||'n/a')+'\x0a');}catch(f){f['name']==='HostLlmPendingError'&&(hostLlm['printDeviInstructions'](f),process['exit'](0x2)),console['error']('\x0a\x20\x20✗\x20\x20Mood\x20board\x20add\x20failed:\x20'+f['message']+'\x0a'),process['exit'](0x1);}})());break;}if(msub==='list'){const boards=moodboard['listBoards'](projectVal);if(!boards['length'])console['log']('\x0a\x20\x20No\x20mood\x20boards\x20found\x20for\x20this\x20project.\x0a');else{console['log']('\x0a──\x20Mood\x20boards\x20('+boards['length']+')\x20──');for(const b of boards)console['log']('\x20\x20•\x20'+b);console['log']('');}break;}console['error']('\x0a\x20\x20Unknown\x20moodboard\x20subcommand.\x20Use:\x20create\x20|\x20critique\x20|\x20add\x20|\x20list\x0a'),process['exit'](0x1);}case'retrieve':{!fileVal&&(console['error']('\x0a\x20\x20✗\x20\x20--file\x20is\x20required.\x20\x20Example:\x20npx\x20analyzthis_design\x20retrieve\x20--file\x20colors.csv\x20--column\x20\x22Product\x20Type\x22\x20--keywords\x20saas\x0a'),process['exit'](0x1));try{const keywords=keywordsVal?keywordsVal['split'](',')['map'](a=>a['trim']())['filter'](Boolean):[],filters=columnVal&&keywords['length']?[{'column':columnVal,'anyOf':keywords}]:[],limit=limitVal?parseInt(limitVal,0xa):0x3,result=retrieve['retrieve']({'file':fileVal,'filters':filters,'limit':limit});if(!result['rows']['length'])console['log']('\x0a\x20\x20No\x20rows\x20matched\x20in\x20'+fileVal+(columnVal?'\x20for\x20column\x20\x22'+columnVal+'\x22':'')+(keywords['length']?'\x20with\x20keywords:\x20'+keywords['join'](',\x20'):'')+'.\x0a');else{console['log']('\x0a📋\x20'+result['rows']['length']+'/'+result['matched']+'\x20matching\x20row(s)\x20in\x20'+fileVal+(result['cacheHit']?'\x20(cache\x20hit)':'')+':\x0a');for(const row of result['rows']){console['log']('\x20\x20Row\x20'+row['__no']+':');for(const [k,v]of Object['entries'](row)){if(k['startsWith']('__')||!v)continue;console['log']('\x20\x20\x20\x20'+k+':\x20'+v);}console['log']('');}if(columnVal)console['log']('\x20\x20Citation\x20format:\x20['+fileVal+',\x20row\x20N:\x20\x22'+columnVal+'\x20value\x22]\x0a');}}catch(r){console['error']('\x0a\x20\x20✗\x20\x20'+r['message']+'\x0a'),process['exit'](0x1);}break;}case'run':{!taskVal&&(console['error']('\x0a\x20\x20✗\x20\x20--task\x20is\x20required.\x20\x20Example:\x20npx\x20analyzthis_design\x20run\x20--task\x20\x22Review\x20onboarding\x20flow\x22\x20--budget\x20free\x0a'),process['exit'](0x1));((async()=>{try{const a=await orchestratorRun({'task':taskVal,'figma':figmaVal||'','project':projectVal,'provider':providerVal,'model':modelVal,'dryRun':dryRunFlag,'budget':budgetVal||'auto','sequential':sequentialFlag||!flags['includes']('--parallel'),'maxChunks':maxChunksVal?parseInt(maxChunksVal,0xa):null,'unchunked':unchunkedFlag,'output':outputVal,'continueRun':continueFlag});if(dryRunFlag){console['log']('\x0a──\x20Chunk\x20plan\x20(dry\x20run)\x20──'),console['log'](JSON['stringify'](a['plan']||a,null,0x2)['slice'](0x0,0xbb8)),console['log']('');return;}if(a['mode']==='host_pending'||a['host_pending']){const c=a['host_pending'];console['log']('\x0a╔══════════════════════════════════════════════════════════════════════╗'),console['log']('║\x20\x20DEVI\x20—\x20Host\x20LLM\x20pending\x20(chunk\x20planner)\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20║'),console['log']('╚══════════════════════════════════════════════════════════════════════╝\x0a'),console['log']('\x20\x20Step:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+c['step_id']),console['log']('\x20\x20Prompt\x20file:\x20\x20\x20\x20\x20\x20'+path['join'](c['run_dir'],'pending',c['step_id']+'.json')),console['log']('\x20\x20Run\x20directory:\x20\x20\x20\x20'+c['run_dir']),console['log']('\x0a\x20\x20In\x20Cursor,\x20invoke:\x20\x20/devi'),console['log']('\x20\x20Or\x20submit\x20response:'),console['log']('\x20\x20\x20\x20npx\x20analyzthis_design\x20devi\x20respond\x20--run\x20'+c['run_dir']+'\x20--step\x20'+c['step_id']+'\x20--file\x20response.md'),console['log']('\x20\x20Then\x20continue:'),console['log']('\x20\x20\x20\x20npx\x20analyzthis_design\x20run\x20--continue\x20--task\x20\x22'+taskVal+'\x22\x0a'),process['exit'](0x2);return;}}catch(f){f['name']==='HostLlmPendingError'&&(hostLlm['printDeviInstructions'](f),process['exit'](0x2)),console['error']('\x0a\x20\x20✗\x20\x20Run\x20failed:\x20'+f['message']+'\x0a'),process['exit'](0x1);}})());break;}case'run-unchunked':{let runTask=taskVal;if(!runTask&&continueFlag){const st=session['show']({'project':projectVal});runTask=st?.['host_run']?.['task']||hostLlm['loadManifest'](st?.['host_run']?.['run_dir']||'')?.['task']||st?.['digest']?.['task_map_summary'];}!runTask&&(console['error']('\x0a\x20\x20✗\x20\x20--task\x20is\x20required.\x20\x20Example:\x20npx\x20analyzthis_design\x20run-unchunked\x20--task\x20\x22Fix\x20contrast\x22\x20--dry-run\x0a'),process['exit'](0x1));orchestratorRun({'task':runTask,'figma':figmaVal||'','provider':providerVal,'model':modelVal,'dryRun':dryRunFlag,'lite':liteFlag,'full':fullFlag,'deliberate':deliberateFlag?!![]:null,'noDeliberate':noDeliberateFlag,'maxRounds':maxRoundsVal,'satisfaction':satisfactionVal,'continueRun':continueFlag,'experts':expertsVal?expertsVal['split'](',')['map'](a=>a['trim']())['filter'](Boolean):null,'project':projectVal,'output':outputVal,'unchunked':!![]})['catch'](a=>{if(a['name']==='HostLlmPendingError')process['exit'](0x2);console['error']('\x0a\x20\x20✗\x20\x20Run\x20failed:\x20'+a['message']+'\x0a'),process['exit'](0x1);});break;}case'devi':{const sub=flags[0x0];if(sub==='status'){let runDir=runDirVal;if(!runDir){const st=session['show']({'project':projectVal});runDir=st?.['host_run']?.['run_dir']||hostLlm['findLatestRun'](st?.['project_id']||session['getProjectId']())?.['runDir'];}if(!runDir||!fs['existsSync'](runDir)){console['log']('\x0a\x20\x20No\x20host\x20run\x20found.\x20Start\x20one:\x20npx\x20analyzthis_design\x20run\x20--task\x20\x22...\x22\x20--full\x0a');break;}const pending=hostLlm['listPending'](runDir);console['log']('\x0a📋\x20Devi\x20—\x20host\x20run:\x20'+runDir+'\x0a');for(const p of pending){console['log']('\x20\x20'+(p['hasResponse']?'✅':'⏳')+'\x20'+p['stepId']+'\x20('+p['personaId']+')');}const waiting=pending['filter'](a=>!a['hasResponse']);waiting['length']?console['log']('\x0a\x20\x20'+waiting['length']+'\x20pending\x20—\x20invoke\x20/devi\x20in\x20Cursor\x20or\x20devi\x20respond\x20for\x20each\x20step.\x0a'):console['log']('\x0a\x20\x20All\x20responses\x20present\x20—\x20run:\x20npx\x20analyzthis_design\x20run\x20--continue\x20--task\x20\x22...\x22\x0a');break;}if(sub==='respond'){(!runDirVal||!stepVal||!fileVal)&&(console['error']('\x0a\x20\x20✗\x20\x20devi\x20respond\x20requires\x20--run,\x20--step,\x20and\x20--file\x0a'),process['exit'](0x1));const text=fs['readFileSync'](path['resolve'](fileVal),'utf8');hostLlm['submitResponse'](path['resolve'](runDirVal),stepVal,text),console['log']('\x0a✅\x20Wrote\x20response\x20for\x20'+stepVal+'\x0a');break;}console['log']('\x0a\x20\x20Usage:\x20devi\x20status\x20|\x20devi\x20respond\x20--run\x20<dir>\x20--step\x20<id>\x20--file\x20<path>\x0a');break;}case'metrics':{const projectIds=allFlag?session['listProjects']():[projectVal||session['getProjectId']()];if(!projectIds['length']){console['log']('\x0a\x20\x20No\x20sessions\x20found.\x0a');break;}console['log']('\x0a📊\x20Last-run\x20metrics\x0a');for(const projectId of projectIds){const state=session['show']({'project':projectId});if(!state)continue;const m=state['metrics']||{};console['log']('\x20\x20'+projectId),console['log']('\x20\x20\x20\x20mode:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(m['mode']??'n/a')),console['log']('\x20\x20\x20\x20llm_calls:\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(m['llm_calls']??0x0)),console['log']('\x20\x20\x20\x20experts_run:\x20\x20\x20\x20\x20\x20\x20'+((m['experts_run']||[])['join'](',\x20')||'none')),console['log']('\x20\x20\x20\x20input_tokens_est:\x20\x20'+(m['input_tokens_est']??0x0)),console['log']('\x20\x20\x20\x20output_tokens_est:\x20'+(m['output_tokens_est']??0x0)),console['log']('\x20\x20\x20\x20cache_hits:\x20\x20\x20\x20\x20\x20\x20\x20'+(m['cache_hits']??0x0)),console['log']('\x20\x20\x20\x20deliberation_rounds:\x20'+(m['deliberation_rounds']??0x0)),console['log']('\x20\x20\x20\x20objections_raised:\x20'+(m['objections_raised']??0x0)),console['log']('\x20\x20\x20\x20objections_resolved:\x20'+(m['objections_resolved']??0x0)),console['log']('\x20\x20\x20\x20raj_escalations:\x20\x20\x20'+(m['raj_escalations']??0x0));const d=state['deliberation'];d?.['mode']&&console['log']('\x20\x20\x20\x20deliberation_mode:\x20'+d['mode']+',\x20consensus='+d['consensus_reached']),console['log']('');}break;}case'cost':{cost['report']({'project':projectVal,'all':allFlag});break;}case'feedback':{const sub=flags[0x0]||'record';if(sub==='record'){!personaVal&&(console['error']('\x0a\x20\x20✗\x20\x20--persona\x20is\x20required.\x0a'),console['error']('\x20\x20Example:\x20npx\x20analyzthis_design\x20feedback\x20record\x20--persona\x20arjun\x20--rating\x202\x20\x5c\x0a'),console['error']('\x20\x20\x20\x20--comment\x20\x22Invented\x20tokens\x22\x20--correction\x20\x22Use\x20tokens.css\x20primary\x20+\x20spacing-4\x22\x0a'),process['exit'](0x1));const ratingNum=ratingVal!=null?Number(ratingVal):undefined,satisfied=ratingNum!=null?ratingNum>=0x4:![];try{const result=feedback['recordFeedback']({'project':projectVal,'persona':personaVal,'satisfied':satisfied,'rating':ratingNum,'comment':commentVal||'','correction':correctionVal||'','tags':parseFeedbackTags(tagsVal),'markRejected':!satisfied});console['log']('\x0a📝\x20Feedback\x20recorded\x20for\x20\x22'+personaVal+'\x22\x20('+result['entry']['id']+').'),console['log']('\x20\x20\x20Global\x20log:\x20'+result['globalFile']+'\x0a');}catch(u){console['error']('\x0a\x20\x20✗\x20\x20'+u['message']+'\x0a'),process['exit'](0x1);}break;}if(sub==='list'){const items=feedback['listFeedback']({'project':projectVal,'all':allFlag});if(!items['length']){console['log']('\x0a\x20\x20No\x20feedback\x20entries\x20yet.\x0a'),console['log']('\x20\x20Record\x20one:\x20npx\x20analyzthis_design\x20feedback\x20record\x20--persona\x20arjun\x20--rating\x202\x20--comment\x20\x22...\x22\x0a');break;}console['log']('\x0a──\x20Feedback\x20('+items['length']+')\x20───────────────────────────────');for(const e of items){const mood=e['satisfied']?'✅':'⚠️',rating=e['rating']!=null?'\x20rating='+e['rating']:'',tags=e['tags']?.['length']?'\x20['+e['tags']['join'](',\x20')+']':'',sent=e['submitted_at']?'\x20📤':'';console['log'](mood+'\x20'+e['at']+'\x20\x20'+e['persona']+rating+tags+sent);if(e['comment'])console['log']('\x20\x20\x20comment:\x20'+e['comment']['slice'](0x0,0x78)+(e['comment']['length']>0x78?'…':''));if(e['correction'])console['log']('\x20\x20\x20correction:\x20'+e['correction']['slice'](0x0,0x78)+(e['correction']['length']>0x78?'…':''));}console['log']('');break;}if(sub==='export'){try{const result=feedback['exportCorrections']({'persona':personaVal,'project':projectVal,'all':allFlag,'output':outputVal,'includePositive':includePositiveFlag});console['log']('\x0a✅\x20Wrote\x20'+result['pairs']+'\x20correction\x20pair(s)\x20to\x20'+result['filePath']),!result['pairs']&&(console['log']('\x20\x20\x20No\x20entries\x20with\x20comment/correction\x20found.\x20Record\x20feedback\x20first.'),console['log']('\x20\x20\x20Tags\x20hint:\x20'+feedback['ISSUE_TAG_HINTS']['slice'](0x0,0x6)['join'](',\x20')+',\x20…')),console['log']('');}catch(w){console['error']('\x0a\x20\x20✗\x20\x20'+w['message']+'\x0a'),process['exit'](0x1);}break;}if(sub==='submit'){((async()=>{try{const a=await feedbackSubmit['submitFeedback']({'project':projectVal,'all':allFlag,'persona':personaVal,'includePositive':includePositiveFlag,'dryRun':dryRunFlag,'yes':yesFlag,'limit':limitVal});a['cancelled']&&(console['log']('\x0a\x20\x20'+a['message']+'\x0a'),process['exit'](0x0));if(a['dryRun']&&a['payloads']){console['log']('\x0a──\x20Dry\x20run:\x20'+a['payloads']['length']+'\x20row(s)\x20─────────────────'),console['log']('\x20\x20\x20Endpoint:\x20'+a['endpoint']),console['log'](JSON['stringify'](a['payloads'][0x0],null,0x2));a['payloads']['length']>0x1&&console['log']('\x20\x20\x20…\x20and\x20'+(a['payloads']['length']-0x1)+'\x20more');console['log']('');return;}console['log']('\x0a✅\x20'+a['message']);if(a['endpoint'])console['log']('\x20\x20\x20Endpoint:\x20'+a['endpoint']);console['log']('');}catch(c){console['error']('\x0a\x20\x20✗\x20\x20'+c['message']+'\x0a'),process['exit'](0x1);}})());break;}if(sub==='status'){const st=feedbackSubmit['submitStatus']();console['log']('\x0a──\x20Feedback\x20submit\x20status\x20───────────────────────────'),console['log']('\x20\x20Consent:\x20\x20\x20\x20\x20'+st['consent']),console['log']('\x20\x20Endpoint:\x20\x20\x20\x20'+st['endpoint']),console['log']('\x20\x20Anon\x20key:\x20\x20\x20\x20'+st['anonKey']),console['log']('\x20\x20Unsent:\x20\x20\x20\x20\x20\x20'+st['unsentCount']+'\x20entr'+(st['unsentCount']===0x1?'y':'ies')),console['log']('\x20\x20Install\x20id:\x20\x20'+st['installId']+'\x20(anonymous)'),console['log']('\x20\x20Package:\x20\x20\x20\x20\x20'+st['packageVersion']),console['log']('');break;}if(sub==='revoke'){feedbackSubmit['revokeConsent'](),console['log']('\x0a🛑\x20Opt-in\x20consent\x20revoked.\x20Run\x20feedback\x20submit\x20again\x20to\x20re-consent.\x0a');break;}console['error']('\x0aUnknown\x20feedback\x20subcommand:\x20\x22'+sub+'\x22.\x20Use:\x20record\x20|\x20list\x20|\x20export\x20|\x20submit\x20|\x20status\x20|\x20revoke\x0a'),process['exit'](0x1);}case'export-training':{!personaVal&&(console['error']('\x0a\x20\x20✗\x20\x20--persona\x20is\x20required.\x20\x20Example:\x20npx\x20analyzthis_design\x20export-training\x20--persona\x20arjun\x0a'),process['exit'](0x1));try{const result=exportTraining({'persona':personaVal,'project':projectVal,'all':allFlag,'output':outputVal});console['log']('\x0a✅\x20Wrote\x20'+result['pairs']+'\x20accepted\x20training\x20pair(s)\x20for\x20\x22'+personaVal+'\x22\x20to\x20'+result['filePath']),!result['pairs']&&console['log']('\x20\x20\x20No\x20accepted\x20outputs\x20found.\x20Mark\x20one\x20first:\x20npx\x20analyzthis_design\x20session\x20accept\x20--persona\x20'+personaVal),console['log']('');}catch(x){console['error']('\x0a\x20\x20✗\x20\x20'+x['message']+'\x0a'),process['exit'](0x1);}break;}case'evolve':{const evolve=require('../lib/evolve'),windowArg=getFlag('window'),windowDays=windowArg?parseInt(windowArg,0xa):0x7;if(flags['includes']('--extract')){((async()=>{try{const a=await evolve['runEvolution']({'windowDays':windowDays,'dryRun':dryRunFlag});console['log']('\x0a──\x20Evolution\x20report\x20'+(dryRunFlag?'(dry\x20run)':'')+'\x20──'),console['log']('\x20\x20Lessons\x20extracted:\x20\x20'+a['extracted_lessons']),console['log']('\x20\x20Outcomes\x20inferred:\x20\x20'+a['inferred_outcomes']),console['log']('\x20\x20Prompt\x20patches:\x20\x20\x20\x20\x20'+a['prompt_patches']['length']),console['log']('\x20\x20Reference\x20proposals:'+a['reference_proposals']['length']),console['log']('\x20\x20Router\x20patches:\x20\x20\x20\x20\x20'+a['router_patches']['length']);for(const c of a['prompt_patches']){console['log']('\x0a\x20\x20Patch:\x20'+c['id']+'\x20—\x20'+c['persona']+'\x20—\x20'+c['description']);}for(const f of a['reference_proposals']){console['log']('\x0a\x20\x20Reference:\x20'+f['id']+'\x20—\x20'+f['persona']+'\x20—\x20'+f['description']);}for(const g of a['router_patches']){console['log']('\x0a\x20\x20Router:\x20'+g['id']+'\x20—\x20'+g['task_type']+'\x20→\x20'+g['suggested_route_to']['join'](',\x20'));}console['log']('');}catch(o){console['error']('\x0a\x20\x20✗\x20\x20'+o['message']+'\x0a'),process['exit'](0x1);}})());break;}if(flags['includes']('--apply')){const applyId=getFlag('apply');!applyId&&(console['error']('\x0a\x20\x20✗\x20\x20--apply\x20requires\x20a\x20patch\x20id\x0a'),process['exit'](0x1));try{const result=evolve['applyPatch']({'patchId':applyId,'dryRun':dryRunFlag});if(result['preview'])console['log']('\x0a──\x20Dry-run\x20patch\x20preview\x20──'),console['log']('\x20\x20Target:\x20'+result['targetFile']),console['log']('\x20\x20Preview:\x0a'+result['preview']['slice'](0x0,0x4b0));else{console['log']('\x0a✅\x20Patch\x20'+(result['applied']?'applied':'previewed')+':\x20'+applyId);if(result['targetFile'])console['log']('\x20\x20\x20Target:\x20'+result['targetFile']);if(result['message'])console['log']('\x20\x20\x20Note:\x20'+result['message']);}console['log']('');}catch(y){console['error']('\x0a\x20\x20✗\x20\x20'+y['message']+'\x0a'),process['exit'](0x1);}break;}console['log']('\x0a\x20\x20Usage:\x20evolve\x20--extract\x20[--window\x20N]\x20[--dry-run]\x20|\x20evolve\x20--apply\x20<patchId>\x20[--dry-run]\x0a');break;}case'outcome':{const outcome=require('../lib/outcome');if(flags['includes']('--infer')){const windowArg2=getFlag('window'),wd=windowArg2?parseInt(windowArg2,0xa):0x7;try{const result=outcome['inferAllOutcomes']({'windowDays':wd});console['log']('\x0a✅\x20Inferred\x20'+result['inferred']+'\x20outcome(s),\x20'+result['confirmed']+'\x20confirmed,\x20'+result['unknown']+'\x20unknown.\x0a');}catch(z){console['error']('\x0a\x20\x20✗\x20\x20'+z['message']+'\x0a'),process['exit'](0x1);}break;}if(flags['includes']('--pending')){const pending=outcome['listPendingConfirmations']();if(!pending['length'])console['log']('\x0a\x20\x20No\x20pending\x20outcome\x20confirmations.\x0a');else{console['log']('\x0a──\x20Pending\x20outcome\x20confirmations\x20('+pending['length']+')\x20──');for(const p of pending){console['log']('\x20\x20'+p['project']+'\x20/\x20'+p['persona']+':\x20'+p['inferred']+'\x20('+p['reason']+')');}console['log']('');}break;}if(flags['includes']('--confirm')){!personaVal&&(console['error']('\x0a\x20\x20✗\x20\x20--persona\x20is\x20required\x20for\x20--confirm\x0a'),process['exit'](0x1));const resultVal=getFlag('result');!resultVal&&(console['error']('\x0a\x20\x20✗\x20\x20--result\x20is\x20required\x20(shipped\x20|\x20revised\x20|\x20blocked_correctly\x20|\x20missed)\x0a'),process['exit'](0x1));try{outcome['confirmOutcome']({'project':projectVal,'persona':personaVal,'outcome':resultVal}),console['log']('\x0a✅\x20Outcome\x20confirmed:\x20'+personaVal+'\x20=\x20'+resultVal+'\x0a');}catch(A){console['error']('\x0a\x20\x20✗\x20\x20'+A['message']+'\x0a'),process['exit'](0x1);}break;}console['log']('\x0a\x20\x20Usage:\x20outcome\x20--infer\x20[--window\x20N]\x20|\x20outcome\x20--pending\x20|\x20outcome\x20--confirm\x20--persona\x20X\x20--result\x20Y\x0a');break;}case'--help':case'help':case'-h':console['log'](HELP);break;default:console['error']('\x0aUnknown\x20command:\x20\x22'+cmd+'\x22\x0a'),console['log'](HELP),process['exit'](0x1);}
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const { install, remove, SKILLS, TARGET_DIRS, printWelcomeBanner } = require('../lib/install');
|
|
8
|
+
const { resolveTargets, ALL_TARGET_IDS } = require('../lib/platforms');
|
|
9
|
+
const { connect, disconnect, sync, status } = require('../lib/knowledge');
|
|
10
|
+
const session = require('../lib/session');
|
|
11
|
+
const research = require('../lib/research');
|
|
12
|
+
const retrieve = require('../lib/retrieve');
|
|
13
|
+
const { exportTraining } = require('../lib/export');
|
|
14
|
+
const feedback = require('../lib/feedback');
|
|
15
|
+
const feedbackSubmit = require('../lib/feedback-submit');
|
|
16
|
+
const cost = require('../lib/cost');
|
|
17
|
+
const { collect } = require('../lib/collect');
|
|
18
|
+
const designSpec = require('../lib/design-spec');
|
|
19
|
+
const { run: orchestratorRun } = require('../lib/orchestrator/run');
|
|
20
|
+
const hostLlm = require('../lib/host-llm');
|
|
21
|
+
const moodboard = require('../lib/moodboard');
|
|
22
|
+
|
|
23
|
+
const HELP = `
|
|
24
|
+
Analyzthis_Design — 8 AI design personas with a personal knowledge bank
|
|
25
|
+
|
|
26
|
+
Usage:
|
|
27
|
+
npx analyzthis_design [command] [options]
|
|
28
|
+
|
|
29
|
+
── Skill commands ───────────────────────────────────────────
|
|
30
|
+
install Copy all skills to the target AI tool's directory (default)
|
|
31
|
+
remove Delete installed skills from the target AI tool's directory
|
|
32
|
+
list Show installed skills for a target
|
|
33
|
+
welcome Print getting-started banner for your AI tool (--target)
|
|
34
|
+
|
|
35
|
+
── Knowledge bank commands ──────────────────────────────────
|
|
36
|
+
connect Register a vault or knowledge folder as a source
|
|
37
|
+
sync Read all sources and build the knowledge-bank skill
|
|
38
|
+
disconnect Remove a source from the registry
|
|
39
|
+
status Show connected sources and last sync time
|
|
40
|
+
collect Kavi: scan codebase → Obsidian vault → enrich → sync knowledge bank
|
|
41
|
+
(--vault path, --dry-run, --no-enrich, --no-web, --no-discover,
|
|
42
|
+
--web-limit N, --target cursor|claude|codex|grok|windsurf|agents|all)
|
|
43
|
+
|
|
44
|
+
── Design spec commands ─────────────────────────────────────
|
|
45
|
+
spec show Print design_spec from session state
|
|
46
|
+
spec validate Validate a DesignSpec JSON file (--file) or session
|
|
47
|
+
spec save Save DesignSpec JSON to session (--file required)
|
|
48
|
+
spec template Print empty DesignSpec template block
|
|
49
|
+
|
|
50
|
+
── Session commands (agentic orchestrator) ──────────────────
|
|
51
|
+
session init Create a fresh session-state.json for this project
|
|
52
|
+
session show Print the current session-state.json
|
|
53
|
+
session reset Delete the session state for this project (--all for every project)
|
|
54
|
+
session accept Mark a persona's last output accepted, for training export
|
|
55
|
+
(--persona <id>, optional --reject to unmark)
|
|
56
|
+
Optional feedback: --comment, --correction, --rating 1-5, --tags a,b
|
|
57
|
+
|
|
58
|
+
── Persona feedback commands ─────────────────────────────────
|
|
59
|
+
feedback record Record unhappiness or a correction for a persona output
|
|
60
|
+
(--persona <id>, --comment, --correction, --rating 1-5, --tags)
|
|
61
|
+
feedback list List feedback entries for this project (--all for every project)
|
|
62
|
+
feedback export Export rejected + correction JSONL pairs for training
|
|
63
|
+
(--persona <id>, --all, --output <path>, --include-positive)
|
|
64
|
+
feedback submit Opt-in: send anonymized corrections to community store (Supabase)
|
|
65
|
+
(--yes skip prompt, --dry-run preview, --all unsent across projects)
|
|
66
|
+
feedback status Show submit consent, endpoint config, unsent count
|
|
67
|
+
feedback revoke Revoke opt-in consent for community submit
|
|
68
|
+
|
|
69
|
+
── Efficiency / cost commands ────────────────────────────────
|
|
70
|
+
metrics Print the last run's cost metrics (--all for every project)
|
|
71
|
+
cost Print the last run's $ cost from config.pricing (--all for every project)
|
|
72
|
+
export-training Write accepted-output JSONL pairs for LoRA prep
|
|
73
|
+
(--persona <id>, --all, --output <path>)
|
|
74
|
+
feedback export Write rejected + correction JSONL pairs (DPO / negative examples)
|
|
75
|
+
|
|
76
|
+
── Research commands ────────────────────────────────────────
|
|
77
|
+
research --url <url> Fetch a URL and append to session web-context.md
|
|
78
|
+
research --query <text> Search stub (or provider) appended to web-context.md
|
|
79
|
+
|
|
80
|
+
── Mood board commands ─────────────────────────────────────
|
|
81
|
+
moodboard create --task <text> Build a mood board from web + DS references
|
|
82
|
+
[--url <url> ...] [--auto]
|
|
83
|
+
moodboard critique --board <id> Run team deliberation over a board
|
|
84
|
+
moodboard add --board <id> Add a user reference and rerun critique
|
|
85
|
+
[--url <url>] [--title <t>] [--desc <d>]
|
|
86
|
+
[--tags a,b] [--note <text>]
|
|
87
|
+
moodboard list List mood boards for this project
|
|
88
|
+
|
|
89
|
+
── Reference data (retrieve-on-demand) ───────────────────────
|
|
90
|
+
retrieve --file <csv> --column <col> --keywords a,b Filtered, citation-ready rows
|
|
91
|
+
--limit N (default 3)
|
|
92
|
+
|
|
93
|
+
── Orchestrator (standalone runtime) ────────────────────────
|
|
94
|
+
run --task <text> DEFAULT v2.0: frontier planner → cheap chunk models → synthesis
|
|
95
|
+
--budget free only zero-cost models (Ollama, free APIs)
|
|
96
|
+
--budget cheap include cheap cloud models with user keys
|
|
97
|
+
--sequential run chunks sequentially (default)
|
|
98
|
+
--max-chunks N cap chunks (default 6)
|
|
99
|
+
--dry-run show planner output without executing chunks
|
|
100
|
+
--unchunked use the legacy single-pass orchestrator
|
|
101
|
+
|
|
102
|
+
run-unchunked --task <text> Legacy non-chunked orchestrator
|
|
103
|
+
--continue resume after /devi fills pending responses
|
|
104
|
+
--lite (default) MoE subset only | --full allow full chain
|
|
105
|
+
--experts a,b explicit override, skips the router entirely
|
|
106
|
+
--deliberate adversarial satisfaction loops (default on)
|
|
107
|
+
--no-deliberate legacy sequential pass-the-parcel mode
|
|
108
|
+
--max-rounds N cap deliberation rounds (default 3)
|
|
109
|
+
--satisfaction X satisfaction threshold 0.0-1.0 (default 0.4)
|
|
110
|
+
|
|
111
|
+
── Devi (host LLM — no API keys) ────────────────────────────
|
|
112
|
+
devi status List pending persona prompts awaiting host LLM responses
|
|
113
|
+
(--run path to a specific run directory)
|
|
114
|
+
devi respond Submit a persona response file
|
|
115
|
+
(--run path, --step 001-arjun, --file response.md)
|
|
116
|
+
|
|
117
|
+
── Options ──────────────────────────────────────────────────
|
|
118
|
+
--target Platform: cursor | claude | codex | grok | windsurf | agents | all (default: cursor)
|
|
119
|
+
--force Overwrite existing skills on install
|
|
120
|
+
--vault Path to Obsidian vault or markdown folder (connect command)
|
|
121
|
+
--tags Comma-separated tags to filter by, e.g. design,brand,ux
|
|
122
|
+
--include Comma-separated sub-folder names to include, e.g. Design,Brand
|
|
123
|
+
--project Project id override for session/research/run commands (default: derived from cwd)
|
|
124
|
+
--all With "session reset", clear every project's session state
|
|
125
|
+
--url URL to fetch (research command)
|
|
126
|
+
--query Search query (research command)
|
|
127
|
+
--task Task description (run command)
|
|
128
|
+
--figma Figma URL (run command)
|
|
129
|
+
--provider anthropic | openai | google | zai | ollama | groq | together | openrouter | deepseek | host (default: auto)
|
|
130
|
+
--model Model override (run / run-unchunked command)
|
|
131
|
+
--continue With "run-unchunked", resume host-mode run after devi respond
|
|
132
|
+
--dry-run Print routing + chain without calling any LLM (run / run-unchunked command); or show planner output
|
|
133
|
+
--lite Force MoE subset only, even for full_screen_review (run-unchunked command; default)
|
|
134
|
+
--full Allow the full design-critic chain for full_screen_review (run-unchunked command)
|
|
135
|
+
--experts Comma-separated persona ids, bypasses the router entirely (run-unchunked command)
|
|
136
|
+
--budget free | cheap | auto — chunk model budget (run command; default: auto)
|
|
137
|
+
--sequential Run chunks sequentially (run command; default on)
|
|
138
|
+
--max-chunks Cap number of planner chunks (run command; default 6)
|
|
139
|
+
--unchunked Force legacy single-pass orchestrator (run command)
|
|
140
|
+
--output Write final session-state.json to this path (run / run-unchunked command); or JSONL path (export-training)
|
|
141
|
+
--persona Persona id (session accept; export-training; feedback commands)
|
|
142
|
+
--reject With "session accept", mark the output rejected instead of accepted
|
|
143
|
+
--comment What was wrong or what you liked (session accept / feedback record)
|
|
144
|
+
--correction How you fixed it or what you wanted instead (session accept / feedback record)
|
|
145
|
+
--rating 1 (very unhappy) to 5 (very happy) — feedback record / session accept
|
|
146
|
+
--include-positive With "feedback export", include satisfied entries too
|
|
147
|
+
--yes With "feedback submit", accept consent prompt without asking again
|
|
148
|
+
--deliberate With "run", force adversarial deliberation loops
|
|
149
|
+
--no-deliberate With "run", legacy sequential handoff (no objection rounds)
|
|
150
|
+
--max-rounds With "run", cap deliberation rounds (default 3)
|
|
151
|
+
--satisfaction With "run", satisfaction threshold 0.0-1.0 (default 0.4)
|
|
152
|
+
--no-enrich With "collect", write draft vault + sync without LLM enrichment
|
|
153
|
+
--no-web With "collect", skip fetching URLs from config/PRDs/README
|
|
154
|
+
--no-discover With "collect", skip Obsidian/vault/knowledge-graph discovery
|
|
155
|
+
--web-limit Cap external URLs fetched during collect (default: 10)
|
|
156
|
+
--limit Cap notes enriched (collect) or retrieve rows (retrieve)
|
|
157
|
+
--board Mood board id (moodboard critique / add)
|
|
158
|
+
--title Reference title (moodboard add)
|
|
159
|
+
--desc Reference description (moodboard add)
|
|
160
|
+
--auto With moodboard create, discover references without explicit URLs
|
|
161
|
+
--help Show this help message
|
|
162
|
+
|
|
163
|
+
── Examples ─────────────────────────────────────────────────
|
|
164
|
+
npx analyzthis_design # install for Cursor
|
|
165
|
+
npx analyzthis_design --target all # install for all tools
|
|
166
|
+
npx analyzthis_design welcome # re-print getting-started help
|
|
167
|
+
npx analyzthis_design welcome --target claude
|
|
168
|
+
|
|
169
|
+
npx analyzthis_design collect # Kavi: scan → vault → enrich → sync
|
|
170
|
+
npx analyzthis_design collect --dry-run # preview classification + web URLs
|
|
171
|
+
npx analyzthis_design collect --no-enrich --limit 50
|
|
172
|
+
npx analyzthis_design collect --no-web # skip external URL fetch
|
|
173
|
+
npx analyzthis_design collect --vault ~/Documents/MyVault --target all
|
|
174
|
+
|
|
175
|
+
npx analyzthis_design connect --vault ~/Documents/MyVault
|
|
176
|
+
npx analyzthis_design connect --vault ~/docs --tags design,brand,product
|
|
177
|
+
npx analyzthis_design connect --vault ~/vault --include Design,Research
|
|
178
|
+
npx analyzthis_design sync # sync to Cursor
|
|
179
|
+
npx analyzthis_design sync --target all # sync to all tools
|
|
180
|
+
npx analyzthis_design status # show sources
|
|
181
|
+
npx analyzthis_design disconnect --vault ~/Documents/MyVault
|
|
182
|
+
|
|
183
|
+
npx analyzthis_design session init # start a new session for this repo
|
|
184
|
+
npx analyzthis_design session show # inspect current session state
|
|
185
|
+
npx analyzthis_design session reset # clear session state for this repo
|
|
186
|
+
|
|
187
|
+
npx analyzthis_design research --url https://example.com/design-tokens
|
|
188
|
+
npx analyzthis_design research --query "EY design system tokens"
|
|
189
|
+
|
|
190
|
+
npx analyzthis_design moodboard create --task "B2B fintech dashboard, trustworthy, high-contrast" --auto
|
|
191
|
+
npx analyzthis_design moodboard critique --board <boardId>
|
|
192
|
+
npx analyzthis_design moodboard add --board <boardId> --url https://dribbble.com/shots/example --title "Alt hero" --tags "landing,trust"
|
|
193
|
+
|
|
194
|
+
npx analyzthis_design retrieve --file colors.csv --column "Product Type" --keywords saas,dashboard
|
|
195
|
+
npx analyzthis_design retrieve --file styles.csv --column "Best For" --keywords b2b --limit 3
|
|
196
|
+
|
|
197
|
+
npx analyzthis_design run --task "Fix contrast on landing page" --dry-run
|
|
198
|
+
npx analyzthis_design run --task "Review this screen" --budget free
|
|
199
|
+
npx analyzthis_design run --task "Review this screen" --budget cheap --sequential
|
|
200
|
+
npx analyzthis_design run-unchunked --task "Just check spacing" --experts arjun
|
|
201
|
+
npx analyzthis_design devi status
|
|
202
|
+
npx analyzthis_design devi respond --run ~/.analyzthis_design/runs/... --step 001-arjun --file out.md
|
|
203
|
+
npx analyzthis_design run-unchunked --task "Review this screen" --provider anthropic
|
|
204
|
+
|
|
205
|
+
npx analyzthis_design session accept --persona arjun
|
|
206
|
+
npx analyzthis_design session accept --persona arjun --reject \\
|
|
207
|
+
--comment "Invented tokens not in our DS" \\
|
|
208
|
+
--correction "Use --color-primary and spacing-4 from tokens.css" \\
|
|
209
|
+
--rating 2 --tags invented_tokens,missed_ds
|
|
210
|
+
npx analyzthis_design feedback record --persona arjun --rating 2 --comment "..." --correction "..."
|
|
211
|
+
npx analyzthis_design feedback list
|
|
212
|
+
npx analyzthis_design feedback export --persona arjun --all
|
|
213
|
+
npx analyzthis_design feedback submit --dry-run
|
|
214
|
+
npx analyzthis_design feedback submit --all --yes
|
|
215
|
+
npx analyzthis_design feedback status
|
|
216
|
+
npx analyzthis_design metrics
|
|
217
|
+
npx analyzthis_design cost
|
|
218
|
+
npx analyzthis_design export-training --persona arjun --all
|
|
219
|
+
|
|
220
|
+
── Install paths ────────────────────────────────────────────
|
|
221
|
+
Cursor → ~/.cursor/skills/
|
|
222
|
+
Claude → ~/.claude/skills/ (+ legacy ~/.claude/commands/)
|
|
223
|
+
Codex → ~/.codex/skills/
|
|
224
|
+
Grok → ~/.grok/skills/
|
|
225
|
+
Windsurf → ~/.codeium/windsurf/skills/
|
|
226
|
+
agents → ~/.agents/skills/ (cross-tool discovery)
|
|
227
|
+
|
|
228
|
+
── Knowledge bank config ────────────────────────────────────
|
|
229
|
+
Config → ~/.analyzthis_design/config.json
|
|
230
|
+
|
|
231
|
+
Docs: https://github.com/rishikeshjoshi/analyzthis_design
|
|
232
|
+
`;
|
|
233
|
+
|
|
234
|
+
// ─── Parse args ──────────────────────────────────────────────────────────────
|
|
235
|
+
|
|
236
|
+
const [,, cmd, ...flags] = process.argv;
|
|
237
|
+
|
|
238
|
+
function getFlag(name) {
|
|
239
|
+
// Supports both --flag=value and --flag value
|
|
240
|
+
const eq = flags.find(f => f.startsWith(`--${name}=`));
|
|
241
|
+
if (eq) return eq.split('=').slice(1).join('=');
|
|
242
|
+
const idx = flags.indexOf(`--${name}`);
|
|
243
|
+
if (idx !== -1 && flags[idx + 1] && !flags[idx + 1].startsWith('--')) return flags[idx + 1];
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function parseFeedbackTags(raw) {
|
|
248
|
+
if (!raw) return [];
|
|
249
|
+
return raw.split(',').map((t) => t.trim().toLowerCase()).filter(Boolean);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const force = flags.includes('--force');
|
|
253
|
+
const targetVal = getFlag('target') || 'cursor';
|
|
254
|
+
const vaultVal = getFlag('vault');
|
|
255
|
+
const tagsVal = getFlag('tags');
|
|
256
|
+
const includeVal = getFlag('include');
|
|
257
|
+
const projectVal = getFlag('project');
|
|
258
|
+
const allFlag = flags.includes('--all');
|
|
259
|
+
const urlVal = getFlag('url');
|
|
260
|
+
const queryVal = getFlag('query');
|
|
261
|
+
const taskVal = getFlag('task');
|
|
262
|
+
const figmaVal = getFlag('figma');
|
|
263
|
+
const providerVal = getFlag('provider');
|
|
264
|
+
const modelVal = getFlag('model');
|
|
265
|
+
const outputVal = getFlag('output');
|
|
266
|
+
const dryRunFlag = flags.includes('--dry-run');
|
|
267
|
+
const liteFlag = flags.includes('--lite');
|
|
268
|
+
const fullFlag = flags.includes('--full');
|
|
269
|
+
const expertsVal = getFlag('experts');
|
|
270
|
+
const fileVal = getFlag('file');
|
|
271
|
+
const columnVal = getFlag('column');
|
|
272
|
+
const keywordsVal = getFlag('keywords');
|
|
273
|
+
const limitVal = getFlag('limit');
|
|
274
|
+
const personaVal = getFlag('persona');
|
|
275
|
+
const rejectFlag = flags.includes('--reject');
|
|
276
|
+
const commentVal = getFlag('comment');
|
|
277
|
+
const correctionVal = getFlag('correction');
|
|
278
|
+
const ratingVal = getFlag('rating');
|
|
279
|
+
const includePositiveFlag = flags.includes('--include-positive');
|
|
280
|
+
const yesFlag = flags.includes('--yes');
|
|
281
|
+
const deliberateFlag = flags.includes('--deliberate');
|
|
282
|
+
const noDeliberateFlag = flags.includes('--no-deliberate');
|
|
283
|
+
const maxRoundsVal = getFlag('max-rounds');
|
|
284
|
+
const satisfactionVal = getFlag('satisfaction');
|
|
285
|
+
const continueFlag = flags.includes('--continue');
|
|
286
|
+
const runDirVal = getFlag('run');
|
|
287
|
+
const stepVal = getFlag('step');
|
|
288
|
+
const noEnrichFlag = flags.includes('--no-enrich');
|
|
289
|
+
const noWebFlag = flags.includes('--no-web');
|
|
290
|
+
const noDiscoverFlag = flags.includes('--no-discover');
|
|
291
|
+
const webLimitVal = getFlag('web-limit');
|
|
292
|
+
const boardVal = getFlag('board');
|
|
293
|
+
const titleVal = getFlag('title');
|
|
294
|
+
const descVal = getFlag('desc');
|
|
295
|
+
const autoFlag = flags.includes('--auto');
|
|
296
|
+
const budgetVal = getFlag('budget');
|
|
297
|
+
const sequentialFlag = flags.includes('--sequential');
|
|
298
|
+
const maxChunksVal = getFlag('max-chunks');
|
|
299
|
+
const unchunkedFlag = flags.includes('--unchunked');
|
|
300
|
+
|
|
301
|
+
// ─── Commands ────────────────────────────────────────────────────────────────
|
|
302
|
+
|
|
303
|
+
switch (cmd) {
|
|
304
|
+
case undefined:
|
|
305
|
+
case 'install':
|
|
306
|
+
install({ force, target: targetVal });
|
|
307
|
+
break;
|
|
308
|
+
|
|
309
|
+
case 'remove':
|
|
310
|
+
case 'uninstall':
|
|
311
|
+
remove({ target: targetVal });
|
|
312
|
+
break;
|
|
313
|
+
|
|
314
|
+
case 'welcome': {
|
|
315
|
+
const targets = resolveTargets(targetVal) || ['cursor'];
|
|
316
|
+
for (const tId of targets) printWelcomeBanner(tId);
|
|
317
|
+
break;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
case 'list': {
|
|
321
|
+
const { TARGETS } = require('../lib/platforms');
|
|
322
|
+
const targets = resolveTargets(targetVal);
|
|
323
|
+
if (!targets) {
|
|
324
|
+
console.error(`\n ✗ Unknown target "${targetVal}". Choose: ${ALL_TARGET_IDS.join(', ')}, all\n`);
|
|
325
|
+
process.exit(1);
|
|
326
|
+
}
|
|
327
|
+
for (const tId of targets) {
|
|
328
|
+
const t = TARGETS[tId];
|
|
329
|
+
console.log(`\nInstalled Analyzthis_Design skills [${t.label}] (${t.root}):\n`);
|
|
330
|
+
for (const skill of SKILLS) {
|
|
331
|
+
const asDir = path.join(t.root, skill);
|
|
332
|
+
const asFile = path.join(t.root, `${skill}.md`);
|
|
333
|
+
let exists = fs.existsSync(asDir) || fs.existsSync(asFile);
|
|
334
|
+
if (!exists && t.also) {
|
|
335
|
+
exists = fs.existsSync(path.join(t.also.root, skill)) ||
|
|
336
|
+
fs.existsSync(path.join(t.also.root, `${skill}.md`));
|
|
337
|
+
}
|
|
338
|
+
console.log(` ${exists ? '✅' : '✗ '} ${skill}`);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
console.log('');
|
|
342
|
+
break;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// ── Knowledge bank ──────────────────────────────────────────────────────
|
|
346
|
+
|
|
347
|
+
case 'connect': {
|
|
348
|
+
if (!vaultVal) {
|
|
349
|
+
console.error('\n ✗ --vault is required. Example: npx analyzthis_design connect --vault ~/Documents/MyVault\n');
|
|
350
|
+
process.exit(1);
|
|
351
|
+
}
|
|
352
|
+
try {
|
|
353
|
+
const tags = tagsVal ? tagsVal.split(',').map(t => t.trim()) : [];
|
|
354
|
+
const include = includeVal ? includeVal.split(',').map(t => t.trim()) : [];
|
|
355
|
+
const abs = connect({ vaultPath: vaultVal, tags, include });
|
|
356
|
+
console.log(`\n✅ Connected: ${abs}`);
|
|
357
|
+
if (tags.length) console.log(` Tags filter: ${tags.join(', ')}`);
|
|
358
|
+
if (include.length) console.log(` Folder filter: ${include.join(', ')}`);
|
|
359
|
+
console.log(`\n Run "npx analyzthis_design sync" to build the knowledge bank.\n`);
|
|
360
|
+
} catch (err) {
|
|
361
|
+
console.error(`\n ✗ ${err.message}\n`);
|
|
362
|
+
process.exit(1);
|
|
363
|
+
}
|
|
364
|
+
break;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
case 'disconnect': {
|
|
368
|
+
if (!vaultVal) {
|
|
369
|
+
console.error('\n ✗ --vault is required. Example: npx analyzthis_design disconnect --vault ~/Documents/MyVault\n');
|
|
370
|
+
process.exit(1);
|
|
371
|
+
}
|
|
372
|
+
disconnect(vaultVal);
|
|
373
|
+
console.log(`\n🗑 Disconnected: ${path.resolve(vaultVal)}\n`);
|
|
374
|
+
break;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
case 'sync': {
|
|
378
|
+
const { resolveTargets, ALL_TARGET_IDS } = require('../lib/platforms');
|
|
379
|
+
const targets = resolveTargets(targetVal);
|
|
380
|
+
if (!targets) {
|
|
381
|
+
console.error(`\n ✗ Unknown target "${targetVal}". Choose: ${ALL_TARGET_IDS.join(', ')}, all\n`);
|
|
382
|
+
process.exit(1);
|
|
383
|
+
}
|
|
384
|
+
console.log('\n⏳ Syncing knowledge bank...\n');
|
|
385
|
+
try {
|
|
386
|
+
const result = sync({ targets });
|
|
387
|
+
if (result.message) {
|
|
388
|
+
console.log(` ⚠ ${result.message}\n`);
|
|
389
|
+
} else {
|
|
390
|
+
console.log(`✅ Synced ${result.synced} note(s) into the knowledge bank.`);
|
|
391
|
+
for (const t of result.copiedTo) console.log(` • ${t}`);
|
|
392
|
+
console.log(`\n💡 The knowledge bank is now active. All personas will read it first.\n`);
|
|
393
|
+
}
|
|
394
|
+
} catch (err) {
|
|
395
|
+
console.error(`\n ✗ Sync failed: ${err.message}\n`);
|
|
396
|
+
process.exit(1);
|
|
397
|
+
}
|
|
398
|
+
break;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
case 'status': {
|
|
402
|
+
const cfg = status();
|
|
403
|
+
if (!cfg.sources || cfg.sources.length === 0) {
|
|
404
|
+
console.log('\n No knowledge sources connected.\n Run: npx analyzthis_design connect --vault /path/to/vault\n');
|
|
405
|
+
} else {
|
|
406
|
+
console.log(`\n📚 Knowledge bank sources (${cfg.sources.length}):\n`);
|
|
407
|
+
for (const s of cfg.sources) {
|
|
408
|
+
console.log(` • ${s.path}`);
|
|
409
|
+
if (s.tags.length) console.log(` Tags: ${s.tags.join(', ')}`);
|
|
410
|
+
if (s.include.length) console.log(` Folders: ${s.include.join(', ')}`);
|
|
411
|
+
console.log(` Added: ${s.addedAt}`);
|
|
412
|
+
}
|
|
413
|
+
if (cfg.lastSync) console.log(`\n Last sync: ${cfg.lastSync}`);
|
|
414
|
+
console.log('');
|
|
415
|
+
}
|
|
416
|
+
break;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// ── Session (agentic orchestrator) ──────────────────────────────────────
|
|
420
|
+
|
|
421
|
+
case 'session': {
|
|
422
|
+
const sub = flags.find(f => !f.startsWith('--'));
|
|
423
|
+
switch (sub) {
|
|
424
|
+
case 'init': {
|
|
425
|
+
const { projectId, filePath } = session.init({ project: projectVal });
|
|
426
|
+
console.log(`\n✅ Session initialized for project "${projectId}"`);
|
|
427
|
+
console.log(` ${filePath}\n`);
|
|
428
|
+
break;
|
|
429
|
+
}
|
|
430
|
+
case 'show': {
|
|
431
|
+
const state = session.show({ project: projectVal });
|
|
432
|
+
if (!state) {
|
|
433
|
+
console.log('\n No session found. Run: npx analyzthis_design session init\n');
|
|
434
|
+
} else {
|
|
435
|
+
console.log(JSON.stringify(state, null, 2));
|
|
436
|
+
}
|
|
437
|
+
break;
|
|
438
|
+
}
|
|
439
|
+
case 'reset': {
|
|
440
|
+
const result = session.reset({ project: projectVal, all: allFlag });
|
|
441
|
+
console.log(`\n🗑 Session reset: ${result.removed}\n`);
|
|
442
|
+
break;
|
|
443
|
+
}
|
|
444
|
+
case 'accept': {
|
|
445
|
+
if (!personaVal) {
|
|
446
|
+
console.error('\n ✗ --persona is required. Example: npx analyzthis_design session accept --persona arjun\n');
|
|
447
|
+
process.exit(1);
|
|
448
|
+
}
|
|
449
|
+
if (commentVal || correctionVal || ratingVal) {
|
|
450
|
+
try {
|
|
451
|
+
const fb = feedback.recordFeedback({
|
|
452
|
+
project: projectVal,
|
|
453
|
+
persona: personaVal,
|
|
454
|
+
satisfied: !rejectFlag,
|
|
455
|
+
rating: ratingVal != null ? Number(ratingVal) : undefined,
|
|
456
|
+
comment: commentVal || '',
|
|
457
|
+
correction: correctionVal || '',
|
|
458
|
+
tags: parseFeedbackTags(tagsVal),
|
|
459
|
+
markRejected: true,
|
|
460
|
+
});
|
|
461
|
+
console.log(`\n✅ Marked "${personaVal}" as ${rejectFlag ? 'rejected' : 'accepted'} with feedback (${fb.entry.id}).\n`);
|
|
462
|
+
} catch (err) {
|
|
463
|
+
console.error(`\n ✗ ${err.message}\n`);
|
|
464
|
+
process.exit(1);
|
|
465
|
+
}
|
|
466
|
+
} else {
|
|
467
|
+
const result = session.markAccepted({ project: projectVal, persona: personaVal, accepted: !rejectFlag });
|
|
468
|
+
if (!result.updated) {
|
|
469
|
+
console.log(`\n ⚠ ${result.reason}\n`);
|
|
470
|
+
} else {
|
|
471
|
+
console.log(`\n✅ Marked "${personaVal}" output as ${rejectFlag ? 'rejected' : 'accepted'}.\n`);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
break;
|
|
475
|
+
}
|
|
476
|
+
default:
|
|
477
|
+
console.error(`\nUnknown session subcommand: "${sub || ''}". Use: init | show | reset | accept\n`);
|
|
478
|
+
process.exit(1);
|
|
479
|
+
}
|
|
480
|
+
break;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// ── Design spec ─────────────────────────────────────────────────────────
|
|
484
|
+
|
|
485
|
+
case 'spec': {
|
|
486
|
+
const sub = flags[0] || 'show';
|
|
487
|
+
if (sub === 'template') {
|
|
488
|
+
console.log('\n' + designSpec.templateMarkdown() + '\n');
|
|
489
|
+
break;
|
|
490
|
+
}
|
|
491
|
+
if (sub === 'show') {
|
|
492
|
+
const row = designSpec.showFromSession({ project: projectVal });
|
|
493
|
+
if (!row) {
|
|
494
|
+
console.log('\n No design_spec in session. Run /design-director or /ux-ideator Phase 7 first.\n');
|
|
495
|
+
break;
|
|
496
|
+
}
|
|
497
|
+
console.log('\n── design_spec ──────────────────────────────────────');
|
|
498
|
+
console.log(JSON.stringify(row.design_spec, null, 2));
|
|
499
|
+
console.log('');
|
|
500
|
+
break;
|
|
501
|
+
}
|
|
502
|
+
if (sub === 'save') {
|
|
503
|
+
if (!fileVal) {
|
|
504
|
+
console.error('\n ✗ spec save requires --file <path.json>\n');
|
|
505
|
+
process.exit(1);
|
|
506
|
+
}
|
|
507
|
+
try {
|
|
508
|
+
const raw = fs.readFileSync(path.resolve(fileVal), 'utf8');
|
|
509
|
+
const spec = JSON.parse(raw);
|
|
510
|
+
const validation = designSpec.validateDesignSpec(spec);
|
|
511
|
+
if (!validation.valid) {
|
|
512
|
+
console.log('\n✗ Cannot save invalid spec:\n');
|
|
513
|
+
for (const e of validation.errors) console.log(` • ${e}`);
|
|
514
|
+
console.log('');
|
|
515
|
+
process.exit(1);
|
|
516
|
+
}
|
|
517
|
+
const saved = designSpec.saveToSession(spec, { project: projectVal, merge: false });
|
|
518
|
+
console.log(`\n✅ Saved design_spec to session (${saved.projectId})\n`);
|
|
519
|
+
} catch (err) {
|
|
520
|
+
console.error(`\n ✗ ${err.message}\n`);
|
|
521
|
+
process.exit(1);
|
|
522
|
+
}
|
|
523
|
+
break;
|
|
524
|
+
}
|
|
525
|
+
if (sub === 'validate') {
|
|
526
|
+
try {
|
|
527
|
+
let result;
|
|
528
|
+
if (fileVal) {
|
|
529
|
+
result = designSpec.validateFile(fileVal);
|
|
530
|
+
} else {
|
|
531
|
+
const row = designSpec.showFromSession({ project: projectVal });
|
|
532
|
+
if (!row) {
|
|
533
|
+
console.error('\n ✗ No design_spec in session and no --file provided.\n');
|
|
534
|
+
process.exit(1);
|
|
535
|
+
}
|
|
536
|
+
result = { spec: row.design_spec, ...designSpec.validateDesignSpec(row.design_spec) };
|
|
537
|
+
}
|
|
538
|
+
if (result.valid) {
|
|
539
|
+
console.log('\n✅ DesignSpec is valid.\n');
|
|
540
|
+
if (result.spec && !fileVal) {
|
|
541
|
+
console.log(` status: ${result.spec.status} | screen: ${result.spec.screen_name}\n`);
|
|
542
|
+
}
|
|
543
|
+
} else {
|
|
544
|
+
console.log('\n✗ DesignSpec validation failed:\n');
|
|
545
|
+
for (const e of result.errors) console.log(` • ${e}`);
|
|
546
|
+
console.log('');
|
|
547
|
+
process.exit(1);
|
|
548
|
+
}
|
|
549
|
+
} catch (err) {
|
|
550
|
+
console.error(`\n ✗ ${err.message}\n`);
|
|
551
|
+
process.exit(1);
|
|
552
|
+
}
|
|
553
|
+
break;
|
|
554
|
+
}
|
|
555
|
+
console.error('\n ✗ Unknown spec subcommand. Use: spec show | validate | save | template\n');
|
|
556
|
+
process.exit(1);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// ── Collect knowledge (Kavi) ────────────────────────────────────────────
|
|
560
|
+
|
|
561
|
+
case 'collect': {
|
|
562
|
+
collect({
|
|
563
|
+
project: projectVal,
|
|
564
|
+
vault: vaultVal || undefined,
|
|
565
|
+
dryRun: dryRunFlag,
|
|
566
|
+
enrich: !noEnrichFlag,
|
|
567
|
+
web: !noWebFlag,
|
|
568
|
+
discoverSources: !noDiscoverFlag,
|
|
569
|
+
webLimit: webLimitVal ? parseInt(webLimitVal, 10) : null,
|
|
570
|
+
limit: limitVal ? parseInt(limitVal, 10) : null,
|
|
571
|
+
target: targetVal,
|
|
572
|
+
provider: providerVal,
|
|
573
|
+
model: modelVal,
|
|
574
|
+
}).catch((err) => {
|
|
575
|
+
console.error(`\n ✗ Collect failed: ${err.message}\n`);
|
|
576
|
+
process.exit(1);
|
|
577
|
+
});
|
|
578
|
+
break;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
// ── Research ────────────────────────────────────────────────────────────
|
|
582
|
+
|
|
583
|
+
case 'research': {
|
|
584
|
+
(async () => {
|
|
585
|
+
try {
|
|
586
|
+
if (urlVal) {
|
|
587
|
+
console.log(`\n⏳ Fetching ${urlVal}...\n`);
|
|
588
|
+
const result = await research.researchUrl({ url: urlVal, project: projectVal });
|
|
589
|
+
console.log(`✅ Wrote ${result.chars} chars to ${result.filePath}\n`);
|
|
590
|
+
} else if (queryVal) {
|
|
591
|
+
console.log(`\n⏳ Researching "${queryVal}"...\n`);
|
|
592
|
+
const result = await research.researchQuery({ query: queryVal, project: projectVal });
|
|
593
|
+
if (result.mode === 'stub') {
|
|
594
|
+
console.log(`⚠ No research.provider configured — wrote a stub for the host IDE to fill.`);
|
|
595
|
+
console.log(` ${result.filePath}`);
|
|
596
|
+
console.log(` Tip: set research.provider in ~/.analyzthis_design/config.json, or use WebSearch in Cursor.\n`);
|
|
597
|
+
} else {
|
|
598
|
+
console.log(`✅ Wrote ${result.chars} chars to ${result.filePath}\n`);
|
|
599
|
+
}
|
|
600
|
+
} else {
|
|
601
|
+
console.error('\n ✗ Provide --url <url> or --query <text>\n');
|
|
602
|
+
process.exit(1);
|
|
603
|
+
}
|
|
604
|
+
} catch (err) {
|
|
605
|
+
console.error(`\n ✗ Research failed: ${err.message}\n`);
|
|
606
|
+
process.exit(1);
|
|
607
|
+
}
|
|
608
|
+
})();
|
|
609
|
+
break;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// ── Mood board ───────────────────────────────────────────────────────────
|
|
613
|
+
|
|
614
|
+
case 'moodboard': {
|
|
615
|
+
const msub = flags.find((f) => !f.startsWith('--')) || 'create';
|
|
616
|
+
if (msub === 'create') {
|
|
617
|
+
if (!taskVal) {
|
|
618
|
+
console.error('\n ✗ --task is required. Example: npx analyzthis_design moodboard create --task "B2B fintech dashboard" --auto\n');
|
|
619
|
+
process.exit(1);
|
|
620
|
+
}
|
|
621
|
+
(async () => {
|
|
622
|
+
try {
|
|
623
|
+
const urls = [];
|
|
624
|
+
const raw = flags.filter((f) => f.startsWith('--url=')).map((f) => f.split('=').slice(1).join('='));
|
|
625
|
+
for (let i = 0; i < flags.length; i++) {
|
|
626
|
+
if (flags[i] === '--url' && flags[i + 1] && !flags[i + 1].startsWith('--')) urls.push(flags[i + 1]);
|
|
627
|
+
}
|
|
628
|
+
for (const u of raw) if (urls.indexOf(u) === -1) urls.push(u);
|
|
629
|
+
const result = await moodboard.buildMoodBoard({
|
|
630
|
+
project: projectVal,
|
|
631
|
+
task: taskVal,
|
|
632
|
+
urls: urls,
|
|
633
|
+
discover: autoFlag || urls.length > 0,
|
|
634
|
+
dryRun: dryRunFlag,
|
|
635
|
+
});
|
|
636
|
+
console.log(`\n✅ Mood board created: ${result.board.board_id}`);
|
|
637
|
+
console.log(` References: ${result.board.references.length}`);
|
|
638
|
+
console.log(` Board dir: ${result.boardDir}`);
|
|
639
|
+
console.log(` Workspace: ${result.workspacePath}\n`);
|
|
640
|
+
if (dryRunFlag) {
|
|
641
|
+
console.log(JSON.stringify(result.board, null, 2).slice(0, 2000));
|
|
642
|
+
console.log('');
|
|
643
|
+
}
|
|
644
|
+
} catch (err) {
|
|
645
|
+
console.error(`\n ✗ Mood board create failed: ${err.message}\n`);
|
|
646
|
+
process.exit(1);
|
|
647
|
+
}
|
|
648
|
+
})();
|
|
649
|
+
break;
|
|
650
|
+
}
|
|
651
|
+
if (msub === 'critique') {
|
|
652
|
+
if (!boardVal) {
|
|
653
|
+
console.error('\n ✗ --board is required. Example: npx analyzthis_design moodboard critique --board <id>\n');
|
|
654
|
+
process.exit(1);
|
|
655
|
+
}
|
|
656
|
+
(async () => {
|
|
657
|
+
try {
|
|
658
|
+
const result = await moodboard.critiqueMoodBoard({
|
|
659
|
+
project: projectVal,
|
|
660
|
+
boardId: boardVal,
|
|
661
|
+
provider: providerVal,
|
|
662
|
+
model: modelVal,
|
|
663
|
+
dryRun: dryRunFlag,
|
|
664
|
+
noDeliberate: noDeliberateFlag,
|
|
665
|
+
maxRounds: maxRoundsVal,
|
|
666
|
+
satisfaction: satisfactionVal,
|
|
667
|
+
});
|
|
668
|
+
console.log(`\n✅ Mood board critique complete: ${result.board.board_id}`);
|
|
669
|
+
console.log(` Verdict: ${result.board.synthesis?.verdict || 'n/a'}`);
|
|
670
|
+
console.log(` Rounds: ${result.board.deliberation?.round || 0}`);
|
|
671
|
+
console.log(` Board: ${result.boardDir || path.join(session.sessionDir(projectVal || session.getProjectId()), 'moodboard', boardVal)}`);
|
|
672
|
+
console.log(` Workspace: ${result.workspacePath}\n`);
|
|
673
|
+
} catch (err) {
|
|
674
|
+
if (err.name === 'HostLlmPendingError') {
|
|
675
|
+
hostLlm.printDeviInstructions(err);
|
|
676
|
+
process.exit(2);
|
|
677
|
+
}
|
|
678
|
+
console.error(`\n ✗ Mood board critique failed: ${err.message}\n`);
|
|
679
|
+
process.exit(1);
|
|
680
|
+
}
|
|
681
|
+
})();
|
|
682
|
+
break;
|
|
683
|
+
}
|
|
684
|
+
if (msub === 'add') {
|
|
685
|
+
if (!boardVal) {
|
|
686
|
+
console.error('\n ✗ --board is required. Example: npx analyzthis_design moodboard add --board <id> --url <url>\n');
|
|
687
|
+
process.exit(1);
|
|
688
|
+
}
|
|
689
|
+
(async () => {
|
|
690
|
+
try {
|
|
691
|
+
const tags = tagsVal ? tagsVal.split(',').map((t) => t.trim()).filter(Boolean) : [];
|
|
692
|
+
const result = await moodboard.addUserReferenceAndRerun({
|
|
693
|
+
project: projectVal,
|
|
694
|
+
boardId: boardVal,
|
|
695
|
+
reference: {
|
|
696
|
+
url: urlVal || '',
|
|
697
|
+
title: titleVal || '',
|
|
698
|
+
description: descVal || '',
|
|
699
|
+
tags: tags,
|
|
700
|
+
note: commentVal || '',
|
|
701
|
+
},
|
|
702
|
+
provider: providerVal,
|
|
703
|
+
model: modelVal,
|
|
704
|
+
dryRun: dryRunFlag,
|
|
705
|
+
noDeliberate: noDeliberateFlag,
|
|
706
|
+
maxRounds: maxRoundsVal,
|
|
707
|
+
satisfaction: satisfactionVal,
|
|
708
|
+
});
|
|
709
|
+
console.log(`\n✅ Added reference to board ${result.board.board_id}: ${result.added.id}`);
|
|
710
|
+
console.log(` Total references: ${result.board.references.length}`);
|
|
711
|
+
console.log(` Verdict: ${result.board.synthesis?.verdict || 'n/a'}\n`);
|
|
712
|
+
} catch (err) {
|
|
713
|
+
if (err.name === 'HostLlmPendingError') {
|
|
714
|
+
hostLlm.printDeviInstructions(err);
|
|
715
|
+
process.exit(2);
|
|
716
|
+
}
|
|
717
|
+
console.error(`\n ✗ Mood board add failed: ${err.message}\n`);
|
|
718
|
+
process.exit(1);
|
|
719
|
+
}
|
|
720
|
+
})();
|
|
721
|
+
break;
|
|
722
|
+
}
|
|
723
|
+
if (msub === 'list') {
|
|
724
|
+
const boards = moodboard.listBoards(projectVal);
|
|
725
|
+
if (!boards.length) {
|
|
726
|
+
console.log('\n No mood boards found for this project.\n');
|
|
727
|
+
} else {
|
|
728
|
+
console.log(`\n── Mood boards (${boards.length}) ──`);
|
|
729
|
+
for (const b of boards) console.log(` • ${b}`);
|
|
730
|
+
console.log('');
|
|
731
|
+
}
|
|
732
|
+
break;
|
|
733
|
+
}
|
|
734
|
+
console.error('\n Unknown moodboard subcommand. Use: create | critique | add | list\n');
|
|
735
|
+
process.exit(1);
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
// ── Retrieve-on-demand reference rows ───────────────────────────────────
|
|
739
|
+
|
|
740
|
+
case 'retrieve': {
|
|
741
|
+
if (!fileVal) {
|
|
742
|
+
console.error('\n ✗ --file is required. Example: npx analyzthis_design retrieve --file colors.csv --column "Product Type" --keywords saas\n');
|
|
743
|
+
process.exit(1);
|
|
744
|
+
}
|
|
745
|
+
try {
|
|
746
|
+
const keywords = keywordsVal ? keywordsVal.split(',').map(s => s.trim()).filter(Boolean) : [];
|
|
747
|
+
const filters = columnVal && keywords.length ? [{ column: columnVal, anyOf: keywords }] : [];
|
|
748
|
+
const limit = limitVal ? parseInt(limitVal, 10) : 3;
|
|
749
|
+
const result = retrieve.retrieve({ file: fileVal, filters, limit });
|
|
750
|
+
if (!result.rows.length) {
|
|
751
|
+
console.log(`\n No rows matched in ${fileVal}${columnVal ? ` for column "${columnVal}"` : ''}${keywords.length ? ` with keywords: ${keywords.join(', ')}` : ''}.\n`);
|
|
752
|
+
} else {
|
|
753
|
+
console.log(`\n📋 ${result.rows.length}/${result.matched} matching row(s) in ${fileVal}${result.cacheHit ? ' (cache hit)' : ''}:\n`);
|
|
754
|
+
for (const row of result.rows) {
|
|
755
|
+
console.log(` Row ${row.__no}:`);
|
|
756
|
+
for (const [k, v] of Object.entries(row)) {
|
|
757
|
+
if (k.startsWith('__') || !v) continue;
|
|
758
|
+
console.log(` ${k}: ${v}`);
|
|
759
|
+
}
|
|
760
|
+
console.log('');
|
|
761
|
+
}
|
|
762
|
+
if (columnVal) console.log(` Citation format: [${fileVal}, row N: "${columnVal} value"]\n`);
|
|
763
|
+
}
|
|
764
|
+
} catch (err) {
|
|
765
|
+
console.error(`\n ✗ ${err.message}\n`);
|
|
766
|
+
process.exit(1);
|
|
767
|
+
}
|
|
768
|
+
break;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
// ── Orchestrator run (chunked by default, v2.0) ───────────────────────────
|
|
772
|
+
|
|
773
|
+
case 'run': {
|
|
774
|
+
if (!taskVal) {
|
|
775
|
+
console.error('\n ✗ --task is required. Example: npx analyzthis_design run --task "Review onboarding flow" --budget free\n');
|
|
776
|
+
process.exit(1);
|
|
777
|
+
}
|
|
778
|
+
(async () => {
|
|
779
|
+
try {
|
|
780
|
+
const result = await orchestratorRun({
|
|
781
|
+
task: taskVal,
|
|
782
|
+
figma: figmaVal || '',
|
|
783
|
+
project: projectVal,
|
|
784
|
+
provider: providerVal,
|
|
785
|
+
model: modelVal,
|
|
786
|
+
dryRun: dryRunFlag,
|
|
787
|
+
budget: budgetVal || 'auto',
|
|
788
|
+
sequential: sequentialFlag || !flags.includes('--parallel'),
|
|
789
|
+
maxChunks: maxChunksVal ? parseInt(maxChunksVal, 10) : null,
|
|
790
|
+
unchunked: unchunkedFlag,
|
|
791
|
+
output: outputVal,
|
|
792
|
+
continueRun: continueFlag,
|
|
793
|
+
});
|
|
794
|
+
if (dryRunFlag) {
|
|
795
|
+
console.log('\n── Chunk plan (dry run) ──');
|
|
796
|
+
console.log(JSON.stringify(result.plan || result, null, 2).slice(0, 3000));
|
|
797
|
+
console.log('');
|
|
798
|
+
return;
|
|
799
|
+
}
|
|
800
|
+
if (result.mode === 'host_pending' || result.host_pending) {
|
|
801
|
+
const pending = result.host_pending;
|
|
802
|
+
console.log('\n╔══════════════════════════════════════════════════════════════════════╗');
|
|
803
|
+
console.log('║ DEVI — Host LLM pending (chunk planner) ║');
|
|
804
|
+
console.log('╚══════════════════════════════════════════════════════════════════════╝\n');
|
|
805
|
+
console.log(` Step: ${pending.step_id}`);
|
|
806
|
+
console.log(` Prompt file: ${path.join(pending.run_dir, 'pending', pending.step_id + '.json')}`);
|
|
807
|
+
console.log(` Run directory: ${pending.run_dir}`);
|
|
808
|
+
console.log('\n In Cursor, invoke: /devi');
|
|
809
|
+
console.log(' Or submit response:');
|
|
810
|
+
console.log(` npx analyzthis_design devi respond --run ${pending.run_dir} --step ${pending.step_id} --file response.md`);
|
|
811
|
+
console.log(' Then continue:');
|
|
812
|
+
console.log(` npx analyzthis_design run --continue --task "${taskVal}"\n`);
|
|
813
|
+
process.exit(2);
|
|
814
|
+
return;
|
|
815
|
+
}
|
|
816
|
+
} catch (err) {
|
|
817
|
+
if (err.name === 'HostLlmPendingError') {
|
|
818
|
+
hostLlm.printDeviInstructions(err);
|
|
819
|
+
process.exit(2);
|
|
820
|
+
}
|
|
821
|
+
console.error(`\n ✗ Run failed: ${err.message}\n`);
|
|
822
|
+
process.exit(1);
|
|
823
|
+
}
|
|
824
|
+
})();
|
|
825
|
+
break;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
case 'run-unchunked': {
|
|
829
|
+
let runTask = taskVal;
|
|
830
|
+
if (!runTask && continueFlag) {
|
|
831
|
+
const st = session.show({ project: projectVal });
|
|
832
|
+
runTask = st?.host_run?.task || hostLlm.loadManifest(st?.host_run?.run_dir || '')?.task || st?.digest?.task_map_summary;
|
|
833
|
+
}
|
|
834
|
+
if (!runTask) {
|
|
835
|
+
console.error('\n ✗ --task is required. Example: npx analyzthis_design run-unchunked --task "Fix contrast" --dry-run\n');
|
|
836
|
+
process.exit(1);
|
|
837
|
+
}
|
|
838
|
+
orchestratorRun({
|
|
839
|
+
task: runTask,
|
|
840
|
+
figma: figmaVal || '',
|
|
841
|
+
provider: providerVal,
|
|
842
|
+
model: modelVal,
|
|
843
|
+
dryRun: dryRunFlag,
|
|
844
|
+
lite: liteFlag,
|
|
845
|
+
full: fullFlag,
|
|
846
|
+
deliberate: deliberateFlag ? true : null,
|
|
847
|
+
noDeliberate: noDeliberateFlag,
|
|
848
|
+
maxRounds: maxRoundsVal,
|
|
849
|
+
satisfaction: satisfactionVal,
|
|
850
|
+
continueRun: continueFlag,
|
|
851
|
+
experts: expertsVal ? expertsVal.split(',').map((s) => s.trim()).filter(Boolean) : null,
|
|
852
|
+
project: projectVal,
|
|
853
|
+
output: outputVal,
|
|
854
|
+
unchunked: true,
|
|
855
|
+
}).catch((err) => {
|
|
856
|
+
if (err.name === 'HostLlmPendingError') process.exit(2);
|
|
857
|
+
console.error(`\n ✗ Run failed: ${err.message}\n`);
|
|
858
|
+
process.exit(1);
|
|
859
|
+
});
|
|
860
|
+
break;
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
case 'devi': {
|
|
864
|
+
const sub = flags[0];
|
|
865
|
+
if (sub === 'status') {
|
|
866
|
+
let runDir = runDirVal;
|
|
867
|
+
if (!runDir) {
|
|
868
|
+
const st = session.show({ project: projectVal });
|
|
869
|
+
runDir = st?.host_run?.run_dir || hostLlm.findLatestRun(st?.project_id || session.getProjectId())?.runDir;
|
|
870
|
+
}
|
|
871
|
+
if (!runDir || !fs.existsSync(runDir)) {
|
|
872
|
+
console.log('\n No host run found. Start one: npx analyzthis_design run --task "..." --full\n');
|
|
873
|
+
break;
|
|
874
|
+
}
|
|
875
|
+
const pending = hostLlm.listPending(runDir);
|
|
876
|
+
console.log(`\n📋 Devi — host run: ${runDir}\n`);
|
|
877
|
+
for (const p of pending) {
|
|
878
|
+
console.log(` ${p.hasResponse ? '✅' : '⏳'} ${p.stepId} (${p.personaId})`);
|
|
879
|
+
}
|
|
880
|
+
const waiting = pending.filter((p) => !p.hasResponse);
|
|
881
|
+
if (waiting.length) {
|
|
882
|
+
console.log(`\n ${waiting.length} pending — invoke /devi in Cursor or devi respond for each step.\n`);
|
|
883
|
+
} else {
|
|
884
|
+
console.log('\n All responses present — run: npx analyzthis_design run --continue --task "..."\n');
|
|
885
|
+
}
|
|
886
|
+
break;
|
|
887
|
+
}
|
|
888
|
+
if (sub === 'respond') {
|
|
889
|
+
if (!runDirVal || !stepVal || !fileVal) {
|
|
890
|
+
console.error('\n ✗ devi respond requires --run, --step, and --file\n');
|
|
891
|
+
process.exit(1);
|
|
892
|
+
}
|
|
893
|
+
const text = fs.readFileSync(path.resolve(fileVal), 'utf8');
|
|
894
|
+
hostLlm.submitResponse(path.resolve(runDirVal), stepVal, text);
|
|
895
|
+
console.log(`\n✅ Wrote response for ${stepVal}\n`);
|
|
896
|
+
break;
|
|
897
|
+
}
|
|
898
|
+
console.log('\n Usage: devi status | devi respond --run <dir> --step <id> --file <path>\n');
|
|
899
|
+
break;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
// ── Efficiency / cost metrics ────────────────────────────────────────────
|
|
903
|
+
|
|
904
|
+
case 'metrics': {
|
|
905
|
+
const projectIds = allFlag ? session.listProjects() : [projectVal || session.getProjectId()];
|
|
906
|
+
if (!projectIds.length) {
|
|
907
|
+
console.log('\n No sessions found.\n');
|
|
908
|
+
break;
|
|
909
|
+
}
|
|
910
|
+
console.log('\n📊 Last-run metrics\n');
|
|
911
|
+
for (const projectId of projectIds) {
|
|
912
|
+
const state = session.show({ project: projectId });
|
|
913
|
+
if (!state) continue;
|
|
914
|
+
const m = state.metrics || {};
|
|
915
|
+
console.log(` ${projectId}`);
|
|
916
|
+
console.log(` mode: ${m.mode ?? 'n/a'}`);
|
|
917
|
+
console.log(` llm_calls: ${m.llm_calls ?? 0}`);
|
|
918
|
+
console.log(` experts_run: ${(m.experts_run || []).join(', ') || 'none'}`);
|
|
919
|
+
console.log(` input_tokens_est: ${m.input_tokens_est ?? 0}`);
|
|
920
|
+
console.log(` output_tokens_est: ${m.output_tokens_est ?? 0}`);
|
|
921
|
+
console.log(` cache_hits: ${m.cache_hits ?? 0}`);
|
|
922
|
+
console.log(` deliberation_rounds: ${m.deliberation_rounds ?? 0}`);
|
|
923
|
+
console.log(` objections_raised: ${m.objections_raised ?? 0}`);
|
|
924
|
+
console.log(` objections_resolved: ${m.objections_resolved ?? 0}`);
|
|
925
|
+
console.log(` raj_escalations: ${m.raj_escalations ?? 0}`);
|
|
926
|
+
const d = state.deliberation;
|
|
927
|
+
if (d?.mode) {
|
|
928
|
+
console.log(` deliberation_mode: ${d.mode}, consensus=${d.consensus_reached}`);
|
|
929
|
+
}
|
|
930
|
+
console.log('');
|
|
931
|
+
}
|
|
932
|
+
break;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
// ── $-cost report (v1.10) ────────────────────────────────────────────────
|
|
936
|
+
|
|
937
|
+
case 'cost': {
|
|
938
|
+
cost.report({ project: projectVal, all: allFlag });
|
|
939
|
+
break;
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
// ── Persona feedback (v1.16) ────────────────────────────────────────────
|
|
943
|
+
|
|
944
|
+
case 'feedback': {
|
|
945
|
+
const sub = flags[0] || 'record';
|
|
946
|
+
if (sub === 'record') {
|
|
947
|
+
if (!personaVal) {
|
|
948
|
+
console.error('\n ✗ --persona is required.\n');
|
|
949
|
+
console.error(' Example: npx analyzthis_design feedback record --persona arjun --rating 2 \\\n');
|
|
950
|
+
console.error(' --comment "Invented tokens" --correction "Use tokens.css primary + spacing-4"\n');
|
|
951
|
+
process.exit(1);
|
|
952
|
+
}
|
|
953
|
+
const ratingNum = ratingVal != null ? Number(ratingVal) : undefined;
|
|
954
|
+
const satisfied = ratingNum != null ? ratingNum >= 4 : false;
|
|
955
|
+
try {
|
|
956
|
+
const result = feedback.recordFeedback({
|
|
957
|
+
project: projectVal,
|
|
958
|
+
persona: personaVal,
|
|
959
|
+
satisfied,
|
|
960
|
+
rating: ratingNum,
|
|
961
|
+
comment: commentVal || '',
|
|
962
|
+
correction: correctionVal || '',
|
|
963
|
+
tags: parseFeedbackTags(tagsVal),
|
|
964
|
+
markRejected: !satisfied,
|
|
965
|
+
});
|
|
966
|
+
console.log(`\n📝 Feedback recorded for "${personaVal}" (${result.entry.id}).`);
|
|
967
|
+
console.log(` Global log: ${result.globalFile}\n`);
|
|
968
|
+
} catch (err) {
|
|
969
|
+
console.error(`\n ✗ ${err.message}\n`);
|
|
970
|
+
process.exit(1);
|
|
971
|
+
}
|
|
972
|
+
break;
|
|
973
|
+
}
|
|
974
|
+
if (sub === 'list') {
|
|
975
|
+
const items = feedback.listFeedback({ project: projectVal, all: allFlag });
|
|
976
|
+
if (!items.length) {
|
|
977
|
+
console.log('\n No feedback entries yet.\n');
|
|
978
|
+
console.log(' Record one: npx analyzthis_design feedback record --persona arjun --rating 2 --comment "..."\n');
|
|
979
|
+
break;
|
|
980
|
+
}
|
|
981
|
+
console.log(`\n── Feedback (${items.length}) ───────────────────────────────`);
|
|
982
|
+
for (const e of items) {
|
|
983
|
+
const mood = e.satisfied ? '✅' : '⚠️';
|
|
984
|
+
const rating = e.rating != null ? ` rating=${e.rating}` : '';
|
|
985
|
+
const tags = e.tags?.length ? ` [${e.tags.join(', ')}]` : '';
|
|
986
|
+
const sent = e.submitted_at ? ' 📤' : '';
|
|
987
|
+
console.log(`${mood} ${e.at} ${e.persona}${rating}${tags}${sent}`);
|
|
988
|
+
if (e.comment) console.log(` comment: ${e.comment.slice(0, 120)}${e.comment.length > 120 ? '…' : ''}`);
|
|
989
|
+
if (e.correction) console.log(` correction: ${e.correction.slice(0, 120)}${e.correction.length > 120 ? '…' : ''}`);
|
|
990
|
+
}
|
|
991
|
+
console.log('');
|
|
992
|
+
break;
|
|
993
|
+
}
|
|
994
|
+
if (sub === 'export') {
|
|
995
|
+
try {
|
|
996
|
+
const result = feedback.exportCorrections({
|
|
997
|
+
persona: personaVal,
|
|
998
|
+
project: projectVal,
|
|
999
|
+
all: allFlag,
|
|
1000
|
+
output: outputVal,
|
|
1001
|
+
includePositive: includePositiveFlag,
|
|
1002
|
+
});
|
|
1003
|
+
console.log(`\n✅ Wrote ${result.pairs} correction pair(s) to ${result.filePath}`);
|
|
1004
|
+
if (!result.pairs) {
|
|
1005
|
+
console.log(' No entries with comment/correction found. Record feedback first.');
|
|
1006
|
+
console.log(` Tags hint: ${feedback.ISSUE_TAG_HINTS.slice(0, 6).join(', ')}, …`);
|
|
1007
|
+
}
|
|
1008
|
+
console.log('');
|
|
1009
|
+
} catch (err) {
|
|
1010
|
+
console.error(`\n ✗ ${err.message}\n`);
|
|
1011
|
+
process.exit(1);
|
|
1012
|
+
}
|
|
1013
|
+
break;
|
|
1014
|
+
}
|
|
1015
|
+
if (sub === 'submit') {
|
|
1016
|
+
(async () => {
|
|
1017
|
+
try {
|
|
1018
|
+
const result = await feedbackSubmit.submitFeedback({
|
|
1019
|
+
project: projectVal,
|
|
1020
|
+
all: allFlag,
|
|
1021
|
+
persona: personaVal,
|
|
1022
|
+
includePositive: includePositiveFlag,
|
|
1023
|
+
dryRun: dryRunFlag,
|
|
1024
|
+
yes: yesFlag,
|
|
1025
|
+
limit: limitVal,
|
|
1026
|
+
});
|
|
1027
|
+
if (result.cancelled) {
|
|
1028
|
+
console.log(`\n ${result.message}\n`);
|
|
1029
|
+
process.exit(0);
|
|
1030
|
+
}
|
|
1031
|
+
if (result.dryRun && result.payloads) {
|
|
1032
|
+
console.log(`\n── Dry run: ${result.payloads.length} row(s) ─────────────────`);
|
|
1033
|
+
console.log(` Endpoint: ${result.endpoint}`);
|
|
1034
|
+
console.log(JSON.stringify(result.payloads[0], null, 2));
|
|
1035
|
+
if (result.payloads.length > 1) {
|
|
1036
|
+
console.log(` … and ${result.payloads.length - 1} more`);
|
|
1037
|
+
}
|
|
1038
|
+
console.log('');
|
|
1039
|
+
return;
|
|
1040
|
+
}
|
|
1041
|
+
console.log(`\n✅ ${result.message}`);
|
|
1042
|
+
if (result.endpoint) console.log(` Endpoint: ${result.endpoint}`);
|
|
1043
|
+
console.log('');
|
|
1044
|
+
} catch (err) {
|
|
1045
|
+
console.error(`\n ✗ ${err.message}\n`);
|
|
1046
|
+
process.exit(1);
|
|
1047
|
+
}
|
|
1048
|
+
})();
|
|
1049
|
+
break;
|
|
1050
|
+
}
|
|
1051
|
+
if (sub === 'status') {
|
|
1052
|
+
const st = feedbackSubmit.submitStatus();
|
|
1053
|
+
console.log('\n── Feedback submit status ───────────────────────────');
|
|
1054
|
+
console.log(` Consent: ${st.consent}`);
|
|
1055
|
+
console.log(` Endpoint: ${st.endpoint}`);
|
|
1056
|
+
console.log(` Anon key: ${st.anonKey}`);
|
|
1057
|
+
console.log(` Unsent: ${st.unsentCount} entr${st.unsentCount === 1 ? 'y' : 'ies'}`);
|
|
1058
|
+
console.log(` Install id: ${st.installId} (anonymous)`);
|
|
1059
|
+
console.log(` Package: ${st.packageVersion}`);
|
|
1060
|
+
console.log('');
|
|
1061
|
+
break;
|
|
1062
|
+
}
|
|
1063
|
+
if (sub === 'revoke') {
|
|
1064
|
+
feedbackSubmit.revokeConsent();
|
|
1065
|
+
console.log('\n🛑 Opt-in consent revoked. Run feedback submit again to re-consent.\n');
|
|
1066
|
+
break;
|
|
1067
|
+
}
|
|
1068
|
+
console.error(`\nUnknown feedback subcommand: "${sub}". Use: record | list | export | submit | status | revoke\n`);
|
|
1069
|
+
process.exit(1);
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
// ── LoRA readiness: training-pair export (Phase 5, hook only) ──────────
|
|
1073
|
+
|
|
1074
|
+
case 'export-training': {
|
|
1075
|
+
if (!personaVal) {
|
|
1076
|
+
console.error('\n ✗ --persona is required. Example: npx analyzthis_design export-training --persona arjun\n');
|
|
1077
|
+
process.exit(1);
|
|
1078
|
+
}
|
|
1079
|
+
try {
|
|
1080
|
+
const result = exportTraining({ persona: personaVal, project: projectVal, all: allFlag, output: outputVal });
|
|
1081
|
+
console.log(`\n✅ Wrote ${result.pairs} accepted training pair(s) for "${personaVal}" to ${result.filePath}`);
|
|
1082
|
+
if (!result.pairs) {
|
|
1083
|
+
console.log(` No accepted outputs found. Mark one first: npx analyzthis_design session accept --persona ${personaVal}`);
|
|
1084
|
+
}
|
|
1085
|
+
console.log('');
|
|
1086
|
+
} catch (err) {
|
|
1087
|
+
console.error(`\n ✗ ${err.message}\n`);
|
|
1088
|
+
process.exit(1);
|
|
1089
|
+
}
|
|
1090
|
+
break;
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
case 'evolve': {
|
|
1094
|
+
const evolve = require('../lib/evolve');
|
|
1095
|
+
const windowArg = getFlag('window');
|
|
1096
|
+
const windowDays = windowArg ? parseInt(windowArg, 10) : 7;
|
|
1097
|
+
if (flags.includes('--extract')) {
|
|
1098
|
+
(async () => {
|
|
1099
|
+
try {
|
|
1100
|
+
const report = await evolve.runEvolution({ windowDays, dryRun: dryRunFlag });
|
|
1101
|
+
console.log('\n── Evolution report ' + (dryRunFlag ? '(dry run)' : '') + ' ──');
|
|
1102
|
+
console.log(' Lessons extracted: ' + report.extracted_lessons);
|
|
1103
|
+
console.log(' Outcomes inferred: ' + report.inferred_outcomes);
|
|
1104
|
+
console.log(' Prompt patches: ' + report.prompt_patches.length);
|
|
1105
|
+
console.log(' Reference proposals:' + report.reference_proposals.length);
|
|
1106
|
+
console.log(' Router patches: ' + report.router_patches.length);
|
|
1107
|
+
for (const p of report.prompt_patches) {
|
|
1108
|
+
console.log('\n Patch: ' + p.id + ' — ' + p.persona + ' — ' + p.description);
|
|
1109
|
+
}
|
|
1110
|
+
for (const p of report.reference_proposals) {
|
|
1111
|
+
console.log('\n Reference: ' + p.id + ' — ' + p.persona + ' — ' + p.description);
|
|
1112
|
+
}
|
|
1113
|
+
for (const p of report.router_patches) {
|
|
1114
|
+
console.log('\n Router: ' + p.id + ' — ' + p.task_type + ' → ' + p.suggested_route_to.join(', '));
|
|
1115
|
+
}
|
|
1116
|
+
console.log('');
|
|
1117
|
+
} catch (err) {
|
|
1118
|
+
console.error(`\n ✗ ${err.message}\n`);
|
|
1119
|
+
process.exit(1);
|
|
1120
|
+
}
|
|
1121
|
+
})();
|
|
1122
|
+
break;
|
|
1123
|
+
}
|
|
1124
|
+
if (flags.includes('--apply')) {
|
|
1125
|
+
const applyId = getFlag('apply');
|
|
1126
|
+
if (!applyId) {
|
|
1127
|
+
console.error('\n �� --apply requires a patch id\n');
|
|
1128
|
+
process.exit(1);
|
|
1129
|
+
}
|
|
1130
|
+
try {
|
|
1131
|
+
const result = evolve.applyPatch({ patchId: applyId, dryRun: dryRunFlag });
|
|
1132
|
+
if (result.preview) {
|
|
1133
|
+
console.log('\n── Dry-run patch preview ──');
|
|
1134
|
+
console.log(' Target: ' + result.targetFile);
|
|
1135
|
+
console.log(' Preview:\n' + result.preview.slice(0, 1200));
|
|
1136
|
+
} else {
|
|
1137
|
+
console.log('\n��� Patch ' + (result.applied ? 'applied' : 'previewed') + ': ' + applyId);
|
|
1138
|
+
if (result.targetFile) console.log(' Target: ' + result.targetFile);
|
|
1139
|
+
if (result.message) console.log(' Note: ' + result.message);
|
|
1140
|
+
}
|
|
1141
|
+
console.log('');
|
|
1142
|
+
} catch (err) {
|
|
1143
|
+
console.error(`\n �� ${err.message}\n`);
|
|
1144
|
+
process.exit(1);
|
|
1145
|
+
}
|
|
1146
|
+
break;
|
|
1147
|
+
}
|
|
1148
|
+
if (flags.includes('--metrics')) {
|
|
1149
|
+
const em = require('../lib/evolution-metrics');
|
|
1150
|
+
const m = em.computeEvolutionMetrics(projectVal);
|
|
1151
|
+
console.log('\n' + em.formatEvolutionSummary(m));
|
|
1152
|
+
break;
|
|
1153
|
+
}
|
|
1154
|
+
if (flags.includes('--ready')) {
|
|
1155
|
+
const em = require('../lib/evolution-metrics');
|
|
1156
|
+
const ready = em.checkEvolutionReady(projectVal);
|
|
1157
|
+
console.log('\n' + (ready.ready ? '[READY] ' : '[PENDING] ') + ready.reason);
|
|
1158
|
+
console.log('');
|
|
1159
|
+
console.log(em.formatEvolutionSummary(ready.metrics));
|
|
1160
|
+
break;
|
|
1161
|
+
}
|
|
1162
|
+
console.log('\n Usage: evolve --extract [--window N] [--dry-run] | evolve --apply <patchId> [--dry-run] | evolve --metrics | evolve --ready\n');
|
|
1163
|
+
break;
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
case 'outcome': {
|
|
1167
|
+
const outcome = require('../lib/outcome');
|
|
1168
|
+
if (flags.includes('--infer')) {
|
|
1169
|
+
const windowArg2 = getFlag('window');
|
|
1170
|
+
const wd = windowArg2 ? parseInt(windowArg2, 10) : 7;
|
|
1171
|
+
try {
|
|
1172
|
+
const result = outcome.inferAllOutcomes({ windowDays: wd });
|
|
1173
|
+
console.log('\n✅ Inferred ' + result.inferred + ' outcome(s), ' + result.confirmed + ' confirmed, ' + result.unknown + ' unknown.\n');
|
|
1174
|
+
} catch (err) {
|
|
1175
|
+
console.error(`\n ✗ ${err.message}\n`);
|
|
1176
|
+
process.exit(1);
|
|
1177
|
+
}
|
|
1178
|
+
break;
|
|
1179
|
+
}
|
|
1180
|
+
if (flags.includes('--pending')) {
|
|
1181
|
+
const pending = outcome.listPendingConfirmations();
|
|
1182
|
+
if (!pending.length) {
|
|
1183
|
+
console.log('\n No pending outcome confirmations.\n');
|
|
1184
|
+
} else {
|
|
1185
|
+
console.log('\n── Pending outcome confirmations (' + pending.length + ') ──');
|
|
1186
|
+
for (const p of pending) {
|
|
1187
|
+
console.log(' ' + p.project + ' / ' + p.persona + ': ' + p.inferred + ' (' + p.reason + ')');
|
|
1188
|
+
}
|
|
1189
|
+
console.log('');
|
|
1190
|
+
}
|
|
1191
|
+
break;
|
|
1192
|
+
}
|
|
1193
|
+
if (flags.includes('--confirm')) {
|
|
1194
|
+
if (!personaVal) {
|
|
1195
|
+
console.error('\n ✗ --persona is required for --confirm\n');
|
|
1196
|
+
process.exit(1);
|
|
1197
|
+
}
|
|
1198
|
+
const resultVal = getFlag('result');
|
|
1199
|
+
if (!resultVal) {
|
|
1200
|
+
console.error('\n ✗ --result is required (shipped | revised | blocked_correctly | missed)\n');
|
|
1201
|
+
process.exit(1);
|
|
1202
|
+
}
|
|
1203
|
+
try {
|
|
1204
|
+
outcome.confirmOutcome({ project: projectVal, persona: personaVal, outcome: resultVal });
|
|
1205
|
+
console.log('\n✅ Outcome confirmed: ' + personaVal + ' = ' + resultVal + '\n');
|
|
1206
|
+
} catch (err) {
|
|
1207
|
+
console.error(`\n ✗ ${err.message}\n`);
|
|
1208
|
+
process.exit(1);
|
|
1209
|
+
}
|
|
1210
|
+
break;
|
|
1211
|
+
}
|
|
1212
|
+
console.log('\n Usage: outcome --infer [--window N] | outcome --pending | outcome --confirm --persona X --result Y\n');
|
|
1213
|
+
break;
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
case '--help':
|
|
1217
|
+
case 'help':
|
|
1218
|
+
case '-h':
|
|
1219
|
+
console.log(HELP);
|
|
1220
|
+
break;
|
|
1221
|
+
|
|
1222
|
+
default:
|
|
1223
|
+
console.error(`\nUnknown command: "${cmd}"\n`);
|
|
1224
|
+
console.log(HELP);
|
|
1225
|
+
process.exit(1);
|
|
1226
|
+
}
|