@jaggerxtrm/specialists 3.5.0 → 3.6.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 +12 -1
- package/config/hooks/specialists-session-start.mjs +105 -0
- package/config/nodes/research-multi.node.json +11 -0
- package/config/nodes/research.node.json +27 -0
- package/config/presets.json +26 -0
- package/config/skills/specialists-creator/SKILL.md +323 -145
- package/config/skills/specialists-creator/scripts/scaffold-specialist.ts +228 -0
- package/config/skills/using-nodes/SKILL.md +333 -0
- package/config/skills/using-specialists/SKILL.md +843 -173
- package/config/specialists/debugger.specialist.json +74 -0
- package/config/specialists/executor.specialist.json +117 -0
- package/config/specialists/explorer.specialist.json +82 -0
- package/config/specialists/memory-processor.specialist.json +65 -0
- package/config/specialists/node-coordinator.specialist.json +64 -0
- package/config/specialists/overthinker.specialist.json +65 -0
- package/config/specialists/parallel-review.specialist.json +65 -0
- package/config/specialists/planner.specialist.json +93 -0
- package/config/specialists/researcher.specialist.json +65 -0
- package/config/specialists/reviewer.specialist.json +60 -0
- package/config/specialists/specialists-creator.specialist.json +68 -0
- package/config/specialists/sync-docs.specialist.json +80 -0
- package/config/specialists/test-runner.specialist.json +67 -0
- package/config/specialists/xt-merge.specialist.json +60 -0
- package/dist/index.js +13818 -2743
- package/package.json +6 -3
- package/config/specialists/debugger.specialist.yaml +0 -121
- package/config/specialists/executor.specialist.yaml +0 -257
- package/config/specialists/explorer.specialist.yaml +0 -85
- package/config/specialists/memory-processor.specialist.yaml +0 -154
- package/config/specialists/overthinker.specialist.yaml +0 -76
- package/config/specialists/parallel-review.specialist.yaml +0 -75
- package/config/specialists/planner.specialist.yaml +0 -94
- package/config/specialists/reviewer.specialist.yaml +0 -142
- package/config/specialists/specialists-creator.specialist.yaml +0 -90
- package/config/specialists/sync-docs.specialist.yaml +0 -68
- package/config/specialists/test-runner.specialist.yaml +0 -65
- package/config/specialists/xt-merge.specialist.yaml +0 -159
package/README.md
CHANGED
|
@@ -40,6 +40,13 @@ specialists feed -f
|
|
|
40
40
|
bd close <id> --reason "Done"
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
+
Merge worktree branches:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
specialists merge <bead-id> # single chain or epic (topological)
|
|
47
|
+
specialists merge <bead-id> --rebuild # rebuild after merge
|
|
48
|
+
```
|
|
49
|
+
|
|
43
50
|
`specialists run` prints `[job started: <id>]` early and also writes the id to `.specialists/jobs/latest`.
|
|
44
51
|
|
|
45
52
|
Ad-hoc work:
|
|
@@ -81,6 +88,7 @@ specialists doctor
|
|
|
81
88
|
| xtrm / worktree integration | [docs/worktree.md](docs/worktree.md) |
|
|
82
89
|
| RPC mode notes | [docs/pi-rpc.md](docs/pi-rpc.md) |
|
|
83
90
|
| Pi subprocess isolation and extensions | [docs/pi-session.md](docs/pi-session.md) |
|
|
91
|
+
| NodeSupervisor architecture, node lifecycle, and `sp node` CLI | [docs/nodes.md](docs/nodes.md) |
|
|
84
92
|
|
|
85
93
|
## Project structure
|
|
86
94
|
|
|
@@ -125,11 +133,14 @@ Use `specialists init` instead.
|
|
|
125
133
|
|
|
126
134
|
```bash
|
|
127
135
|
bun run build
|
|
128
|
-
bun test
|
|
136
|
+
bun test # bun vitest run (default)
|
|
137
|
+
bun run test:node # node vitest run (subprocess-safe alternative)
|
|
129
138
|
specialists help
|
|
130
139
|
specialists quickstart
|
|
131
140
|
```
|
|
132
141
|
|
|
142
|
+
`test:node` uses plain `node vitest run` as an alternative to `bun --bun vitest`. Useful for executor/codex subprocess chains that may trigger stall detection during vitest's tinypool worker initialization silence.
|
|
143
|
+
|
|
133
144
|
## License
|
|
134
145
|
|
|
135
146
|
MIT
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// specialists-session-start — Claude Code SessionStart hook
|
|
3
|
+
// Injects specialists context at the start of every session:
|
|
4
|
+
// • Active background jobs (if any)
|
|
5
|
+
// • Available specialists list
|
|
6
|
+
// • Key CLI commands reminder
|
|
7
|
+
//
|
|
8
|
+
// Installed by: specialists init
|
|
9
|
+
// Hook type: SessionStart
|
|
10
|
+
|
|
11
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
12
|
+
import { join } from 'node:path';
|
|
13
|
+
import { homedir } from 'node:os';
|
|
14
|
+
|
|
15
|
+
const cwd = process.env.CLAUDE_PROJECT_DIR ?? process.cwd();
|
|
16
|
+
const HOME = homedir();
|
|
17
|
+
const jobsDir = join(cwd, '.specialists', 'jobs');
|
|
18
|
+
const lines = [];
|
|
19
|
+
|
|
20
|
+
// ── 1. Active background jobs ──────────────────────────────────────────────
|
|
21
|
+
if (existsSync(jobsDir)) {
|
|
22
|
+
let entries = [];
|
|
23
|
+
try { entries = readdirSync(jobsDir); } catch { /* ignore */ }
|
|
24
|
+
|
|
25
|
+
const activeJobs = [];
|
|
26
|
+
for (const jobId of entries) {
|
|
27
|
+
const statusPath = join(jobsDir, jobId, 'status.json');
|
|
28
|
+
if (!existsSync(statusPath)) continue;
|
|
29
|
+
try {
|
|
30
|
+
const s = JSON.parse(readFileSync(statusPath, 'utf-8'));
|
|
31
|
+
if (s.status === 'running' || s.status === 'starting') {
|
|
32
|
+
const elapsed = s.elapsed_s !== undefined ? ` (${s.elapsed_s}s)` : '';
|
|
33
|
+
activeJobs.push(
|
|
34
|
+
` • ${s.specialist ?? jobId} [${s.status}]${elapsed} → specialists result ${jobId}`
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
} catch { /* malformed status.json */ }
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (activeJobs.length > 0) {
|
|
41
|
+
lines.push('## Specialists — Active Background Jobs');
|
|
42
|
+
lines.push('');
|
|
43
|
+
lines.push(...activeJobs);
|
|
44
|
+
lines.push('');
|
|
45
|
+
lines.push('Use `specialists feed <job-id> --follow` to stream events, or `specialists result <job-id>` when done.');
|
|
46
|
+
lines.push('');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ── 2. Available specialists (read YAML dirs directly) ────────────────────
|
|
51
|
+
function readSpecialistNames(dir) {
|
|
52
|
+
if (!existsSync(dir)) return [];
|
|
53
|
+
try {
|
|
54
|
+
return readdirSync(dir)
|
|
55
|
+
.filter(f => f.endsWith('.specialist.yaml'))
|
|
56
|
+
.map(f => f.replace('.specialist.yaml', ''));
|
|
57
|
+
} catch {
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const projectNames = readSpecialistNames(join(cwd, 'specialists'));
|
|
63
|
+
const userNames = readSpecialistNames(join(HOME, '.agents', 'specialists'));
|
|
64
|
+
|
|
65
|
+
// Merge, deduplicate, sort
|
|
66
|
+
const allNames = [...new Set([...projectNames, ...userNames])].sort();
|
|
67
|
+
|
|
68
|
+
if (allNames.length > 0) {
|
|
69
|
+
lines.push('## Specialists — Available');
|
|
70
|
+
lines.push('');
|
|
71
|
+
if (projectNames.length > 0) {
|
|
72
|
+
lines.push(`project (${projectNames.length}): ${projectNames.join(', ')}`);
|
|
73
|
+
}
|
|
74
|
+
if (userNames.length > 0) {
|
|
75
|
+
// Only show user-scope names not already in project
|
|
76
|
+
const extraUser = userNames.filter(n => !projectNames.includes(n));
|
|
77
|
+
if (extraUser.length > 0) {
|
|
78
|
+
lines.push(`user (${extraUser.length}): ${extraUser.join(', ')}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
lines.push('');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// ── 3. Key commands reminder ───────────────────────────────────────────────
|
|
85
|
+
lines.push('## Specialists — Session Quick Reference');
|
|
86
|
+
lines.push('');
|
|
87
|
+
lines.push('```');
|
|
88
|
+
lines.push('specialists list # discover available specialists');
|
|
89
|
+
lines.push('specialists run <name> --prompt "..." # run foreground (streams output)');
|
|
90
|
+
lines.push('specialists run <name> --prompt "..." # run; job ID prints on stderr');
|
|
91
|
+
lines.push('specialists feed <job-id> --follow # tail live events');
|
|
92
|
+
lines.push('specialists result <job-id> # read final output');
|
|
93
|
+
lines.push('specialists status # system health');
|
|
94
|
+
lines.push('specialists doctor # troubleshoot issues');
|
|
95
|
+
lines.push('```');
|
|
96
|
+
lines.push('');
|
|
97
|
+
lines.push('MCP tools: use_specialist (foreground only)');
|
|
98
|
+
|
|
99
|
+
// ── Output ─────────────────────────────────────────────────────────────────
|
|
100
|
+
if (lines.length === 0) process.exit(0);
|
|
101
|
+
|
|
102
|
+
process.stdout.write(JSON.stringify({
|
|
103
|
+
type: 'inject',
|
|
104
|
+
content: lines.join('\n'),
|
|
105
|
+
}) + '\n');
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "research-multi",
|
|
3
|
+
"coordinator": "node-coordinator",
|
|
4
|
+
"members": [],
|
|
5
|
+
"initialPrompt": "You are coordinating a multi-researcher discovery node. There are NO pre-spawned members — you must spawn all members yourself via sp node spawn-member.\n\nYour mission: gather deep, wide research across both the codebase and online sources, then synthesize.\n\nOrchestration plan:\n\nPhase 1 — parallel discovery (spawn all at once, then wait-phase):\n - explorer-1: codebase explorer — map the current context injection pipeline (what gets injected at specialist spawn, where bd prime runs, how runner.ts builds the prompt, what gitnexus cheatsheet injection looks like, token costs)\n - researcher-1: search for agent/LLM context efficiency patterns — how do frontier agent frameworks (LangMem, MemGPT, AgentOS, CrewAI) handle memory retrieval and context injection? token budget strategies?\n - researcher-2: search for bun:sqlite FTS5 and vector/embedding search capabilities — can bun:sqlite do semantic search? what scoring approaches work for memory retrieval without embeddings? SQLite FTS5 rank() function?\n - researcher-3: search for specialist memory system patterns across GitHub — find real implementations of agent memory stores, typed retrieval, decay/scoring. Use ghgrep to find patterns.\n\nPhase 2 — synthesis (spawn after phase 1 evidence is in):\n - overthinker-1: deep analysis of the research findings — design the optimal bd prime filtering strategy and the specialist memory SQLite schema. Critique assumptions. Synthesize across all phase 1 findings.\n\nExecution rules:\n - Spawn all 4 phase-1 members simultaneously, then call wait-phase with all 4 member keys.\n - After wait-phase completes, read ALL member results with sp node result before spawning overthinker.\n - Do not advance to phase 2 until you have read every phase 1 result.\n - After overthinker completes, read its result and synthesize final recommendations, then remain in waiting for operator closure.",
|
|
6
|
+
"memoryNamespace": "research-multi",
|
|
7
|
+
"completion_strategy": "manual",
|
|
8
|
+
"max_retries": 3,
|
|
9
|
+
"default_context_depth": 1,
|
|
10
|
+
"base_branch": "master"
|
|
11
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "research",
|
|
3
|
+
"coordinator": "node-coordinator",
|
|
4
|
+
"members": [
|
|
5
|
+
{
|
|
6
|
+
"memberId": "explorer",
|
|
7
|
+
"specialist": "explorer",
|
|
8
|
+
"role": "Codebase exploration and discovery. Read files, search code, map architecture. Report findings."
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"memberId": "overthinker",
|
|
12
|
+
"specialist": "overthinker",
|
|
13
|
+
"role": "Deep multi-phase analysis. Reason about tradeoffs, critique assumptions, synthesize insights."
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"memberId": "researcher",
|
|
17
|
+
"specialist": "researcher",
|
|
18
|
+
"role": "Documentation and code researcher. Targeted lookup via ctx7/deepwiki CLIs, or discovery mode via ghgrep to find real-world patterns across GitHub. Report findings with code examples."
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"initialPrompt": "You are coordinating a research node with an explorer, an overthinker, and a researcher. Plan an explicit explore phase first, then wait for the phase barrier, read every member result, synthesize the evidence, and decide whether a design or implementation phase is actually needed. On start, launch the explorer for codebase findings. Use the researcher only when external docs or ecosystem patterns are needed. Use the overthinker after evidence is gathered to analyze tradeoffs and synthesize insights. Maintain memory_patch entries (facts, questions, decisions) throughout.",
|
|
22
|
+
"memoryNamespace": "research",
|
|
23
|
+
"completion_strategy": "pr",
|
|
24
|
+
"max_retries": 3,
|
|
25
|
+
"default_context_depth": 1,
|
|
26
|
+
"base_branch": "master"
|
|
27
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cheap": {
|
|
3
|
+
"description": "Low-cost, fast responses — best for exploration and simple tasks",
|
|
4
|
+
"fields": {
|
|
5
|
+
"specialist.execution.model": "dashscope/qwen3.5-plus",
|
|
6
|
+
"specialist.execution.thinking_level": "off",
|
|
7
|
+
"specialist.execution.stall_timeout_ms": 60000
|
|
8
|
+
}
|
|
9
|
+
},
|
|
10
|
+
"medium": {
|
|
11
|
+
"description": "Balanced cost/quality — good default for most tasks",
|
|
12
|
+
"fields": {
|
|
13
|
+
"specialist.execution.model": "anthropic/claude-sonnet-4-6",
|
|
14
|
+
"specialist.execution.thinking_level": "low",
|
|
15
|
+
"specialist.execution.stall_timeout_ms": 120000
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"power": {
|
|
19
|
+
"description": "Maximum capability — complex implementation and reasoning",
|
|
20
|
+
"fields": {
|
|
21
|
+
"specialist.execution.model": "openai-codex/gpt-5.4",
|
|
22
|
+
"specialist.execution.thinking_level": "high",
|
|
23
|
+
"specialist.execution.stall_timeout_ms": 300000
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|