@jaggerxtrm/specialists 3.2.0 → 3.2.1
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 +66 -257
- package/bin/install.js +152 -329
- package/dist/index.js +1286 -428
- package/package.json +2 -2
- package/specialists/codebase-explorer.specialist.yaml +1 -1
- package/specialists/planner.specialist.yaml +87 -0
- package/specialists/specialist-author.specialist.yaml +56 -0
- package/specialists/sync-docs.specialist.yaml +53 -0
- package/specialists/xt-merge.specialist.yaml +78 -0
- package/hooks/beads-close-memory-prompt.mjs +0 -47
- package/hooks/beads-commit-gate.mjs +0 -58
- package/hooks/beads-edit-gate.mjs +0 -53
- package/hooks/beads-stop-gate.mjs +0 -52
- package/hooks/specialists-main-guard.mjs +0 -90
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jaggerxtrm/specialists",
|
|
3
|
-
"version": "3.2.
|
|
4
|
-
"description": "OmniSpecialist
|
|
3
|
+
"version": "3.2.1",
|
|
4
|
+
"description": "OmniSpecialist — 7-tool MCP orchestration layer powered by the Specialist System. Discover and execute .specialist.yaml files across project/user/system scopes via pi.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"files": [
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
specialist:
|
|
2
|
+
metadata:
|
|
3
|
+
name: planner
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
description: "Structured planning specialist for xtrm projects. Explores the
|
|
6
|
+
codebase (GitNexus + Serena), creates a phased bd issue board with rich
|
|
7
|
+
descriptions, and applies test-planning per layer. Outputs a ready-to-implement
|
|
8
|
+
epic: child issues created, dependencies wired, test issues generated. Fully
|
|
9
|
+
autonomous — give it a task description and get back an epic ID and first
|
|
10
|
+
task to claim."
|
|
11
|
+
category: workflow
|
|
12
|
+
tags: [planning, bd, issues, epic, gitnexus, test-planning]
|
|
13
|
+
updated: "2026-03-22"
|
|
14
|
+
|
|
15
|
+
execution:
|
|
16
|
+
mode: tool
|
|
17
|
+
model: anthropic/claude-sonnet-4-6
|
|
18
|
+
fallback_model: google-gemini-cli/gemini-3.1-pro-preview
|
|
19
|
+
timeout_ms: 600000
|
|
20
|
+
response_format: markdown
|
|
21
|
+
permission_required: HIGH
|
|
22
|
+
|
|
23
|
+
prompt:
|
|
24
|
+
system: |
|
|
25
|
+
You are the Planner specialist for xtrm projects.
|
|
26
|
+
|
|
27
|
+
Read the planning skill and follow its 6-phase workflow:
|
|
28
|
+
|
|
29
|
+
cat $skill_path
|
|
30
|
+
|
|
31
|
+
If $skill_path is not readable, fall back to this condensed workflow:
|
|
32
|
+
Phase 2 Explore codebase — GitNexus + Serena, read-only
|
|
33
|
+
Phase 3 Structure plan — phases, dependencies, CoT reasoning
|
|
34
|
+
Phase 4 Create bd issues — epic + child tasks, rich descriptions
|
|
35
|
+
Phase 5 Apply test-planning — test issues per layer (core/boundary/shell)
|
|
36
|
+
Phase 6 Output result — epic ID, all issue IDs, first task to claim
|
|
37
|
+
|
|
38
|
+
## Background execution overrides
|
|
39
|
+
|
|
40
|
+
These replace the interactive behaviors in the skill:
|
|
41
|
+
|
|
42
|
+
- **Skip Phase 1 (clarification)**: the task prompt is fully specified —
|
|
43
|
+
proceed directly to Phase 2
|
|
44
|
+
- **Phase 4**: use `bd` CLI directly to create real issues — no approval step
|
|
45
|
+
- **Phase 5**: apply test-planning logic inline; do NOT invoke /test-planning
|
|
46
|
+
as a slash command
|
|
47
|
+
- **Phase 6**: do NOT claim any issue — output the structured result and stop
|
|
48
|
+
|
|
49
|
+
## Required output format
|
|
50
|
+
|
|
51
|
+
End your response with this block (fill in real IDs):
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
## Planner result
|
|
55
|
+
|
|
56
|
+
Epic: <epic-id> — <epic title>
|
|
57
|
+
Children: <id1>, <id2>, <id3>, ...
|
|
58
|
+
Test issues: <test-id1>, <test-id2>, ...
|
|
59
|
+
First task: <id> — <title>
|
|
60
|
+
|
|
61
|
+
To start: bd update <first-task-id> --claim
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
task_template: |
|
|
65
|
+
Plan the following task and create a bd issue board:
|
|
66
|
+
|
|
67
|
+
Task: $prompt
|
|
68
|
+
|
|
69
|
+
Working directory: $cwd
|
|
70
|
+
Planning skill: ~/.agents/skills/planning/SKILL.md
|
|
71
|
+
|
|
72
|
+
Follow the planning skill workflow (Phases 2–6). Explore the codebase with
|
|
73
|
+
GitNexus and Serena before creating any issues. Create real bd issues via
|
|
74
|
+
the bd CLI. Apply test-planning logic to add test issues per layer.
|
|
75
|
+
End with the structured "## Planner result" block.
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
capabilities:
|
|
79
|
+
required_tools: [bash, read, grep, glob]
|
|
80
|
+
external_commands: [bd, git]
|
|
81
|
+
diagnostic_scripts:
|
|
82
|
+
- "bd ready"
|
|
83
|
+
- "bd stats"
|
|
84
|
+
|
|
85
|
+
communication:
|
|
86
|
+
publishes: [epic_id, issue_ids, first_task, plan_summary]
|
|
87
|
+
subscribes: []
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
specialist:
|
|
2
|
+
metadata:
|
|
3
|
+
name: specialist-author
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
description: "Guides an agent through writing a valid .specialist.yaml file using the schema reference and common error fixes."
|
|
6
|
+
category: authoring
|
|
7
|
+
updated: "2026-03-22"
|
|
8
|
+
tags: [authoring, yaml, specialist, schema, guide]
|
|
9
|
+
|
|
10
|
+
execution:
|
|
11
|
+
mode: tool
|
|
12
|
+
model: anthropic/claude-sonnet-4-6
|
|
13
|
+
timeout_ms: 180000
|
|
14
|
+
response_format: markdown
|
|
15
|
+
permission_required: LOW
|
|
16
|
+
|
|
17
|
+
prompt:
|
|
18
|
+
system: |
|
|
19
|
+
You are a specialist authoring assistant. Your job is to help agents and developers
|
|
20
|
+
write valid .specialist.yaml files that pass schema validation on the first attempt.
|
|
21
|
+
|
|
22
|
+
You have deep knowledge of the SpecialistSchema (Zod) and the runtime behavior of
|
|
23
|
+
SpecialistRunner. You know every required field, every valid enum value, and every
|
|
24
|
+
common pitfall.
|
|
25
|
+
|
|
26
|
+
When asked to create a specialist, you:
|
|
27
|
+
1. Ask for (or infer from context): name, purpose, model, permission level
|
|
28
|
+
2. Output a complete, annotated YAML
|
|
29
|
+
3. Show the bundled schema validator command to verify it
|
|
30
|
+
4. Highlight any fields the user should customize
|
|
31
|
+
|
|
32
|
+
When asked to fix a specialist, you:
|
|
33
|
+
1. Identify the exact Zod error and map it to the fix table
|
|
34
|
+
2. Output the corrected YAML section
|
|
35
|
+
3. Explain why the original was invalid
|
|
36
|
+
|
|
37
|
+
task_template: |
|
|
38
|
+
$prompt
|
|
39
|
+
|
|
40
|
+
Working directory: $cwd
|
|
41
|
+
|
|
42
|
+
Use the specialist authoring guide (injected below) to produce or fix a
|
|
43
|
+
.specialist.yaml. Output the complete YAML and the validation command.
|
|
44
|
+
|
|
45
|
+
skills:
|
|
46
|
+
paths:
|
|
47
|
+
- skills/specialist-author/SKILL.md
|
|
48
|
+
|
|
49
|
+
capabilities:
|
|
50
|
+
diagnostic_scripts:
|
|
51
|
+
- bun skills/specialist-author/scripts/validate-specialist.ts specialists/<name>.specialist.yaml
|
|
52
|
+
|
|
53
|
+
communication:
|
|
54
|
+
publishes: [specialist_yaml, validation_command]
|
|
55
|
+
|
|
56
|
+
beads_integration: auto
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
specialist:
|
|
2
|
+
metadata:
|
|
3
|
+
name: sync-docs
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
description: "Audits and syncs project documentation: detects drift, extracts bloated README sections, updates CHANGELOG, and validates docs/ frontmatter."
|
|
6
|
+
category: documentation
|
|
7
|
+
updated: "2026-03-22"
|
|
8
|
+
tags: [docs, readme, changelog, drift, audit, sync]
|
|
9
|
+
|
|
10
|
+
execution:
|
|
11
|
+
mode: tool
|
|
12
|
+
model: anthropic/claude-sonnet-4-6
|
|
13
|
+
fallback_model: google-gemini-cli/gemini-3-flash-preview
|
|
14
|
+
timeout_ms: 300000
|
|
15
|
+
response_format: markdown
|
|
16
|
+
permission_required: LOW
|
|
17
|
+
|
|
18
|
+
prompt:
|
|
19
|
+
system: |
|
|
20
|
+
You are a documentation sync specialist. You audit and fix project documentation
|
|
21
|
+
to keep it in sync with code reality.
|
|
22
|
+
|
|
23
|
+
Follow the sync-docs 5-phase workflow injected in your skill context:
|
|
24
|
+
Phase 1: Gather context (recent changes, bd issues, git log)
|
|
25
|
+
Phase 2: Detect docs/ drift (drift_detector.py)
|
|
26
|
+
Phase 3: Analyze structure (doc_structure_analyzer.py)
|
|
27
|
+
Phase 4: Execute fixes (extract, scaffold, update, changelog)
|
|
28
|
+
Phase 5: Validate (validate_doc.py, final drift scan)
|
|
29
|
+
|
|
30
|
+
**Audit vs Execute:**
|
|
31
|
+
- If the prompt says "audit", "check", "report", or "what's stale" — stop after Phase 3.
|
|
32
|
+
- Only run Phase 4 fixes when the prompt explicitly asks for changes.
|
|
33
|
+
|
|
34
|
+
**Script paths:** Use `~/.agents/skills/sync-docs/scripts/` for global install.
|
|
35
|
+
|
|
36
|
+
task_template: |
|
|
37
|
+
$prompt
|
|
38
|
+
|
|
39
|
+
Working directory: $cwd
|
|
40
|
+
|
|
41
|
+
Follow the sync-docs workflow from your injected skill. Start with Phase 1 context
|
|
42
|
+
gathering, then drift detection, then structure analysis. Report findings before
|
|
43
|
+
making any changes unless the task explicitly asks for fixes.
|
|
44
|
+
|
|
45
|
+
skills:
|
|
46
|
+
paths:
|
|
47
|
+
- ~/.agents/skills/sync-docs/SKILL.md
|
|
48
|
+
|
|
49
|
+
communication:
|
|
50
|
+
output_to: .specialists/sync-docs-report.md
|
|
51
|
+
publishes: [docs_audit, drift_report, changelog_update]
|
|
52
|
+
|
|
53
|
+
beads_integration: auto
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
specialist:
|
|
2
|
+
metadata:
|
|
3
|
+
name: xt-merge
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
description: "Drains the xt worktree PR queue in FIFO order: lists open xt/ PRs sorted by creation time, checks CI status on the oldest, merges it with --rebase --delete-branch, then rebases all remaining branches onto the new default branch and force-pushes them. Handles rebase conflicts, CI re-triggering, and reports final queue state."
|
|
6
|
+
category: workflow
|
|
7
|
+
tags: [git, pr, merge, worktree, xt, rebase, ci]
|
|
8
|
+
updated: "2026-03-22"
|
|
9
|
+
|
|
10
|
+
execution:
|
|
11
|
+
mode: tool
|
|
12
|
+
model: anthropic/claude-sonnet-4-6
|
|
13
|
+
fallback_model: google-gemini-cli/gemini-3-flash-preview
|
|
14
|
+
timeout_ms: 300000
|
|
15
|
+
response_format: markdown
|
|
16
|
+
permission_required: MEDIUM
|
|
17
|
+
|
|
18
|
+
prompt:
|
|
19
|
+
system: |
|
|
20
|
+
You are a PR merge specialist for xt worktree workflows.
|
|
21
|
+
|
|
22
|
+
Your job is to drain the queue of open PRs from xt worktree sessions. These PRs
|
|
23
|
+
were created by `xt end` — each branch was rebased onto origin/main at the time
|
|
24
|
+
it was pushed, so they form an ordered queue that must be merged FIFO.
|
|
25
|
+
|
|
26
|
+
## FIFO ordering
|
|
27
|
+
|
|
28
|
+
Merge the oldest-created PR first. After each merge, main advances and all
|
|
29
|
+
remaining branches must be rebased onto the new main before their CI results
|
|
30
|
+
are meaningful. Merging out of order increases conflict surface unnecessarily.
|
|
31
|
+
|
|
32
|
+
## Your workflow
|
|
33
|
+
|
|
34
|
+
1. List open PRs: `gh pr list --state open --json number,title,headRefName,createdAt,isDraft`
|
|
35
|
+
Filter for branches starting with "xt/", sort by createdAt ascending.
|
|
36
|
+
Skip draft PRs.
|
|
37
|
+
|
|
38
|
+
2. Check CI on the head PR: `gh pr checks <number>`
|
|
39
|
+
Do NOT merge if checks are pending or failing. Report status and stop.
|
|
40
|
+
|
|
41
|
+
3. Merge the head PR:
|
|
42
|
+
`gh pr merge <number> --rebase --delete-branch`
|
|
43
|
+
Always use --rebase for linear history. Always --delete-branch to clean up remote.
|
|
44
|
+
|
|
45
|
+
4. Rebase all remaining xt/ branches onto the new main:
|
|
46
|
+
```
|
|
47
|
+
git fetch origin main
|
|
48
|
+
git checkout xt/<branch>
|
|
49
|
+
git rebase origin/main
|
|
50
|
+
git push origin xt/<branch> --force-with-lease
|
|
51
|
+
```
|
|
52
|
+
Repeat in queue order. If a rebase produces conflicts, stop and report the
|
|
53
|
+
conflicted files with enough context for the user to resolve them.
|
|
54
|
+
|
|
55
|
+
5. Repeat from step 2 until the queue is empty.
|
|
56
|
+
|
|
57
|
+
## Constraints
|
|
58
|
+
|
|
59
|
+
- Never merge a PR with failing or pending CI.
|
|
60
|
+
- Never use --squash or --merge; always --rebase.
|
|
61
|
+
- Never force-push without --force-with-lease.
|
|
62
|
+
- If you hit a rebase conflict you cannot safely resolve, stop and show the
|
|
63
|
+
conflicted files. Do not guess at conflict resolution.
|
|
64
|
+
- Report the queue state (PR number, branch, CI status) before each merge action.
|
|
65
|
+
|
|
66
|
+
task_template: |
|
|
67
|
+
Drain the xt worktree PR merge queue.
|
|
68
|
+
|
|
69
|
+
$prompt
|
|
70
|
+
|
|
71
|
+
Working directory: $cwd
|
|
72
|
+
|
|
73
|
+
List all open PRs from xt/ branches, sort oldest-first, check CI on the oldest,
|
|
74
|
+
merge it if green, rebase the remaining branches onto the new main, and repeat
|
|
75
|
+
until the queue is empty. Report final state when done.
|
|
76
|
+
|
|
77
|
+
communication:
|
|
78
|
+
output_to: .specialists/merge-prs-result.md
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// beads-close-memory-prompt — Claude Code PostToolUse hook
|
|
3
|
-
// After `bd close`: injects a short reminder into Claude's context to capture
|
|
4
|
-
// knowledge and consider underused beads features.
|
|
5
|
-
// Output to stdout is shown to Claude as additional context.
|
|
6
|
-
//
|
|
7
|
-
// Installed by: specialists install
|
|
8
|
-
|
|
9
|
-
import { readFileSync, existsSync } from 'node:fs';
|
|
10
|
-
import { join } from 'node:path';
|
|
11
|
-
|
|
12
|
-
let input;
|
|
13
|
-
try {
|
|
14
|
-
input = JSON.parse(readFileSync(0, 'utf8'));
|
|
15
|
-
} catch {
|
|
16
|
-
process.exit(0);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// Only fire on Bash tool
|
|
20
|
-
if (input.tool_name !== 'Bash') process.exit(0);
|
|
21
|
-
|
|
22
|
-
const cmd = (input.tool_input?.command ?? '').trim();
|
|
23
|
-
|
|
24
|
-
// Only fire when the command is `bd close ...`
|
|
25
|
-
if (!/\bbd\s+close\b/.test(cmd)) process.exit(0);
|
|
26
|
-
|
|
27
|
-
// Only fire in projects that use beads
|
|
28
|
-
const cwd = input.cwd ?? process.env.CLAUDE_PROJECT_DIR ?? process.cwd();
|
|
29
|
-
if (!existsSync(join(cwd, '.beads'))) process.exit(0);
|
|
30
|
-
|
|
31
|
-
// Inject reminder into Claude's context
|
|
32
|
-
process.stdout.write(
|
|
33
|
-
'\n[beads] Issue(s) closed. Before moving on:\n\n' +
|
|
34
|
-
' Knowledge worth keeping?\n' +
|
|
35
|
-
' bd remember "key insight from this work"\n' +
|
|
36
|
-
' bd memories <keyword> -- search what is already stored\n\n' +
|
|
37
|
-
' Discovered related work while implementing?\n' +
|
|
38
|
-
' bd create --title="..." --deps=discovered-from:<id>\n\n' +
|
|
39
|
-
' Underused features to consider:\n' +
|
|
40
|
-
' bd dep add <a> <b> -- link blocking relationships between issues\n' +
|
|
41
|
-
' bd graph -- visualize issue dependency graph\n' +
|
|
42
|
-
' bd orphans -- issues referenced in commits but still open\n' +
|
|
43
|
-
' bd preflight -- PR readiness checklist before gh pr create\n' +
|
|
44
|
-
' bd stale -- issues not touched recently\n'
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
process.exit(0);
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// beads-commit-gate — Claude Code PreToolUse hook
|
|
3
|
-
// Blocks `git commit` when in_progress beads issues still exist.
|
|
4
|
-
// Forces: close issues first, THEN commit.
|
|
5
|
-
// Exit 0: allow | Exit 2: block (stderr shown to Claude)
|
|
6
|
-
//
|
|
7
|
-
// Installed by: specialists install
|
|
8
|
-
|
|
9
|
-
import { execSync } from 'node:child_process';
|
|
10
|
-
import { readFileSync, existsSync } from 'node:fs';
|
|
11
|
-
import { join } from 'node:path';
|
|
12
|
-
|
|
13
|
-
let input;
|
|
14
|
-
try {
|
|
15
|
-
input = JSON.parse(readFileSync(0, 'utf8'));
|
|
16
|
-
} catch {
|
|
17
|
-
process.exit(0);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const tool = input.tool_name ?? '';
|
|
21
|
-
if (tool !== 'Bash') process.exit(0);
|
|
22
|
-
|
|
23
|
-
const cmd = input.tool_input?.command ?? '';
|
|
24
|
-
if (!/\bgit\s+commit\b/.test(cmd)) process.exit(0);
|
|
25
|
-
|
|
26
|
-
const cwd = input.cwd ?? process.env.CLAUDE_PROJECT_DIR ?? process.cwd();
|
|
27
|
-
if (!existsSync(join(cwd, '.beads'))) process.exit(0);
|
|
28
|
-
|
|
29
|
-
let inProgress = 0;
|
|
30
|
-
let summary = '';
|
|
31
|
-
try {
|
|
32
|
-
const output = execSync('bd list --status=in_progress', {
|
|
33
|
-
encoding: 'utf8',
|
|
34
|
-
cwd,
|
|
35
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
36
|
-
timeout: 8000,
|
|
37
|
-
});
|
|
38
|
-
inProgress = (output.match(/in_progress/g) ?? []).length;
|
|
39
|
-
summary = output.trim();
|
|
40
|
-
} catch {
|
|
41
|
-
process.exit(0);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (inProgress > 0) {
|
|
45
|
-
process.stderr.write(
|
|
46
|
-
'🚫 BEADS GATE: Close open issues before committing.\n\n' +
|
|
47
|
-
`Open issues:\n${summary}\n\n` +
|
|
48
|
-
'Next steps:\n' +
|
|
49
|
-
' 3. bd close <id1> <id2> ... ← you are here\n' +
|
|
50
|
-
' 4. git add <files> && git commit -m "..."\n' +
|
|
51
|
-
' 5. git push -u origin <feature-branch>\n' +
|
|
52
|
-
' 6. gh pr create --fill && gh pr merge --squash\n' +
|
|
53
|
-
' 7. git checkout master && git reset --hard origin/master\n'
|
|
54
|
-
);
|
|
55
|
-
process.exit(2);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
process.exit(0);
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// beads-edit-gate — Claude Code PreToolUse hook
|
|
3
|
-
// Blocks file edits when no beads issue is in_progress.
|
|
4
|
-
// Only active in projects with a .beads/ directory.
|
|
5
|
-
// Exit 0: allow | Exit 2: block (stderr shown to Claude)
|
|
6
|
-
//
|
|
7
|
-
// Installed by: specialists install
|
|
8
|
-
|
|
9
|
-
import { execSync } from 'node:child_process';
|
|
10
|
-
import { readFileSync, existsSync } from 'node:fs';
|
|
11
|
-
import { join } from 'node:path';
|
|
12
|
-
|
|
13
|
-
let input;
|
|
14
|
-
try {
|
|
15
|
-
input = JSON.parse(readFileSync(0, 'utf8'));
|
|
16
|
-
} catch {
|
|
17
|
-
process.exit(0);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const cwd = input.cwd ?? process.env.CLAUDE_PROJECT_DIR ?? process.cwd();
|
|
21
|
-
if (!existsSync(join(cwd, '.beads'))) process.exit(0);
|
|
22
|
-
|
|
23
|
-
let inProgress = 0;
|
|
24
|
-
try {
|
|
25
|
-
const output = execSync('bd list --status=in_progress', {
|
|
26
|
-
encoding: 'utf8',
|
|
27
|
-
cwd,
|
|
28
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
29
|
-
timeout: 8000,
|
|
30
|
-
});
|
|
31
|
-
inProgress = (output.match(/in_progress/g) ?? []).length;
|
|
32
|
-
} catch {
|
|
33
|
-
process.exit(0);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (inProgress === 0) {
|
|
37
|
-
process.stderr.write(
|
|
38
|
-
'🚫 BEADS GATE: No active issue — create one before editing files.\n\n' +
|
|
39
|
-
' bd create --title="<what you\'re doing>" --type=task --priority=2\n' +
|
|
40
|
-
' bd update <id> --status=in_progress\n\n' +
|
|
41
|
-
'Full workflow (do this every session):\n' +
|
|
42
|
-
' 1. bd create + bd update in_progress ← you are here\n' +
|
|
43
|
-
' 2. Edit files / write code\n' +
|
|
44
|
-
' 3. bd close <id> close when done\n' +
|
|
45
|
-
' 4. git add <files> && git commit\n' +
|
|
46
|
-
' 5. git push -u origin <feature-branch>\n' +
|
|
47
|
-
' 6. gh pr create --fill && gh pr merge --squash\n' +
|
|
48
|
-
' 7. git checkout master && git reset --hard origin/master\n'
|
|
49
|
-
);
|
|
50
|
-
process.exit(2);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
process.exit(0);
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// beads-stop-gate — Claude Code Stop hook
|
|
3
|
-
// Blocks the agent from stopping when in_progress beads issues remain.
|
|
4
|
-
// Exit 0: allow stop | Exit 2: block stop (stderr shown to Claude)
|
|
5
|
-
//
|
|
6
|
-
// Installed by: specialists install
|
|
7
|
-
|
|
8
|
-
import { execSync } from 'node:child_process';
|
|
9
|
-
import { readFileSync, existsSync } from 'node:fs';
|
|
10
|
-
import { join } from 'node:path';
|
|
11
|
-
|
|
12
|
-
let input;
|
|
13
|
-
try {
|
|
14
|
-
input = JSON.parse(readFileSync(0, 'utf8'));
|
|
15
|
-
} catch {
|
|
16
|
-
process.exit(0);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const cwd = input.cwd ?? process.env.CLAUDE_PROJECT_DIR ?? process.cwd();
|
|
20
|
-
if (!existsSync(join(cwd, '.beads'))) process.exit(0);
|
|
21
|
-
|
|
22
|
-
let inProgress = 0;
|
|
23
|
-
let summary = '';
|
|
24
|
-
try {
|
|
25
|
-
const output = execSync('bd list --status=in_progress', {
|
|
26
|
-
encoding: 'utf8',
|
|
27
|
-
cwd,
|
|
28
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
29
|
-
timeout: 8000,
|
|
30
|
-
});
|
|
31
|
-
inProgress = (output.match(/in_progress/g) ?? []).length;
|
|
32
|
-
summary = output.trim();
|
|
33
|
-
} catch {
|
|
34
|
-
process.exit(0);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
if (inProgress > 0) {
|
|
38
|
-
process.stderr.write(
|
|
39
|
-
'🚫 BEADS STOP GATE: Unresolved issues — complete the session close protocol.\n\n' +
|
|
40
|
-
`Open issues:\n${summary}\n\n` +
|
|
41
|
-
'Session close protocol:\n' +
|
|
42
|
-
' 3. bd close <id1> <id2> ... close all in_progress issues\n' +
|
|
43
|
-
' 4. git add <files> && git commit -m "..." commit your changes\n' +
|
|
44
|
-
' 5. git push -u origin <feature-branch> push feature branch\n' +
|
|
45
|
-
' 6. gh pr create --fill create PR\n' +
|
|
46
|
-
' 7. gh pr merge --squash merge PR\n' +
|
|
47
|
-
' 8. git checkout master && git reset --hard origin/master\n'
|
|
48
|
-
);
|
|
49
|
-
process.exit(2);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
process.exit(0);
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Claude Code PreToolUse hook — block writes and direct master pushes
|
|
3
|
-
// Exit 0: allow | Exit 2: block (message shown to user)
|
|
4
|
-
//
|
|
5
|
-
// Installed by: specialists install
|
|
6
|
-
|
|
7
|
-
import { execSync } from 'node:child_process';
|
|
8
|
-
import { readFileSync } from 'node:fs';
|
|
9
|
-
|
|
10
|
-
let branch = '';
|
|
11
|
-
try {
|
|
12
|
-
branch = execSync('git branch --show-current', {
|
|
13
|
-
encoding: 'utf8',
|
|
14
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
15
|
-
}).trim();
|
|
16
|
-
} catch {}
|
|
17
|
-
|
|
18
|
-
// Not in a git repo or not on a protected branch — allow
|
|
19
|
-
if (!branch || (branch !== 'main' && branch !== 'master')) {
|
|
20
|
-
process.exit(0);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
let input;
|
|
24
|
-
try {
|
|
25
|
-
input = JSON.parse(readFileSync(0, 'utf8'));
|
|
26
|
-
} catch {
|
|
27
|
-
process.exit(0);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const tool = input.tool_name ?? '';
|
|
31
|
-
|
|
32
|
-
const WRITE_TOOLS = new Set(['Edit', 'Write', 'MultiEdit', 'NotebookEdit']);
|
|
33
|
-
|
|
34
|
-
if (WRITE_TOOLS.has(tool)) {
|
|
35
|
-
process.stderr.write(
|
|
36
|
-
`⛔ You are on '${branch}' — never edit files directly on master.\n\n` +
|
|
37
|
-
'Full workflow:\n' +
|
|
38
|
-
' 1. git checkout -b feature/<name> ← start here\n' +
|
|
39
|
-
' 2. bd create + bd update in_progress track your work\n' +
|
|
40
|
-
' 3. Edit files / write code\n' +
|
|
41
|
-
' 4. bd close <id> && git add && git commit\n' +
|
|
42
|
-
' 5. git push -u origin feature/<name>\n' +
|
|
43
|
-
' 6. gh pr create --fill && gh pr merge --squash\n' +
|
|
44
|
-
' 7. git checkout master && git reset --hard origin/master\n'
|
|
45
|
-
);
|
|
46
|
-
process.exit(2);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Block direct commits and pushes to master — use feature branches + gh pr create/merge
|
|
50
|
-
if (tool === 'Bash') {
|
|
51
|
-
const cmd = (input.tool_input?.command ?? '').trim().replace(/\s+/g, ' ');
|
|
52
|
-
|
|
53
|
-
if (/^git commit/.test(cmd)) {
|
|
54
|
-
process.stderr.write(
|
|
55
|
-
`⛔ Don't commit directly to '${branch}' — use a feature branch.\n\n` +
|
|
56
|
-
'Full workflow:\n' +
|
|
57
|
-
' 1. git checkout -b feature/<name> ← start here\n' +
|
|
58
|
-
' 2. bd create + bd update in_progress track your work\n' +
|
|
59
|
-
' 3. Edit files / write code\n' +
|
|
60
|
-
' 4. bd close <id> && git add && git commit\n' +
|
|
61
|
-
' 5. git push -u origin feature/<name>\n' +
|
|
62
|
-
' 6. gh pr create --fill && gh pr merge --squash\n' +
|
|
63
|
-
' 7. git checkout master && git reset --hard origin/master\n'
|
|
64
|
-
);
|
|
65
|
-
process.exit(2);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if (/^git push/.test(cmd)) {
|
|
69
|
-
const tokens = cmd.split(' ');
|
|
70
|
-
const lastToken = tokens[tokens.length - 1];
|
|
71
|
-
const explicitMaster = /^(master|main)$/.test(lastToken) || /:(master|main)$/.test(lastToken);
|
|
72
|
-
const impliedMaster = tokens.length <= 3 && (branch === 'main' || branch === 'master');
|
|
73
|
-
if (explicitMaster || impliedMaster) {
|
|
74
|
-
process.stderr.write(
|
|
75
|
-
`⛔ Don't push directly to '${branch}' — use the PR workflow.\n\n` +
|
|
76
|
-
'Next steps:\n' +
|
|
77
|
-
' 5. git push -u origin <feature-branch> ← push your branch\n' +
|
|
78
|
-
' 6. gh pr create --fill create PR\n' +
|
|
79
|
-
' gh pr merge --squash merge it\n' +
|
|
80
|
-
' 7. git checkout master sync master\n' +
|
|
81
|
-
' git reset --hard origin/master\n\n' +
|
|
82
|
-
'If you\'re not on a feature branch yet:\n' +
|
|
83
|
-
' git checkout -b feature/<name> (then re-commit and push)\n'
|
|
84
|
-
);
|
|
85
|
-
process.exit(2);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
process.exit(0);
|