@engineereddev/fractal-planner 0.1.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/.claude-plugin/marketplace.json +22 -0
- package/.claude-plugin/plugin.json +19 -0
- package/LICENSE +21 -0
- package/README.md +257 -0
- package/agents/fp-analyst.md +96 -0
- package/agents/fp-context-builder.md +87 -0
- package/agents/fp-critic.md +140 -0
- package/agents/fp-decomposer.md +261 -0
- package/agents/fp-interviewer.md +263 -0
- package/agents/fp-linear-sync.md +128 -0
- package/agents/fp-researcher.md +82 -0
- package/agents/fp-task-tracker.md +134 -0
- package/dist/cli/classify-intent.js +118 -0
- package/dist/cli/compute-signals.js +495 -0
- package/dist/cli/generate-plan.js +14209 -0
- package/dist/cli/load-config.js +13661 -0
- package/dist/cli/validate-tasks.js +467 -0
- package/dist/index.js +24598 -0
- package/dist/src/cli/classify-intent.d.ts +3 -0
- package/dist/src/cli/compute-signals.d.ts +14 -0
- package/dist/src/cli/generate-plan.d.ts +3 -0
- package/dist/src/cli/load-config.d.ts +3 -0
- package/dist/src/cli/validate-tasks.d.ts +3 -0
- package/dist/src/config.d.ts +182 -0
- package/dist/src/index.d.ts +12 -0
- package/dist/src/phases/clearance.d.ts +12 -0
- package/dist/src/phases/decomposition.d.ts +41 -0
- package/dist/src/phases/interview.d.ts +17 -0
- package/dist/src/phases/planning.d.ts +21 -0
- package/dist/src/phases/research.d.ts +9 -0
- package/dist/src/types/index.d.ts +116 -0
- package/dist/src/utils/draft.d.ts +21 -0
- package/dist/src/utils/question-strategies.d.ts +24 -0
- package/dist/src/utils/task-parser.d.ts +3 -0
- package/hooks/hooks.json +27 -0
- package/hooks/nudge-teammate.sh +216 -0
- package/hooks/run-comment-checker.sh +91 -0
- package/package.json +65 -0
- package/skills/commit/SKILL.md +157 -0
- package/skills/fp/SKILL.md +857 -0
- package/skills/fp/scripts/resolve-env.sh +66 -0
- package/skills/handoff/SKILL.md +195 -0
- package/skills/implement/SKILL.md +783 -0
- package/skills/implement/reference.md +935 -0
- package/skills/retry/SKILL.md +333 -0
- package/skills/status/SKILL.md +182 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# Resolves plugin root, CLI runner, CLI directory, and full merged config.
|
|
5
|
+
# Called via !`command` in SKILL.md at skill load time.
|
|
6
|
+
#
|
|
7
|
+
# Output format (key: value, one per line):
|
|
8
|
+
# PLUGIN_ROOT: /path/to/fractal-planner
|
|
9
|
+
# CLI_RUNNER: bun
|
|
10
|
+
# CLI_DIR: /path/to/fractal-planner/src/cli
|
|
11
|
+
# CONFIG_JSON: {"maxComplexity":3,...}
|
|
12
|
+
|
|
13
|
+
# --- Resolve plugin root ---
|
|
14
|
+
# $CLAUDE_PLUGIN_ROOT points to the plugin root (where .claude-plugin/ lives).
|
|
15
|
+
# Fallback: script-relative path (scripts/ -> fp/ -> skills/ -> repo root).
|
|
16
|
+
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "$0")/../../.." && pwd)}"
|
|
17
|
+
|
|
18
|
+
# --- Read cliRunner from config ---
|
|
19
|
+
CONFIG_FILE="$PLUGIN_ROOT/.fractal-planner/config.json"
|
|
20
|
+
CLI_RUNNER_SETTING="auto"
|
|
21
|
+
|
|
22
|
+
if [[ -f "$CONFIG_FILE" ]]; then
|
|
23
|
+
CLI_RUNNER_SETTING=$(python3 -c "
|
|
24
|
+
import json,sys
|
|
25
|
+
try:
|
|
26
|
+
c=json.load(open('$CONFIG_FILE'))
|
|
27
|
+
print(c.get('cliRunner','auto'))
|
|
28
|
+
except: print('auto')
|
|
29
|
+
" 2>/dev/null || echo "auto")
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
# --- Resolve CLI runner ---
|
|
33
|
+
case "$CLI_RUNNER_SETTING" in
|
|
34
|
+
bun) CLI_RUNNER="bun" ;;
|
|
35
|
+
node) CLI_RUNNER="node" ;;
|
|
36
|
+
*)
|
|
37
|
+
if command -v bun >/dev/null 2>&1; then
|
|
38
|
+
CLI_RUNNER="bun"
|
|
39
|
+
else
|
|
40
|
+
CLI_RUNNER="node"
|
|
41
|
+
fi
|
|
42
|
+
;;
|
|
43
|
+
esac
|
|
44
|
+
|
|
45
|
+
# --- Resolve CLI directory ---
|
|
46
|
+
if [[ "$CLI_RUNNER" == "bun" ]] && [[ -f "$PLUGIN_ROOT/src/cli/classify-intent.ts" ]]; then
|
|
47
|
+
CLI_DIR="$PLUGIN_ROOT/src/cli"
|
|
48
|
+
else
|
|
49
|
+
CLI_DIR="$PLUGIN_ROOT/dist/cli"
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
# --- Load full merged config via CLI helper ---
|
|
53
|
+
CONFIG_JSON=""
|
|
54
|
+
if [[ "$CLI_RUNNER" == "bun" ]] && [[ -f "$CLI_DIR/load-config.ts" ]]; then
|
|
55
|
+
CONFIG_JSON=$("$CLI_RUNNER" "$CLI_DIR/load-config.ts" 2>/dev/null || echo '{"_error":"config load failed"}')
|
|
56
|
+
elif [[ -f "$CLI_DIR/load-config.js" ]]; then
|
|
57
|
+
CONFIG_JSON=$("$CLI_RUNNER" "$CLI_DIR/load-config.js" 2>/dev/null || echo '{"_error":"config load failed"}')
|
|
58
|
+
else
|
|
59
|
+
CONFIG_JSON='{"_error":"load-config not found"}'
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# --- Output ---
|
|
63
|
+
echo "PLUGIN_ROOT: $PLUGIN_ROOT"
|
|
64
|
+
echo "CLI_RUNNER: $CLI_RUNNER"
|
|
65
|
+
echo "CLI_DIR: $CLI_DIR"
|
|
66
|
+
echo "CONFIG_JSON: $CONFIG_JSON"
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: fp:handoff
|
|
3
|
+
description: Generate a session handoff summary for clean context continuation during large implementations
|
|
4
|
+
argument-hint: <plan-session-id>
|
|
5
|
+
allowed-tools: Read, Glob, Bash, Write
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Fractal Planner: Session Handoff
|
|
9
|
+
|
|
10
|
+
You are generating a handoff summary for a fractal-planner implementation plan. This captures volatile state (discoveries, iteration counts, failure details) so the next `/fp:implement` session resumes with full context.
|
|
11
|
+
|
|
12
|
+
## Step 1: Parse Arguments
|
|
13
|
+
|
|
14
|
+
Parse `$ARGUMENTS` to extract `planId` (the first positional argument).
|
|
15
|
+
|
|
16
|
+
If no `planId` is provided, report the error and stop:
|
|
17
|
+
> "Usage: `/fp:handoff <plan-session-id>`"
|
|
18
|
+
|
|
19
|
+
## Step 2: Validate Prerequisites
|
|
20
|
+
|
|
21
|
+
Check `.fractal-planner/plans/{planId}/` has both:
|
|
22
|
+
1. `plan.md`
|
|
23
|
+
2. `execution-state.json`
|
|
24
|
+
|
|
25
|
+
If either is missing, report the error and stop:
|
|
26
|
+
> "Plan '{planId}' is missing required files. Both `plan.md` and `execution-state.json` must exist. Run `/fp:plan` and `/fp:implement` first."
|
|
27
|
+
|
|
28
|
+
## Step 3: Load Execution State
|
|
29
|
+
|
|
30
|
+
Read `.fractal-planner/plans/{planId}/execution-state.json`. Extract:
|
|
31
|
+
- `taskMap` — object mapping plan task IDs to native task IDs
|
|
32
|
+
- `skippedTasks` — object mapping plan task IDs to skip reasons
|
|
33
|
+
- `failureReasons` — object mapping plan task IDs to failure reasons
|
|
34
|
+
- `iterationMap` — object mapping plan task IDs to iteration numbers (default `{}` if absent)
|
|
35
|
+
- `clarificationsUsed` — object mapping plan task IDs to booleans (default `{}` if absent)
|
|
36
|
+
- `maxIterations`
|
|
37
|
+
|
|
38
|
+
## Step 4: Read Native Task Files
|
|
39
|
+
|
|
40
|
+
Use Glob to find task files:
|
|
41
|
+
```
|
|
42
|
+
Glob("~/.claude/tasks/fp-impl-{planId}/*.json")
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
For each file found, read and extract:
|
|
46
|
+
- `id` — native task ID
|
|
47
|
+
- `subject` — contains `[{planTaskId}] {description}` — extract planTaskId from the `[...]` prefix
|
|
48
|
+
- `status` — `pending`, `in_progress`, `completed`, or `deleted`
|
|
49
|
+
- `metadata` — object with `fpStatus`, `iterations`, `commit`, `summary`, `reason`, `owner` fields
|
|
50
|
+
- `blockedBy` — array of blocking native task IDs
|
|
51
|
+
|
|
52
|
+
Build `statusMap` keyed by planTaskId:
|
|
53
|
+
```
|
|
54
|
+
statusMap[planTaskId] = {
|
|
55
|
+
nativeId, status, fpStatus, iterations, commit, summary, reason, owner, blockedBy
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Fallback**: If the `~/.claude/tasks/fp-impl-{planId}/` directory does not exist or is empty:
|
|
60
|
+
- Classify all `taskMap` entries not in `skippedTasks`/`failureReasons` as PENDING
|
|
61
|
+
- Note "Native task files unavailable — using execution-state.json data only" in the output
|
|
62
|
+
|
|
63
|
+
## Step 5: Active Session Detection
|
|
64
|
+
|
|
65
|
+
Check if `~/.claude/teams/fp-impl-{planId}/config.json` exists:
|
|
66
|
+
```bash
|
|
67
|
+
ls ~/.claude/teams/fp-impl-{planId}/config.json 2>/dev/null
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
If it exists AND any native task has `status: "in_progress"`, display warning:
|
|
71
|
+
> "An implementation session may still be active. Stop it before generating a handoff."
|
|
72
|
+
|
|
73
|
+
Proceed regardless (the warning is informational).
|
|
74
|
+
|
|
75
|
+
## Step 6: Load Plan Descriptions
|
|
76
|
+
|
|
77
|
+
Read `.fractal-planner/plans/{planId}/plan.md`.
|
|
78
|
+
|
|
79
|
+
Build a `planTaskId -> description` map from the Execution Order section. Each entry in the execution order has the format:
|
|
80
|
+
```
|
|
81
|
+
N. [Task {id}]: {description}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Extract the full description for each task ID. If a task ID is not found in plan.md, fall back to the subject from the native task file.
|
|
85
|
+
|
|
86
|
+
## Step 7: Read Artifacts
|
|
87
|
+
|
|
88
|
+
Read the following if they exist:
|
|
89
|
+
- `.fractal-planner/plans/{planId}/notepad.md` — for Key Discoveries (extract the `## Entries` section content)
|
|
90
|
+
- For FAILED tasks only: read `.fractal-planner/plans/{planId}/evidence/task-{planTaskId}-verification.md` to extract the failure reason from the `## Summary` section
|
|
91
|
+
- Note whether `.fractal-planner/plans/{planId}/context.md` exists (informational)
|
|
92
|
+
|
|
93
|
+
## Step 8: Classify Tasks
|
|
94
|
+
|
|
95
|
+
For each plan task ID in `taskMap`, classify using the same table as `fp:status`:
|
|
96
|
+
|
|
97
|
+
| Condition | Classification |
|
|
98
|
+
|-----------|---------------|
|
|
99
|
+
| In `skippedTasks` AND (`status == "deleted"` OR native file absent) | **SKIPPED** |
|
|
100
|
+
| `status == "completed"` AND `fpStatus == "FAILED"` | **FAILED** |
|
|
101
|
+
| `status == "completed"` AND (`fpStatus == "COMPLETED"` OR fpStatus absent) | **COMPLETED** |
|
|
102
|
+
| `status == "in_progress"` | **IN_PROGRESS** |
|
|
103
|
+
| `status == "pending"` | **PENDING** |
|
|
104
|
+
| `status == "deleted"` AND `fpStatus == "SKIPPED"` | **SKIPPED** |
|
|
105
|
+
| Native file not found AND not in `skippedTasks` | **PENDING** |
|
|
106
|
+
|
|
107
|
+
Count each: `completed`, `failed`, `skipped`, `inProgress`, `pending`.
|
|
108
|
+
`total` = number of keys in `taskMap`.
|
|
109
|
+
`remaining` = `inProgress` + `pending`.
|
|
110
|
+
|
|
111
|
+
## Step 9: Generate handoff.md
|
|
112
|
+
|
|
113
|
+
Write `.fractal-planner/plans/{planId}/handoff.md` with this structure:
|
|
114
|
+
|
|
115
|
+
```markdown
|
|
116
|
+
# Handoff: {planId}
|
|
117
|
+
Generated: {ISO timestamp}
|
|
118
|
+
|
|
119
|
+
## Progress
|
|
120
|
+
Completed: {completed}/{total} | Failed: {failed} | Skipped: {skipped} | Remaining: {remaining}
|
|
121
|
+
|
|
122
|
+
## Completed Tasks
|
|
123
|
+
- {planTaskId}: {description} | Iterations: {n}/{maxIterations} | Commit: {hash}
|
|
124
|
+
|
|
125
|
+
## Failed Tasks
|
|
126
|
+
- {planTaskId}: {description} | Iterations: {maxIterations}/{maxIterations} | Reason: {reason}
|
|
127
|
+
|
|
128
|
+
## Skipped Tasks
|
|
129
|
+
- {planTaskId}: {description} | Reason: {skipReason}
|
|
130
|
+
|
|
131
|
+
## In Progress (Interrupted)
|
|
132
|
+
- {planTaskId}: {description} | Iteration: {n}/{maxIterations} | Owner: {builder}
|
|
133
|
+
|
|
134
|
+
## Pending Tasks
|
|
135
|
+
- {planTaskId}: {description} | Blocked by: {deps or "none (ready)"}
|
|
136
|
+
|
|
137
|
+
## Key Discoveries
|
|
138
|
+
{verbatim entries from notepad.md ## Entries section, or "No discoveries recorded."}
|
|
139
|
+
|
|
140
|
+
## Resume Notes
|
|
141
|
+
- Iteration counts and clarification state preserved in execution-state.json
|
|
142
|
+
{- task-specific warnings based on failure patterns, if any}
|
|
143
|
+
{- "All tasks complete. No resume needed." if completed == total}
|
|
144
|
+
|
|
145
|
+
## Resume Command
|
|
146
|
+
/fp:implement {planId}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Rules:**
|
|
150
|
+
- Omit "Failed Tasks" section entirely when `failed == 0`
|
|
151
|
+
- Omit "Skipped Tasks" section entirely when `skipped == 0`
|
|
152
|
+
- Omit "In Progress (Interrupted)" section entirely when `inProgress == 0`
|
|
153
|
+
- Use description from `plan.md` lookup, not truncated subject from native task
|
|
154
|
+
- For COMPLETED: get iterations from `iterationMap[planTaskId]` (fall back to metadata.iterations), commit from metadata.commit
|
|
155
|
+
- For IN_PROGRESS: include owner from task metadata, iteration from `iterationMap[planTaskId]` (default 1)
|
|
156
|
+
- For FAILED: prefer evidence file reason (from Step 7), fall back to `failureReasons[planTaskId]` in execution-state.json
|
|
157
|
+
- For PENDING: list dependencies that are not yet completed. If all dependencies are completed (or task has none), show "none (ready)"
|
|
158
|
+
|
|
159
|
+
## Step 10: Display Summary
|
|
160
|
+
|
|
161
|
+
Present a summary to the user:
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
## Handoff Generated: {planId}
|
|
165
|
+
|
|
166
|
+
**Progress**: [{████████░░░░░░░░░░░░}] {completed}/{total} tasks ({pct}%)
|
|
167
|
+
|
|
168
|
+
| Status | Count |
|
|
169
|
+
|--------------|-------|
|
|
170
|
+
| Completed | {N} |
|
|
171
|
+
| Failed | {N} |
|
|
172
|
+
| Skipped | {N} |
|
|
173
|
+
| In Progress | {N} |
|
|
174
|
+
| Pending | {N} |
|
|
175
|
+
|
|
176
|
+
Handoff written to: `.fractal-planner/plans/{planId}/handoff.md`
|
|
177
|
+
|
|
178
|
+
Resume with: `/fp:implement {planId}`
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Build the 20-character progress bar:
|
|
182
|
+
- Filled blocks (`█`): `floor(completed / total * 20)` chars
|
|
183
|
+
- Empty blocks (`░`): remainder
|
|
184
|
+
|
|
185
|
+
If all tasks are completed, replace the resume line with:
|
|
186
|
+
> "All tasks complete. No resume needed."
|
|
187
|
+
|
|
188
|
+
## Important
|
|
189
|
+
|
|
190
|
+
- This skill is **read-only** except for writing `handoff.md` — it does not modify execution-state.json or native task files
|
|
191
|
+
- Primary source of truth: native task JSON files at `~/.claude/tasks/fp-impl-{planId}/`
|
|
192
|
+
- Secondary source of truth: `execution-state.json` (for `taskMap`, `skippedTasks`, `failureReasons`, `iterationMap`, `clarificationsUsed`)
|
|
193
|
+
- Mirrors `fp:status` patterns for task classification, fallback behavior, and progress display
|
|
194
|
+
- Multiple handoff runs overwrite `handoff.md` — the latest state is most accurate
|
|
195
|
+
- Pre-P7 execution-state.json files (without `iterationMap`/`clarificationsUsed`) are handled gracefully via `{}` defaults
|