beads-orchestration 2.0.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 (40) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +214 -0
  3. package/SKILL.md +263 -0
  4. package/bootstrap.py +928 -0
  5. package/package.json +37 -0
  6. package/scripts/cli.js +64 -0
  7. package/scripts/postinstall.js +71 -0
  8. package/skills/create-beads-orchestration/SKILL.md +263 -0
  9. package/skills/subagents-discipline/SKILL.md +158 -0
  10. package/templates/CLAUDE.md +326 -0
  11. package/templates/agents/architect.md +121 -0
  12. package/templates/agents/code-reviewer.md +248 -0
  13. package/templates/agents/detective.md +101 -0
  14. package/templates/agents/discovery.md +492 -0
  15. package/templates/agents/merge-supervisor.md +119 -0
  16. package/templates/agents/scout.md +100 -0
  17. package/templates/agents/scribe.md +96 -0
  18. package/templates/beads-workflow-injection-api.md +116 -0
  19. package/templates/beads-workflow-injection-git.md +108 -0
  20. package/templates/beads-workflow-injection.md +111 -0
  21. package/templates/frontend-reviews-requirement.md +61 -0
  22. package/templates/hooks/block-orchestrator-tools.sh +98 -0
  23. package/templates/hooks/clarify-vague-request.sh +39 -0
  24. package/templates/hooks/enforce-bead-for-supervisor.sh +32 -0
  25. package/templates/hooks/enforce-branch-before-edit.sh +47 -0
  26. package/templates/hooks/enforce-concise-response.sh +41 -0
  27. package/templates/hooks/enforce-sequential-dispatch.sh +63 -0
  28. package/templates/hooks/inject-discipline-reminder.sh +28 -0
  29. package/templates/hooks/log-dispatch-prompt.sh +39 -0
  30. package/templates/hooks/memory-capture.sh +104 -0
  31. package/templates/hooks/remind-inprogress.sh +14 -0
  32. package/templates/hooks/session-start.sh +121 -0
  33. package/templates/hooks/validate-completion.sh +131 -0
  34. package/templates/hooks/validate-epic-close.sh +84 -0
  35. package/templates/mcp.json.template +12 -0
  36. package/templates/memory/recall.sh +121 -0
  37. package/templates/settings.json +74 -0
  38. package/templates/skills/react-best-practices/SKILL.md +487 -0
  39. package/templates/skills/subagents-discipline/SKILL.md +127 -0
  40. package/templates/ui-constraints.md +76 -0
@@ -0,0 +1,84 @@
1
+ #!/bin/bash
2
+ # Hook: Validate bead close — PR must be merged, epic children must be complete
3
+ # Prevents closing a bead whose branch has no merged PR
4
+ # Prevents closing an epic when children are still open
5
+
6
+ set -euo pipefail
7
+
8
+ TOOL_INPUT="${CLAUDE_TOOL_INPUT:-}"
9
+
10
+ # Only check Bash commands containing "bd close"
11
+ if ! echo "$TOOL_INPUT" | jq -e '.command' >/dev/null 2>&1; then
12
+ exit 0
13
+ fi
14
+
15
+ COMMAND=$(echo "$TOOL_INPUT" | jq -r '.command // ""')
16
+
17
+ # Check if this is a bd close command
18
+ if ! echo "$COMMAND" | grep -qE 'bd\s+close'; then
19
+ exit 0
20
+ fi
21
+
22
+ # Allow --force override
23
+ if echo "$COMMAND" | grep -qE '\-\-force'; then
24
+ exit 0
25
+ fi
26
+
27
+ # Extract the ID being closed (handles: bd close ID, bd close ID && ..., etc.)
28
+ CLOSE_ID=$(echo "$COMMAND" | sed -E 's/.*bd\s+close\s+([A-Za-z0-9._-]+).*/\1/')
29
+
30
+ if [ -z "$CLOSE_ID" ]; then
31
+ exit 0
32
+ fi
33
+
34
+ # === CHECK 1: PR merge validation ===
35
+ # Only applies if repo has a remote and branch exists
36
+ BRANCH="bd-${CLOSE_ID}"
37
+
38
+ HAS_REMOTE=$(git remote get-url origin 2>/dev/null || echo "")
39
+ if [ -n "$HAS_REMOTE" ]; then
40
+ REMOTE_BRANCH=$(git ls-remote --heads origin "$BRANCH" 2>/dev/null || echo "")
41
+
42
+ if [ -n "$REMOTE_BRANCH" ]; then
43
+ # Branch exists on remote — check for merged PR
44
+ if command -v gh >/dev/null 2>&1; then
45
+ MERGED_PR=$(gh pr list --head "$BRANCH" --state merged --json number --jq '.[0].number' 2>/dev/null || echo "")
46
+
47
+ if [ -z "$MERGED_PR" ]; then
48
+ cat << EOF
49
+ {"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"Cannot close bead '$CLOSE_ID' — branch '$BRANCH' has no merged PR. Create and merge a PR first, or use 'bd close $CLOSE_ID --force' to override."}}
50
+ EOF
51
+ exit 0
52
+ fi
53
+ fi
54
+ fi
55
+ fi
56
+
57
+ # === CHECK 2: Epic children validation ===
58
+ # Check if this is an epic by looking for children
59
+ CHILDREN=$(bd show "$CLOSE_ID" --json 2>/dev/null | jq -r '.[0].children // empty' 2>/dev/null || echo "")
60
+
61
+ if [ -z "$CHILDREN" ] || [ "$CHILDREN" = "null" ]; then
62
+ # Not an epic or no children, allow close
63
+ exit 0
64
+ fi
65
+
66
+ # This is an epic - check if all children are complete
67
+ INCOMPLETE=$(bd list --json 2>/dev/null | jq -r --arg epic "$CLOSE_ID" '
68
+ [.[] | select(.parent == $epic and .status != "done" and .status != "closed")] | length
69
+ ' 2>/dev/null || echo "0")
70
+
71
+ if [ "$INCOMPLETE" != "0" ] && [ "$INCOMPLETE" != "" ]; then
72
+ # Get list of incomplete children for the error message
73
+ INCOMPLETE_LIST=$(bd list --json 2>/dev/null | jq -r --arg epic "$CLOSE_ID" '
74
+ [.[] | select(.parent == $epic and .status != "done" and .status != "closed")] | .[] | "\(.id) (\(.status))"
75
+ ' 2>/dev/null | tr '\n' ', ' | sed 's/,$//')
76
+
77
+ cat << EOF
78
+ {"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"Cannot close epic '$CLOSE_ID' - has $INCOMPLETE incomplete children: $INCOMPLETE_LIST. Mark all children as done first."}}
79
+ EOF
80
+ exit 0
81
+ fi
82
+
83
+ # All checks passed, allow close
84
+ exit 0
@@ -0,0 +1,12 @@
1
+ {
2
+ "mcpServers": {
3
+ "provider_delegator": {
4
+ "type": "stdio",
5
+ "command": "{{PROVIDER_DELEGATOR_PATH}}",
6
+ "args": ["-m", "mcp_provider_delegator.server"],
7
+ "env": {
8
+ "AGENT_TEMPLATES_PATH": "{{AGENT_TEMPLATES_PATH}}"
9
+ }
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,121 @@
1
+ #!/bin/bash
2
+ #
3
+ # recall.sh - Search the project knowledge base
4
+ #
5
+ # Usage:
6
+ # .beads/memory/recall.sh "keyword" # Search by keyword
7
+ # .beads/memory/recall.sh "keyword" --type learned # Filter by type
8
+ # .beads/memory/recall.sh --recent 10 # Show N most recent
9
+ # .beads/memory/recall.sh --stats # Knowledge base stats
10
+ # .beads/memory/recall.sh "keyword" --all # Include archive
11
+ #
12
+
13
+ set -euo pipefail
14
+
15
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
16
+ KNOWLEDGE_FILE="$SCRIPT_DIR/knowledge.jsonl"
17
+ ARCHIVE_FILE="$SCRIPT_DIR/knowledge.archive.jsonl"
18
+
19
+ if [[ ! -f "$KNOWLEDGE_FILE" ]] || [[ ! -s "$KNOWLEDGE_FILE" ]]; then
20
+ echo "No knowledge entries yet."
21
+ echo "Entries are created automatically from bd comment commands with INVESTIGATION: or LEARNED: prefixes."
22
+ exit 0
23
+ fi
24
+
25
+ # Parse arguments
26
+ QUERY=""
27
+ TYPE_FILTER=""
28
+ INCLUDE_ARCHIVE=false
29
+ SHOW_RECENT=0
30
+ SHOW_STATS=false
31
+
32
+ while [[ $# -gt 0 ]]; do
33
+ case "$1" in
34
+ --type)
35
+ TYPE_FILTER="${2:-}"
36
+ shift 2
37
+ ;;
38
+ --all)
39
+ INCLUDE_ARCHIVE=true
40
+ shift
41
+ ;;
42
+ --recent)
43
+ SHOW_RECENT="${2:-10}"
44
+ shift 2
45
+ ;;
46
+ --stats)
47
+ SHOW_STATS=true
48
+ shift
49
+ ;;
50
+ --help|-h)
51
+ echo "Usage: recall.sh [query] [--type learned|investigation] [--all] [--recent N] [--stats]"
52
+ exit 0
53
+ ;;
54
+ *)
55
+ QUERY="$1"
56
+ shift
57
+ ;;
58
+ esac
59
+ done
60
+
61
+ # Stats mode
62
+ if [[ "$SHOW_STATS" == "true" ]]; then
63
+ TOTAL=$(wc -l < "$KNOWLEDGE_FILE" | tr -d ' ')
64
+ LEARNED=$(grep -c '"type":"learned"' "$KNOWLEDGE_FILE" 2>/dev/null) || LEARNED=0
65
+ INVESTIGATION=$(grep -c '"type":"investigation"' "$KNOWLEDGE_FILE" 2>/dev/null) || INVESTIGATION=0
66
+ UNIQUE_KEYS=$(jq -r '.key' "$KNOWLEDGE_FILE" 2>/dev/null | sort -u | wc -l | tr -d ' ')
67
+ ARCHIVE_COUNT=0
68
+ [[ -f "$ARCHIVE_FILE" ]] && ARCHIVE_COUNT=$(wc -l < "$ARCHIVE_FILE" | tr -d ' ')
69
+
70
+ echo "## Knowledge Base Stats"
71
+ echo " Active entries: $TOTAL"
72
+ echo " Unique keys: $UNIQUE_KEYS"
73
+ echo " Learned: $LEARNED"
74
+ echo " Investigation: $INVESTIGATION"
75
+ echo " Archived: $ARCHIVE_COUNT"
76
+ exit 0
77
+ fi
78
+
79
+ # Recent mode
80
+ if [[ "$SHOW_RECENT" -gt 0 ]]; then
81
+ echo "## Recent Knowledge ($SHOW_RECENT entries)"
82
+ echo ""
83
+ tail -"$SHOW_RECENT" "$KNOWLEDGE_FILE" | jq -r '
84
+ "[\(.type | ascii_upcase | .[0:5])] \(.key)\n \(.content | .[0:120])\n source=\(.source) bead=\(.bead)\n"
85
+ ' 2>/dev/null
86
+ exit 0
87
+ fi
88
+
89
+ # Search mode (default)
90
+ if [[ -z "$QUERY" ]]; then
91
+ echo "Usage: recall.sh <keyword> [--type learned|investigation] [--all]"
92
+ exit 1
93
+ fi
94
+
95
+ # Build file list
96
+ FILES="$KNOWLEDGE_FILE"
97
+ if [[ "$INCLUDE_ARCHIVE" == "true" && -f "$ARCHIVE_FILE" ]]; then
98
+ FILES="$ARCHIVE_FILE $KNOWLEDGE_FILE"
99
+ fi
100
+
101
+ # Search and deduplicate (latest entry for each key wins)
102
+ RESULTS=$(cat $FILES | grep -i "$QUERY" 2>/dev/null || true)
103
+
104
+ # Apply type filter
105
+ if [[ -n "$TYPE_FILTER" ]]; then
106
+ RESULTS=$(echo "$RESULTS" | grep "\"type\":\"$TYPE_FILTER\"" 2>/dev/null || true)
107
+ fi
108
+
109
+ if [[ -z "$RESULTS" ]]; then
110
+ echo "No knowledge entries matching '$QUERY'"
111
+ [[ -n "$TYPE_FILTER" ]] && echo " (filtered by type: $TYPE_FILTER)"
112
+ exit 0
113
+ fi
114
+
115
+ # Deduplicate by key (latest wins) and format output
116
+ echo "$RESULTS" | jq -s '
117
+ group_by(.key) | map(max_by(.ts)) | sort_by(-.ts) | .[] |
118
+ "[\(.type | ascii_upcase | .[0:5])] \(.key)\n \(.content | .[0:200])\n source=\(.source) bead=\(.bead) tags=\(.tags | join(","))\n"
119
+ ' -r 2>/dev/null
120
+
121
+ exit 0
@@ -0,0 +1,74 @@
1
+ {
2
+ "hooks": {
3
+ "PreToolUse": [
4
+ {
5
+ "hooks": [
6
+ {"type": "command", "command": ".claude/hooks/block-orchestrator-tools.sh"}
7
+ ]
8
+ },
9
+ {
10
+ "matcher": "Task",
11
+ "hooks": [
12
+ {"type": "command", "command": ".claude/hooks/enforce-bead-for-supervisor.sh"},
13
+ {"type": "command", "command": ".claude/hooks/enforce-sequential-dispatch.sh"},
14
+ {"type": "command", "command": ".claude/hooks/remind-inprogress.sh"},
15
+ {"type": "command", "command": ".claude/hooks/inject-discipline-reminder.sh"}
16
+ ]
17
+ },
18
+ {
19
+ "matcher": "Edit",
20
+ "hooks": [
21
+ {"type": "command", "command": ".claude/hooks/enforce-branch-before-edit.sh"}
22
+ ]
23
+ },
24
+ {
25
+ "matcher": "Write",
26
+ "hooks": [
27
+ {"type": "command", "command": ".claude/hooks/enforce-branch-before-edit.sh"}
28
+ ]
29
+ },
30
+ {
31
+ "matcher": "Bash",
32
+ "hooks": [
33
+ {"type": "command", "command": ".claude/hooks/validate-epic-close.sh"}
34
+ ]
35
+ }
36
+ ],
37
+ "PostToolUse": [
38
+ {
39
+ "matcher": "Task",
40
+ "hooks": [
41
+ {"type": "command", "command": ".claude/hooks/enforce-concise-response.sh"},
42
+ {"type": "command", "command": ".claude/hooks/log-dispatch-prompt.sh", "timeout": 10}
43
+ ]
44
+ },
45
+ {
46
+ "matcher": "Bash",
47
+ "hooks": [
48
+ {"type": "command", "command": ".claude/hooks/memory-capture.sh", "timeout": 10}
49
+ ]
50
+ }
51
+ ],
52
+ "SubagentStop": [
53
+ {
54
+ "hooks": [
55
+ {"type": "command", "command": ".claude/hooks/validate-completion.sh"}
56
+ ]
57
+ }
58
+ ],
59
+ "SessionStart": [
60
+ {
61
+ "hooks": [
62
+ {"type": "command", "command": ".claude/hooks/session-start.sh"}
63
+ ]
64
+ }
65
+ ],
66
+ "UserPromptSubmit": [
67
+ {
68
+ "hooks": [
69
+ {"type": "command", "command": ".claude/hooks/clarify-vague-request.sh"}
70
+ ]
71
+ }
72
+ ]
73
+ }
74
+ }