@soleri/cli 1.9.0 → 1.10.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.
Files changed (93) hide show
  1. package/README.md +4 -0
  2. package/dist/commands/agent.d.ts +8 -0
  3. package/dist/commands/agent.js +150 -0
  4. package/dist/commands/agent.js.map +1 -0
  5. package/dist/commands/create.js +30 -4
  6. package/dist/commands/create.js.map +1 -1
  7. package/dist/commands/install-knowledge.js +65 -3
  8. package/dist/commands/install-knowledge.js.map +1 -1
  9. package/dist/commands/install.d.ts +2 -0
  10. package/dist/commands/install.js +80 -0
  11. package/dist/commands/install.js.map +1 -0
  12. package/dist/commands/pack.d.ts +10 -0
  13. package/dist/commands/pack.js +512 -0
  14. package/dist/commands/pack.js.map +1 -0
  15. package/dist/commands/skills.d.ts +8 -0
  16. package/dist/commands/skills.js +167 -0
  17. package/dist/commands/skills.js.map +1 -0
  18. package/dist/commands/uninstall.d.ts +2 -0
  19. package/dist/commands/uninstall.js +74 -0
  20. package/dist/commands/uninstall.js.map +1 -0
  21. package/dist/hook-packs/installer.d.ts +0 -7
  22. package/dist/hook-packs/installer.js +1 -14
  23. package/dist/hook-packs/installer.js.map +1 -1
  24. package/dist/hook-packs/installer.ts +1 -18
  25. package/dist/hook-packs/registry.d.ts +2 -1
  26. package/dist/hook-packs/registry.ts +1 -1
  27. package/dist/main.js +40 -1
  28. package/dist/main.js.map +1 -1
  29. package/dist/prompts/archetypes.d.ts +1 -0
  30. package/dist/prompts/archetypes.js +177 -62
  31. package/dist/prompts/archetypes.js.map +1 -1
  32. package/dist/prompts/create-wizard.js +98 -49
  33. package/dist/prompts/create-wizard.js.map +1 -1
  34. package/dist/prompts/playbook.d.ts +8 -7
  35. package/dist/prompts/playbook.js +201 -15
  36. package/dist/prompts/playbook.js.map +1 -1
  37. package/dist/utils/checks.d.ts +0 -1
  38. package/dist/utils/checks.js +1 -1
  39. package/dist/utils/checks.js.map +1 -1
  40. package/package.json +1 -1
  41. package/src/__tests__/archetypes.test.ts +84 -0
  42. package/src/__tests__/doctor.test.ts +2 -2
  43. package/src/__tests__/wizard-e2e.mjs +508 -0
  44. package/src/commands/agent.ts +181 -0
  45. package/src/commands/create.ts +146 -104
  46. package/src/commands/install-knowledge.ts +75 -4
  47. package/src/commands/install.ts +101 -0
  48. package/src/commands/pack.ts +585 -0
  49. package/src/commands/skills.ts +191 -0
  50. package/src/commands/uninstall.ts +93 -0
  51. package/src/hook-packs/installer.ts +1 -18
  52. package/src/hook-packs/registry.ts +1 -1
  53. package/src/main.ts +42 -1
  54. package/src/prompts/archetypes.ts +193 -62
  55. package/src/prompts/create-wizard.ts +114 -58
  56. package/src/prompts/playbook.ts +207 -21
  57. package/src/utils/checks.ts +1 -1
  58. package/code-reviewer/.claude/hookify.focus-ring-required.local.md +0 -21
  59. package/code-reviewer/.claude/hookify.no-ai-attribution.local.md +0 -18
  60. package/code-reviewer/.claude/hookify.no-any-types.local.md +0 -18
  61. package/code-reviewer/.claude/hookify.no-console-log.local.md +0 -21
  62. package/code-reviewer/.claude/hookify.no-important.local.md +0 -18
  63. package/code-reviewer/.claude/hookify.no-inline-styles.local.md +0 -21
  64. package/code-reviewer/.claude/hookify.semantic-html.local.md +0 -18
  65. package/code-reviewer/.claude/hookify.ux-touch-targets.local.md +0 -18
  66. package/code-reviewer/.mcp.json +0 -11
  67. package/code-reviewer/README.md +0 -346
  68. package/code-reviewer/package-lock.json +0 -4484
  69. package/code-reviewer/package.json +0 -45
  70. package/code-reviewer/scripts/copy-assets.js +0 -15
  71. package/code-reviewer/scripts/setup.sh +0 -130
  72. package/code-reviewer/skills/brainstorming/SKILL.md +0 -170
  73. package/code-reviewer/skills/code-patrol/SKILL.md +0 -176
  74. package/code-reviewer/skills/context-resume/SKILL.md +0 -143
  75. package/code-reviewer/skills/executing-plans/SKILL.md +0 -201
  76. package/code-reviewer/skills/fix-and-learn/SKILL.md +0 -164
  77. package/code-reviewer/skills/health-check/SKILL.md +0 -225
  78. package/code-reviewer/skills/second-opinion/SKILL.md +0 -142
  79. package/code-reviewer/skills/systematic-debugging/SKILL.md +0 -230
  80. package/code-reviewer/skills/verification-before-completion/SKILL.md +0 -170
  81. package/code-reviewer/skills/writing-plans/SKILL.md +0 -207
  82. package/code-reviewer/src/__tests__/facades.test.ts +0 -598
  83. package/code-reviewer/src/activation/activate.ts +0 -125
  84. package/code-reviewer/src/activation/claude-md-content.ts +0 -217
  85. package/code-reviewer/src/activation/inject-claude-md.ts +0 -113
  86. package/code-reviewer/src/extensions/index.ts +0 -47
  87. package/code-reviewer/src/extensions/ops/example.ts +0 -28
  88. package/code-reviewer/src/identity/persona.ts +0 -62
  89. package/code-reviewer/src/index.ts +0 -278
  90. package/code-reviewer/src/intelligence/data/architecture.json +0 -5
  91. package/code-reviewer/src/intelligence/data/code-review.json +0 -5
  92. package/code-reviewer/tsconfig.json +0 -30
  93. package/code-reviewer/vitest.config.ts +0 -23
@@ -1,278 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
4
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
5
- import { dirname, join } from 'node:path';
6
- import { fileURLToPath } from 'node:url';
7
-
8
- import {
9
- createAgentRuntime,
10
- createSemanticFacades,
11
- createDomainFacades,
12
- registerAllFacades,
13
- seedDefaultPlaybooks,
14
- wrapWithMiddleware,
15
- } from '@soleri/core';
16
- import type { OpDefinition, AgentExtensions } from '@soleri/core';
17
- import { z } from 'zod';
18
- import { PERSONA, getPersonaPrompt } from './identity/persona.js';
19
- import { activateAgent, deactivateAgent } from './activation/activate.js';
20
- import { injectClaudeMd, injectClaudeMdGlobal, hasAgentMarker } from './activation/inject-claude-md.js';
21
-
22
- const __dirname = dirname(fileURLToPath(import.meta.url));
23
-
24
- async function main(): Promise<void> {
25
- // ─── Runtime — vault, brain, planner, curator, LLM, key pools ───
26
- const runtime = createAgentRuntime({
27
- agentId: 'code-reviewer',
28
- dataDir: join(__dirname, 'intelligence', 'data'),
29
- });
30
-
31
- const tag = PERSONA.name.toLowerCase();
32
-
33
- // Seed built-in playbooks (idempotent)
34
- const seedResult = seedDefaultPlaybooks(runtime.vault);
35
- if (seedResult.seeded > 0) {
36
- console.error(`[${tag}] Seeded ${seedResult.seeded} built-in playbooks`);
37
- }
38
-
39
- const stats = runtime.vault.stats();
40
- console.error(`[${tag}] Vault: ${stats.totalEntries} entries, Brain: ${runtime.brain.getVocabularySize()} terms`);
41
-
42
- const llmAvail = runtime.llmClient.isAvailable();
43
- console.error(`[${tag}] LLM: OpenAI ${llmAvail.openai ? 'available' : 'not configured'}, Anthropic ${llmAvail.anthropic ? 'available' : 'not configured'}`);
44
-
45
- // ─── Agent-specific ops (reference persona + activation) ────────
46
- const agentOps: OpDefinition[] = [
47
- {
48
- name: 'health',
49
- description: 'Health check — vault status and agent info.',
50
- auth: 'read',
51
- handler: async () => {
52
- const s = runtime.vault.stats();
53
- return {
54
- status: 'ok',
55
- agent: { name: PERSONA.name, role: PERSONA.role },
56
- vault: { entries: s.totalEntries, domains: Object.keys(s.byDomain) },
57
- };
58
- },
59
- },
60
- {
61
- name: 'identity',
62
- description: 'Get agent identity — name, role, principles. Uses IdentityManager with PERSONA fallback.',
63
- auth: 'read',
64
- handler: async () => {
65
- const identity = runtime.identityManager.getIdentity('code-reviewer');
66
- if (identity) return identity;
67
- return PERSONA;
68
- },
69
- },
70
- {
71
- name: 'activate',
72
- description: 'Activate agent persona — returns full context for Claude to adopt. Say "Hello, Code Reviewer!" to trigger.',
73
- auth: 'read',
74
- schema: z.object({
75
- projectPath: z.string().optional().default('.'),
76
- deactivate: z.boolean().optional(),
77
- }),
78
- handler: async (params) => {
79
- if (params.deactivate) {
80
- return deactivateAgent();
81
- }
82
- // Seed identity from PERSONA on first activation
83
- if (!runtime.identityManager.getIdentity('code-reviewer')) {
84
- runtime.identityManager.setIdentity('code-reviewer', {
85
- name: PERSONA.name,
86
- role: PERSONA.role,
87
- description: PERSONA.description ?? '',
88
- personality: PERSONA.principles ?? [],
89
- changedBy: 'system',
90
- changeReason: 'Initial identity seeded from PERSONA',
91
- });
92
- }
93
- return activateAgent(runtime.vault, (params.projectPath as string) ?? '.', runtime.planner);
94
- },
95
- },
96
- {
97
- name: 'inject_claude_md',
98
- description: 'Inject agent sections into CLAUDE.md — project-level or global (~/.claude/CLAUDE.md). Idempotent.',
99
- auth: 'write',
100
- schema: z.object({
101
- projectPath: z.string().optional().default('.'),
102
- global: z.boolean().optional().describe('If true, inject into ~/.claude/CLAUDE.md instead of project-level'),
103
- }),
104
- handler: async (params) => {
105
- if (params.global) {
106
- return injectClaudeMdGlobal();
107
- }
108
- return injectClaudeMd((params.projectPath as string) ?? '.');
109
- },
110
- },
111
- {
112
- name: 'setup',
113
- description: 'Check setup status — CLAUDE.md configured? Vault has entries? What to do next?',
114
- auth: 'read',
115
- schema: z.object({
116
- projectPath: z.string().optional().default('.'),
117
- }),
118
- handler: async (params) => {
119
- const { existsSync } = await import('node:fs');
120
- const { join: joinPath } = await import('node:path');
121
- const { homedir } = await import('node:os');
122
- const projectPath = (params.projectPath as string) ?? '.';
123
-
124
- const projectClaudeMd = joinPath(projectPath, 'CLAUDE.md');
125
- const globalClaudeMd = joinPath(homedir(), '.claude', 'CLAUDE.md');
126
-
127
- const projectExists = existsSync(projectClaudeMd);
128
- const projectHasAgent = hasAgentMarker(projectClaudeMd);
129
- const globalExists = existsSync(globalClaudeMd);
130
- const globalHasAgent = hasAgentMarker(globalClaudeMd);
131
-
132
- const s = runtime.vault.stats();
133
-
134
- const recommendations: string[] = [];
135
- if (!globalHasAgent && !projectHasAgent) {
136
- recommendations.push('No CLAUDE.md configured — run inject_claude_md with global: true for all projects, or without for this project');
137
- } else if (!globalHasAgent) {
138
- recommendations.push('Global ~/.claude/CLAUDE.md not configured — run inject_claude_md with global: true to enable in all projects');
139
- }
140
- if (s.totalEntries === 0) {
141
- recommendations.push('Vault is empty — add intelligence data or capture knowledge via domain facades');
142
- }
143
-
144
- // Check hook status
145
- const { readdirSync } = await import('node:fs');
146
- const agentClaudeDir = joinPath(__dirname, '..', '.claude');
147
- const globalClaudeDir = joinPath(homedir(), '.claude');
148
-
149
- const hookStatus = { agent: [] as string[], global: [] as string[], missing: [] as string[] };
150
-
151
- if (existsSync(agentClaudeDir)) {
152
- try {
153
- const agentHooks = readdirSync(agentClaudeDir)
154
- .filter((f: string) => f.startsWith('hookify.') && f.endsWith('.local.md'))
155
- .map((f: string) => f.replace('hookify.', '').replace('.local.md', ''));
156
- hookStatus.agent = agentHooks;
157
-
158
- for (const hook of agentHooks) {
159
- if (existsSync(joinPath(globalClaudeDir, `hookify.${hook}.local.md`))) {
160
- hookStatus.global.push(hook);
161
- } else {
162
- hookStatus.missing.push(hook);
163
- }
164
- }
165
- } catch {
166
- // ignore read errors
167
- }
168
- }
169
-
170
- if (hookStatus.missing.length > 0) {
171
- recommendations.push(`${hookStatus.missing.length} hook(s) not installed globally — run scripts/setup.sh`);
172
- }
173
-
174
- if (recommendations.length === 0) {
175
- recommendations.push('Code Reviewer is fully set up and ready!');
176
- }
177
-
178
- return {
179
- agent: { name: PERSONA.name, role: PERSONA.role },
180
- claude_md: {
181
- project: { exists: projectExists, has_agent_section: projectHasAgent },
182
- global: { exists: globalExists, has_agent_section: globalHasAgent },
183
- },
184
- vault: { entries: s.totalEntries, domains: Object.keys(s.byDomain) },
185
- hooks: hookStatus,
186
- recommendations,
187
- };
188
- },
189
- },
190
- ];
191
-
192
- // ─── Assemble facades ──────────────────────────────────────────
193
- const semanticFacades = createSemanticFacades(runtime, 'code-reviewer');
194
- const agentFacade = {
195
- name: 'code-reviewer_core',
196
- description: 'Agent-specific operations — health, identity, activation, CLAUDE.md injection, setup.',
197
- ops: agentOps,
198
- };
199
-
200
- const domainFacades = createDomainFacades(runtime, 'code-reviewer', ["code-review","architecture"]);
201
-
202
- // ─── User extensions (auto-discovered from src/extensions/) ────
203
- let extensions: AgentExtensions = {};
204
- try {
205
- const ext = await import('./extensions/index.js');
206
- const loader = ext.default ?? (ext as Record<string, unknown>).loadExtensions;
207
- if (typeof loader === 'function') {
208
- extensions = loader(runtime);
209
- } else if (typeof loader === 'object') {
210
- extensions = loader;
211
- }
212
- if (extensions.ops?.length || extensions.facades?.length || extensions.middleware?.length) {
213
- console.error(`[${tag}] Extensions loaded: ${extensions.ops?.length ?? 0} ops, ${extensions.facades?.length ?? 0} facades, ${extensions.middleware?.length ?? 0} middleware`);
214
- }
215
- } catch {
216
- // No extensions directory or load error — run vanilla
217
- }
218
-
219
- // Merge user ops into agent facade
220
- if (extensions.ops?.length) {
221
- agentFacade.ops.push(...extensions.ops);
222
- }
223
-
224
- // Collect user facades
225
- const userFacades = extensions.facades ?? [];
226
-
227
- // Apply middleware to all facades
228
- const allFacades = [...semanticFacades, agentFacade, ...domainFacades, ...userFacades];
229
- if (extensions.middleware?.length) {
230
- wrapWithMiddleware(allFacades, extensions.middleware);
231
- }
232
-
233
- // Lifecycle: onStartup
234
- if (extensions.hooks?.onStartup) {
235
- await extensions.hooks.onStartup(runtime);
236
- }
237
-
238
- // ─── MCP server ────────────────────────────────────────────────
239
- const server = new McpServer({
240
- name: 'code-reviewer-mcp',
241
- version: '1.0.0',
242
- });
243
-
244
- server.prompt('persona', 'Get agent persona and principles', async () => ({
245
- messages: [{ role: 'assistant' as const, content: { type: 'text' as const, text: getPersonaPrompt() } }],
246
- }));
247
-
248
- registerAllFacades(server, allFacades);
249
-
250
- console.error(`[${tag}] ${PERSONA.name} — ${PERSONA.role}`);
251
- console.error(`[${tag}] Registered ${allFacades.length} facades with ${allFacades.reduce((sum, f) => sum + f.ops.length, 0)} operations`);
252
-
253
- // ─── Transport + shutdown ──────────────────────────────────────
254
- const transport = new StdioServerTransport();
255
- await server.connect(transport);
256
- console.error(`[${tag}] Connected via stdio transport`);
257
- console.error(`[${tag}] Say "Hello, ${PERSONA.name}!" to activate`);
258
-
259
- const shutdown = async (): Promise<void> => {
260
- console.error(`[${tag}] Shutting down...`);
261
- if (extensions.hooks?.onShutdown) {
262
- try {
263
- await extensions.hooks.onShutdown(runtime);
264
- } catch (err) {
265
- console.error(`[${tag}] Extension shutdown error:`, err);
266
- }
267
- }
268
- runtime.close();
269
- process.exit(0);
270
- };
271
- process.on('SIGTERM', shutdown);
272
- process.on('SIGINT', shutdown);
273
- }
274
-
275
- main().catch((err) => {
276
- console.error('[code-reviewer] Fatal error:', err);
277
- process.exit(1);
278
- });
@@ -1,5 +0,0 @@
1
- {
2
- "domain": "architecture",
3
- "version": "1.0.0",
4
- "entries": []
5
- }
@@ -1,5 +0,0 @@
1
- {
2
- "domain": "code-review",
3
- "version": "1.0.0",
4
- "entries": []
5
- }
@@ -1,30 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "NodeNext",
5
- "moduleResolution": "NodeNext",
6
- "lib": [
7
- "ES2022"
8
- ],
9
- "outDir": "dist",
10
- "rootDir": "src",
11
- "strict": true,
12
- "esModuleInterop": true,
13
- "resolveJsonModule": true,
14
- "declaration": true,
15
- "declarationMap": true,
16
- "sourceMap": true,
17
- "forceConsistentCasingInFileNames": true,
18
- "skipLibCheck": true,
19
- "noEmitOnError": true
20
- },
21
- "include": [
22
- "src/**/*.ts"
23
- ],
24
- "exclude": [
25
- "node_modules",
26
- "dist",
27
- "src/**/*.test.ts",
28
- "src/__tests__/**"
29
- ]
30
- }
@@ -1,23 +0,0 @@
1
- import { defineConfig } from 'vitest/config';
2
-
3
- export default defineConfig({
4
- test: {
5
- environment: 'node',
6
- pool: 'forks',
7
- poolOptions: {
8
- forks: {
9
- singleFork: true,
10
- maxForks: 2,
11
- minForks: 1,
12
- },
13
- },
14
- testTimeout: 30_000,
15
- hookTimeout: 10_000,
16
- teardownTimeout: 5_000,
17
- coverage: {
18
- provider: 'v8',
19
- include: ['src/**/*.ts'],
20
- exclude: ['src/**/*.test.ts', 'src/__tests__/**', 'src/index.ts'],
21
- },
22
- },
23
- });