@thierrynakoa/fire-flow 10.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.
- package/.claude-plugin/plugin.json +64 -0
- package/ARCHITECTURE-DIAGRAM.md +440 -0
- package/COMMAND-REFERENCE.md +172 -0
- package/DOMINION-FLOW-OVERVIEW.md +421 -0
- package/LICENSE +21 -0
- package/QUICK-START.md +351 -0
- package/README.md +398 -0
- package/TROUBLESHOOTING.md +264 -0
- package/agents/fire-codebase-mapper.md +484 -0
- package/agents/fire-debugger.md +535 -0
- package/agents/fire-executor.md +949 -0
- package/agents/fire-fact-checker.md +276 -0
- package/agents/fire-learncoding-explainer.md +237 -0
- package/agents/fire-learncoding-walker.md +147 -0
- package/agents/fire-planner.md +675 -0
- package/agents/fire-project-researcher.md +155 -0
- package/agents/fire-research-synthesizer.md +166 -0
- package/agents/fire-researcher.md +723 -0
- package/agents/fire-reviewer.md +499 -0
- package/agents/fire-roadmapper.md +203 -0
- package/agents/fire-verifier.md +880 -0
- package/bin/cli.js +208 -0
- package/commands/fire-0-orient.md +476 -0
- package/commands/fire-1-new.md +281 -0
- package/commands/fire-1a-discuss.md +455 -0
- package/commands/fire-2-plan.md +527 -0
- package/commands/fire-3-execute.md +1303 -0
- package/commands/fire-4-verify.md +845 -0
- package/commands/fire-5-handoff.md +515 -0
- package/commands/fire-6-resume.md +501 -0
- package/commands/fire-7-review.md +409 -0
- package/commands/fire-add-new-skill.md +598 -0
- package/commands/fire-analytics.md +499 -0
- package/commands/fire-assumptions.md +78 -0
- package/commands/fire-autonomous.md +528 -0
- package/commands/fire-brainstorm.md +413 -0
- package/commands/fire-complete-milestone.md +270 -0
- package/commands/fire-dashboard.md +375 -0
- package/commands/fire-debug.md +663 -0
- package/commands/fire-discover.md +616 -0
- package/commands/fire-double-check.md +460 -0
- package/commands/fire-execute-plan.md +182 -0
- package/commands/fire-learncoding.md +242 -0
- package/commands/fire-loop-resume.md +272 -0
- package/commands/fire-loop-stop.md +198 -0
- package/commands/fire-loop.md +1168 -0
- package/commands/fire-map-codebase.md +313 -0
- package/commands/fire-new-milestone.md +356 -0
- package/commands/fire-reflect.md +235 -0
- package/commands/fire-research.md +246 -0
- package/commands/fire-search.md +330 -0
- package/commands/fire-security-audit-repo.md +293 -0
- package/commands/fire-security-scan.md +484 -0
- package/commands/fire-session-summary.md +252 -0
- package/commands/fire-skills-diff.md +506 -0
- package/commands/fire-skills-history.md +388 -0
- package/commands/fire-skills-rollback.md +408 -0
- package/commands/fire-skills-sync.md +470 -0
- package/commands/fire-test.md +520 -0
- package/commands/fire-todos.md +335 -0
- package/commands/fire-transition.md +186 -0
- package/commands/fire-update.md +312 -0
- package/commands/fire-verify-uat.md +146 -0
- package/commands/fire-vuln-scan.md +493 -0
- package/hooks/hooks.json +16 -0
- package/hooks/run-hook.cmd +69 -0
- package/hooks/run-hook.sh +8 -0
- package/hooks/run-session-end.cmd +49 -0
- package/hooks/run-session-end.sh +7 -0
- package/hooks/session-end.sh +90 -0
- package/hooks/session-start.sh +111 -0
- package/package.json +52 -0
- package/plugin.json +7 -0
- package/references/auto-skill-extraction.md +136 -0
- package/references/behavioral-directives.md +365 -0
- package/references/blocker-tracking.md +155 -0
- package/references/checkpoints.md +165 -0
- package/references/circuit-breaker.md +410 -0
- package/references/context-engineering.md +587 -0
- package/references/decision-time-guidance.md +289 -0
- package/references/error-classification.md +326 -0
- package/references/execution-mode-intelligence.md +242 -0
- package/references/git-integration.md +217 -0
- package/references/honesty-protocols.md +304 -0
- package/references/integration-architecture.md +470 -0
- package/references/issue-to-pr-pipeline.md +150 -0
- package/references/metrics-and-trends.md +234 -0
- package/references/playwright-e2e-testing.md +326 -0
- package/references/questioning.md +125 -0
- package/references/research-improvements.md +110 -0
- package/references/skills-usage-guide.md +429 -0
- package/references/tdd.md +131 -0
- package/references/testing-enforcement.md +192 -0
- package/references/ui-brand.md +383 -0
- package/references/validation-checklist.md +456 -0
- package/references/verification-patterns.md +187 -0
- package/references/warrior-principles.md +173 -0
- package/skills-library/SKILLS-INDEX.md +588 -0
- package/skills-library/_general/frontend/html-visual-reports.md +292 -0
- package/skills-library/_general/methodology/debug-swarm-researcher-escape-hatch.md +240 -0
- package/skills-library/_general/methodology/learncoding-agentic-pattern.md +114 -0
- package/skills-library/_general/methodology/shell-autonomous-loop-fixplan.md +238 -0
- package/skills-library/basics/api-rest-basics.md +162 -0
- package/skills-library/basics/env-variables.md +96 -0
- package/skills-library/basics/error-handling-basics.md +125 -0
- package/skills-library/basics/git-commit-conventions.md +106 -0
- package/skills-library/basics/readme-template.md +108 -0
- package/skills-library/common-tasks/async-await-patterns.md +157 -0
- package/skills-library/common-tasks/auth-jwt-basics.md +164 -0
- package/skills-library/common-tasks/database-schema-design.md +166 -0
- package/skills-library/common-tasks/file-upload-basics.md +166 -0
- package/skills-library/common-tasks/form-validation.md +159 -0
- package/skills-library/debugging/FAILURE_TAXONOMY_CLASSIFICATION.md +117 -0
- package/skills-library/debugging/THREE_AGENT_HYPOTHESIS_DEBUGGING.md +86 -0
- package/skills-library/methodology/BREATH_BASED_PARALLEL_EXECUTION.md +678 -0
- package/skills-library/methodology/CONFIDENCE_GATED_EXECUTION.md +243 -0
- package/skills-library/methodology/EVIDENCE_BASED_VALIDATION.md +308 -0
- package/skills-library/methodology/MULTI_PERSPECTIVE_CODE_REVIEW.md +330 -0
- package/skills-library/methodology/PATH_VERIFICATION_GATE.md +211 -0
- package/skills-library/methodology/REFLEXION_MEMORY_PATTERN.md +183 -0
- package/skills-library/methodology/RESEARCH_BACKED_WORKFLOW_UPGRADE.md +263 -0
- package/skills-library/methodology/SABBATH_REST_PATTERN.md +267 -0
- package/skills-library/methodology/STONE_AND_SCAFFOLD.md +220 -0
- package/skills-library/performance/cache-augmented-generation.md +172 -0
- package/skills-library/quality-safety/debugging-steps.md +147 -0
- package/skills-library/quality-safety/deployment-checklist.md +155 -0
- package/skills-library/quality-safety/security-checklist.md +204 -0
- package/skills-library/quality-safety/testing-basics.md +180 -0
- package/skills-library/security/agent-security-scanner.md +445 -0
- package/skills-library/specialists/api-architecture/api-designer.md +49 -0
- package/skills-library/specialists/api-architecture/graphql-architect.md +49 -0
- package/skills-library/specialists/api-architecture/mcp-developer.md +51 -0
- package/skills-library/specialists/api-architecture/microservices-architect.md +50 -0
- package/skills-library/specialists/api-architecture/websocket-engineer.md +48 -0
- package/skills-library/specialists/backend/django-expert.md +52 -0
- package/skills-library/specialists/backend/fastapi-expert.md +52 -0
- package/skills-library/specialists/backend/laravel-specialist.md +52 -0
- package/skills-library/specialists/backend/nestjs-expert.md +51 -0
- package/skills-library/specialists/backend/rails-expert.md +53 -0
- package/skills-library/specialists/backend/spring-boot-engineer.md +56 -0
- package/skills-library/specialists/data-ml/fine-tuning-expert.md +48 -0
- package/skills-library/specialists/data-ml/ml-pipeline.md +47 -0
- package/skills-library/specialists/data-ml/pandas-pro.md +47 -0
- package/skills-library/specialists/data-ml/rag-architect.md +51 -0
- package/skills-library/specialists/data-ml/spark-engineer.md +47 -0
- package/skills-library/specialists/frontend/angular-architect.md +52 -0
- package/skills-library/specialists/frontend/flutter-expert.md +51 -0
- package/skills-library/specialists/frontend/nextjs-developer.md +54 -0
- package/skills-library/specialists/frontend/react-native-expert.md +50 -0
- package/skills-library/specialists/frontend/vue-expert.md +51 -0
- package/skills-library/specialists/infrastructure/chaos-engineer.md +74 -0
- package/skills-library/specialists/infrastructure/cloud-architect.md +70 -0
- package/skills-library/specialists/infrastructure/database-optimizer.md +64 -0
- package/skills-library/specialists/infrastructure/devops-engineer.md +70 -0
- package/skills-library/specialists/infrastructure/kubernetes-specialist.md +52 -0
- package/skills-library/specialists/infrastructure/monitoring-expert.md +70 -0
- package/skills-library/specialists/infrastructure/sre-engineer.md +70 -0
- package/skills-library/specialists/infrastructure/terraform-engineer.md +51 -0
- package/skills-library/specialists/languages/cpp-pro.md +74 -0
- package/skills-library/specialists/languages/csharp-developer.md +69 -0
- package/skills-library/specialists/languages/dotnet-core-expert.md +54 -0
- package/skills-library/specialists/languages/golang-pro.md +51 -0
- package/skills-library/specialists/languages/java-architect.md +49 -0
- package/skills-library/specialists/languages/javascript-pro.md +68 -0
- package/skills-library/specialists/languages/kotlin-specialist.md +68 -0
- package/skills-library/specialists/languages/php-pro.md +49 -0
- package/skills-library/specialists/languages/python-pro.md +52 -0
- package/skills-library/specialists/languages/react-expert.md +51 -0
- package/skills-library/specialists/languages/rust-engineer.md +50 -0
- package/skills-library/specialists/languages/sql-pro.md +56 -0
- package/skills-library/specialists/languages/swift-expert.md +69 -0
- package/skills-library/specialists/languages/typescript-pro.md +51 -0
- package/skills-library/specialists/platform/atlassian-mcp.md +52 -0
- package/skills-library/specialists/platform/embedded-systems.md +53 -0
- package/skills-library/specialists/platform/game-developer.md +53 -0
- package/skills-library/specialists/platform/salesforce-developer.md +53 -0
- package/skills-library/specialists/platform/shopify-expert.md +49 -0
- package/skills-library/specialists/platform/wordpress-pro.md +49 -0
- package/skills-library/specialists/quality/code-documenter.md +51 -0
- package/skills-library/specialists/quality/code-reviewer.md +67 -0
- package/skills-library/specialists/quality/debugging-wizard.md +51 -0
- package/skills-library/specialists/quality/fullstack-guardian.md +51 -0
- package/skills-library/specialists/quality/legacy-modernizer.md +50 -0
- package/skills-library/specialists/quality/playwright-expert.md +65 -0
- package/skills-library/specialists/quality/spec-miner.md +56 -0
- package/skills-library/specialists/quality/test-master.md +65 -0
- package/skills-library/specialists/security/secure-code-guardian.md +55 -0
- package/skills-library/specialists/security/security-reviewer.md +53 -0
- package/skills-library/specialists/workflow/architecture-designer.md +53 -0
- package/skills-library/specialists/workflow/cli-developer.md +70 -0
- package/skills-library/specialists/workflow/feature-forge.md +65 -0
- package/skills-library/specialists/workflow/prompt-engineer.md +54 -0
- package/skills-library/specialists/workflow/the-fool.md +62 -0
- package/templates/ASSUMPTIONS.md +125 -0
- package/templates/BLOCKERS.md +73 -0
- package/templates/DECISION_LOG.md +116 -0
- package/templates/UAT.md +96 -0
- package/templates/blueprint.md +94 -0
- package/templates/brainstorm.md +185 -0
- package/templates/conscience.md +92 -0
- package/templates/fire-handoff.md +159 -0
- package/templates/metrics.md +67 -0
- package/templates/phase-prompt.md +142 -0
- package/templates/record.md +131 -0
- package/templates/review-report.md +117 -0
- package/templates/skills-index.md +157 -0
- package/templates/verification.md +149 -0
- package/templates/vision.md +79 -0
- package/validation-config.yml +793 -0
- package/version.json +7 -0
- package/workflows/execute-phase.md +732 -0
- package/workflows/handoff-session.md +678 -0
- package/workflows/new-project.md +578 -0
- package/workflows/plan-phase.md +592 -0
- package/workflows/verify-phase.md +874 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: shell-autonomous-loop-fixplan
|
|
3
|
+
category: methodology
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
contributed: 2026-03-04
|
|
6
|
+
contributor: dominion-flow-v2
|
|
7
|
+
last_updated: 2026-03-04
|
|
8
|
+
tags: [autonomous, shell-loop, fix_plan, circuit-breaker, session-management, context-limits, ralph-pattern]
|
|
9
|
+
difficulty: hard
|
|
10
|
+
usage_count: 0
|
|
11
|
+
success_rate: 100
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Shell-Level Autonomous Loop with @fix_plan.md
|
|
15
|
+
|
|
16
|
+
## Problem
|
|
17
|
+
|
|
18
|
+
Conversation-level autonomous loops (`/fire-loop`, while-loops inside a single Claude session)
|
|
19
|
+
degrade over time: context fills up, the model loses track of early decisions, and performance
|
|
20
|
+
drops. For long-running tasks (10+ iterations, multi-phase builds, complex debugging), the loop
|
|
21
|
+
**must** run at the shell level — spawning fresh Claude CLI sessions per iteration while
|
|
22
|
+
preserving task continuity through a persistent task file.
|
|
23
|
+
|
|
24
|
+
**Symptoms of the conversation-loop problem:**
|
|
25
|
+
- AI starts repeating work it already did
|
|
26
|
+
- Circuit breaker fires due to output decline (context is full, responses get shorter)
|
|
27
|
+
- Task list lives only in conversation — lost on restart
|
|
28
|
+
- No rate limiting — hits API limits unexpectedly
|
|
29
|
+
- Can't reattach to a running loop after terminal disconnect
|
|
30
|
+
|
|
31
|
+
## Solution Pattern
|
|
32
|
+
|
|
33
|
+
Implement a **bash loop** that spawns `claude --resume <session_id>` on each iteration.
|
|
34
|
+
The AI reads `@fix_plan.md` (a persistent markdown checklist on disk) at the start of
|
|
35
|
+
every fresh session, does one task, checks it off, and writes `EXIT_SIGNAL=true` when done.
|
|
36
|
+
The shell script detects this signal and exits cleanly.
|
|
37
|
+
|
|
38
|
+
**Key insight from bmalph/Ralph:** The shell owns the loop. Claude owns the task.
|
|
39
|
+
The `@fix_plan.md` file is the shared state between them — it survives context resets,
|
|
40
|
+
restarts, disconnects, and rate limit cooldowns.
|
|
41
|
+
|
|
42
|
+
### The Three-Layer Architecture
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
SHELL LAYER (bash script)
|
|
46
|
+
├── Rate limiting (MAX_CALLS_PER_HOUR)
|
|
47
|
+
├── Session management (--resume <id>, expiry after 24h)
|
|
48
|
+
├── Circuit breaker (stagnation / error / output-decline)
|
|
49
|
+
└── EXIT_SIGNAL + BLOCKED_TASK detection
|
|
50
|
+
|
|
51
|
+
TASK LAYER (@fix_plan.md on disk)
|
|
52
|
+
├── [ ] TASK-001: ... AC: ...
|
|
53
|
+
├── [x] TASK-002: ... (completed)
|
|
54
|
+
└── EXIT_SIGNAL=false → EXIT_SIGNAL=true when done
|
|
55
|
+
|
|
56
|
+
CLAUDE LAYER (fresh session each iteration)
|
|
57
|
+
├── Reads @fix_plan.md + PROJECT_CONTEXT.md
|
|
58
|
+
├── Works on next unchecked task
|
|
59
|
+
├── Checks it off [x]
|
|
60
|
+
└── Writes EXIT_SIGNAL=true when all done
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Code Example
|
|
64
|
+
|
|
65
|
+
### @fix_plan.md format
|
|
66
|
+
|
|
67
|
+
```markdown
|
|
68
|
+
# @fix_plan — My Project
|
|
69
|
+
|
|
70
|
+
> AI: Read this at the start of every iteration. Check off completed tasks [x].
|
|
71
|
+
> When ALL tasks are checked, write EXIT_SIGNAL=true.
|
|
72
|
+
|
|
73
|
+
## Phase 1 — Schema
|
|
74
|
+
|
|
75
|
+
- [ ] TASK-001: Create user table migration
|
|
76
|
+
- AC: `npm run db:migrate` runs without errors
|
|
77
|
+
- Files: prisma/schema.prisma, migrations/
|
|
78
|
+
|
|
79
|
+
- [ ] TASK-002: Add email + created_at indexes
|
|
80
|
+
- AC: `EXPLAIN` shows index usage on user queries
|
|
81
|
+
- Files: prisma/schema.prisma
|
|
82
|
+
|
|
83
|
+
## Phase 2 — API
|
|
84
|
+
|
|
85
|
+
- [ ] TASK-003: Build POST /api/users endpoint
|
|
86
|
+
- AC: Returns 201 + user object, Playwright smoke passes
|
|
87
|
+
- Files: src/routes/users.ts, src/controllers/users.ts
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
EXIT_SIGNAL=false
|
|
92
|
+
|
|
93
|
+
<!--
|
|
94
|
+
AI: Check boxes [ ] → [x] as you complete tasks.
|
|
95
|
+
If BLOCKED: write BLOCKED_TASK=TASK-NNN on its own line, then
|
|
96
|
+
Reason: [what you tried and why you're stuck]
|
|
97
|
+
When all [x]: change EXIT_SIGNAL=false → EXIT_SIGNAL=true
|
|
98
|
+
-->
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### dominion_loop.sh (core loop)
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
#!/usr/bin/env bash
|
|
105
|
+
set -euo pipefail
|
|
106
|
+
|
|
107
|
+
PROJECT_DIR="${PROJECT_DIR:-$(pwd)}"
|
|
108
|
+
MAX_CALLS_PER_HOUR="${MAX_CALLS_PER_HOUR:-50}"
|
|
109
|
+
MAX_ITERATIONS="${MAX_ITERATIONS:-100}"
|
|
110
|
+
CIRCUIT_STAGNATION_LIMIT="${CIRCUIT_STAGNATION_LIMIT:-3}"
|
|
111
|
+
CIRCUIT_ERROR_LIMIT="${CIRCUIT_ERROR_LIMIT:-5}"
|
|
112
|
+
SESSION_EXPIRY_SECS="${SESSION_EXPIRY_SECS:-86400}"
|
|
113
|
+
|
|
114
|
+
FIX_PLAN="$PROJECT_DIR/.planning/@fix_plan.md"
|
|
115
|
+
SESSION_FILE="$PROJECT_DIR/.planning/.loop-session"
|
|
116
|
+
|
|
117
|
+
# Load per-project config override
|
|
118
|
+
[ -f "$PROJECT_DIR/.planning/dominion.rc" ] && source "$PROJECT_DIR/.planning/dominion.rc"
|
|
119
|
+
|
|
120
|
+
count_checked() { grep -c '^\- \[x\]' "$FIX_PLAN" 2>/dev/null || echo 0; }
|
|
121
|
+
|
|
122
|
+
SESSION_ID=""
|
|
123
|
+
if [ -f "$SESSION_FILE" ]; then
|
|
124
|
+
SESSION_ID=$(jq -r '.sessionId // empty' "$SESSION_FILE" 2>/dev/null || echo "")
|
|
125
|
+
SESSION_AGE=$(( $(date +%s) - $(jq -r '.createdAt // 0' "$SESSION_FILE" 2>/dev/null) ))
|
|
126
|
+
[ "$SESSION_AGE" -gt "$SESSION_EXPIRY_SECS" ] && SESSION_ID="" && rm -f "$SESSION_FILE"
|
|
127
|
+
fi
|
|
128
|
+
|
|
129
|
+
CALL_WINDOW_START=$(date +%s)
|
|
130
|
+
CALLS_THIS_WINDOW=0
|
|
131
|
+
CB_STAGNATION=0
|
|
132
|
+
CB_ERRORS=0
|
|
133
|
+
CB_LAST_CHECKED=0
|
|
134
|
+
ITERATION=0
|
|
135
|
+
|
|
136
|
+
PROMPT="Read .planning/@fix_plan.md and .planning/PROJECT_CONTEXT.md.
|
|
137
|
+
Work on the next unchecked task [ ]. Update it to [x] when done.
|
|
138
|
+
If BLOCKED after genuine attempts: write BLOCKED_TASK=TASK-NNN then Reason: [why].
|
|
139
|
+
When ALL tasks are [x]: write EXIT_SIGNAL=true in @fix_plan.md."
|
|
140
|
+
|
|
141
|
+
while [ "$ITERATION" -lt "$MAX_ITERATIONS" ]; do
|
|
142
|
+
ITERATION=$(( ITERATION + 1 ))
|
|
143
|
+
CHECKED=$(count_checked)
|
|
144
|
+
|
|
145
|
+
# Rate limiting
|
|
146
|
+
NOW=$(date +%s); ELAPSED=$(( NOW - CALL_WINDOW_START ))
|
|
147
|
+
[ "$ELAPSED" -ge 3600 ] && { CALL_WINDOW_START=$NOW; CALLS_THIS_WINDOW=0; }
|
|
148
|
+
[ "$CALLS_THIS_WINDOW" -ge "$MAX_CALLS_PER_HOUR" ] && { sleep $(( 3600 - ELAPSED )); CALL_WINDOW_START=$(date +%s); CALLS_THIS_WINDOW=0; }
|
|
149
|
+
CALLS_THIS_WINDOW=$(( CALLS_THIS_WINDOW + 1 ))
|
|
150
|
+
|
|
151
|
+
# Build and run claude command
|
|
152
|
+
RESUME_FLAG=""; [ -n "$SESSION_ID" ] && RESUME_FLAG="--resume $SESSION_ID"
|
|
153
|
+
TMPOUT=$(mktemp)
|
|
154
|
+
HAD_ERROR="false"
|
|
155
|
+
|
|
156
|
+
# shellcheck disable=SC2086
|
|
157
|
+
claude --output-format json \
|
|
158
|
+
--allowedTools 'Write,Read,Edit,Glob,Grep,Bash,Task,TodoWrite,WebSearch,WebFetch' \
|
|
159
|
+
$RESUME_FLAG -p "$PROMPT" > "$TMPOUT" 2>&1 || HAD_ERROR="true"
|
|
160
|
+
|
|
161
|
+
# Capture session ID on first run
|
|
162
|
+
if [ -z "$SESSION_ID" ]; then
|
|
163
|
+
SID=$(jq -r '.sessionId // empty' "$TMPOUT" 2>/dev/null || echo "")
|
|
164
|
+
[ -n "$SID" ] && SESSION_ID="$SID" && printf '{"sessionId":"%s","createdAt":%s}' "$SID" "$(date +%s)" > "$SESSION_FILE"
|
|
165
|
+
fi
|
|
166
|
+
|
|
167
|
+
# Check exit conditions
|
|
168
|
+
grep -q 'EXIT_SIGNAL=true' "$FIX_PLAN" 2>/dev/null && { echo "✓ Done."; rm -f "$TMPOUT"; exit 0; }
|
|
169
|
+
|
|
170
|
+
if grep -q 'BLOCKED_TASK=' "$TMPOUT" 2>/dev/null; then
|
|
171
|
+
BLOCKED=$(grep 'BLOCKED_TASK=' "$TMPOUT" | head -1)
|
|
172
|
+
printf '{"blocked":true,"task":"%s","iteration":%s}' "$BLOCKED" "$ITERATION" > "$PROJECT_DIR/.planning/loop-blocked.json"
|
|
173
|
+
echo "⚠ BLOCKED: $BLOCKED"; rm -f "$TMPOUT"; exit 2
|
|
174
|
+
fi
|
|
175
|
+
|
|
176
|
+
# Circuit breaker
|
|
177
|
+
NEW_CHECKED=$(count_checked)
|
|
178
|
+
[ "$NEW_CHECKED" -le "$CB_LAST_CHECKED" ] && CB_STAGNATION=$(( CB_STAGNATION + 1 )) || { CB_STAGNATION=0; CB_LAST_CHECKED=$NEW_CHECKED; }
|
|
179
|
+
[ "$HAD_ERROR" = "true" ] && CB_ERRORS=$(( CB_ERRORS + 1 )) || CB_ERRORS=0
|
|
180
|
+
[ "$CB_STAGNATION" -ge "$CIRCUIT_STAGNATION_LIMIT" ] && { echo "⚡ Stagnation. Cooling down 30m."; sleep 1800; CB_STAGNATION=0; }
|
|
181
|
+
[ "$CB_ERRORS" -ge "$CIRCUIT_ERROR_LIMIT" ] && { echo "⚡ Error limit. Halting."; exit 1; }
|
|
182
|
+
|
|
183
|
+
rm -f "$TMPOUT"; sleep 2
|
|
184
|
+
done
|
|
185
|
+
exit 1
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Implementation Steps
|
|
189
|
+
|
|
190
|
+
1. **Generate @fix_plan.md** — run `/fire-implement` (or manually write tasks with `- [ ] TASK-NNN:` format + `AC:` acceptance criteria)
|
|
191
|
+
2. **Generate PROJECT_CONTEXT.md** — consolidated planning docs in one file the AI reads per iteration
|
|
192
|
+
3. **Copy dominion.rc** — set `MAX_CALLS_PER_HOUR`, `MAX_ITERATIONS`, circuit breaker thresholds
|
|
193
|
+
4. **Run the loop** — `bash dominion_loop.sh --project-dir $(pwd)` or via `/fire-loop`
|
|
194
|
+
5. **Monitor** — `cat .planning/loop-status.json` or `/fire-dashboard`
|
|
195
|
+
6. **Handle BLOCKED** — loop exits code 2, read `.planning/loop-blocked.json`, invoke researcher
|
|
196
|
+
|
|
197
|
+
## When to Use
|
|
198
|
+
|
|
199
|
+
- Task requires >10 AI iterations to complete
|
|
200
|
+
- Multi-phase feature build (schema → API → UI → tests)
|
|
201
|
+
- Long-running autonomous execution where context bloat is a real risk
|
|
202
|
+
- You want rate limiting and circuit breaking enforced at the OS level
|
|
203
|
+
- Task must survive terminal disconnects or restarts
|
|
204
|
+
- You need a reattachable, resumable execution that persists across sessions
|
|
205
|
+
|
|
206
|
+
## When NOT to Use
|
|
207
|
+
|
|
208
|
+
- Simple 1-3 iteration tasks (conversation loop is fine)
|
|
209
|
+
- No `claude` CLI available in PATH
|
|
210
|
+
- Task requires continuous human judgment at each step (use manual `/fire-3-execute`)
|
|
211
|
+
- Project has no `.planning/` structure yet (run `/fire-1-new` first)
|
|
212
|
+
|
|
213
|
+
## Common Mistakes
|
|
214
|
+
|
|
215
|
+
- **Vague acceptance criteria** — if AC is unclear, AI marks tasks done prematurely. Write AC as a testable command: `npm test passes`, `Playwright smoke green`, `tsc --noEmit returns 0`
|
|
216
|
+
- **Too many tasks per @fix_plan.md** — keep tasks 15-30 min each. Huge tasks cause stagnation (CB fires before completion)
|
|
217
|
+
- **Missing PROJECT_CONTEXT.md** — without it, each fresh session lacks planning context and the AI reinvents decisions. Always run `/fire-implement` to generate it
|
|
218
|
+
- **Forgetting exit code 2** — if your orchestrator calls the loop, check exit code 2 = BLOCKED (needs researcher), not just 0 = done and 1 = error
|
|
219
|
+
|
|
220
|
+
## Exit Codes
|
|
221
|
+
|
|
222
|
+
| Code | Meaning | Action |
|
|
223
|
+
|------|---------|--------|
|
|
224
|
+
| 0 | `EXIT_SIGNAL=true` — all tasks complete | Proceed to verification |
|
|
225
|
+
| 1 | Circuit breaker halt or max iterations | Investigate `.planning/loop-status.json` |
|
|
226
|
+
| 2 | `BLOCKED_TASK` detected | Read `.planning/loop-blocked.json`, invoke researcher |
|
|
227
|
+
|
|
228
|
+
## Related Skills
|
|
229
|
+
|
|
230
|
+
- [autonomous-multi-phase-build](autonomous-multi-phase-build.md) — phase-level orchestration within conversation
|
|
231
|
+
- [multi-project-autonomous-build](multi-project-autonomous-build.md) — running multiple projects autonomously
|
|
232
|
+
|
|
233
|
+
## References
|
|
234
|
+
|
|
235
|
+
- Inspired by: [bmalph](https://github.com/LarsCowe/bmalph) — Ralph autonomous loop pattern
|
|
236
|
+
- Ralph loop architecture: `ralph_loop.sh` in bmalph v2.7.0
|
|
237
|
+
- Gap analysis session: 2026-03-04 dominion-flow-v2 implementation
|
|
238
|
+
- Contributed from: dominion-flow-v2 build session
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Skill: REST API Basics
|
|
2
|
+
|
|
3
|
+
**Category:** Basics
|
|
4
|
+
**Difficulty:** Beginner
|
|
5
|
+
**Applies to:** Node.js/Express, Python/Flask, any backend
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## What is a REST API?
|
|
10
|
+
|
|
11
|
+
A REST API is how two programs talk to each other over the internet. Your frontend sends a request; your backend sends back data. Every request has:
|
|
12
|
+
|
|
13
|
+
- **Method** — what action to take (GET, POST, PUT, DELETE)
|
|
14
|
+
- **URL** — what resource to act on
|
|
15
|
+
- **Body** — data sent with the request (POST/PUT only)
|
|
16
|
+
- **Status code** — whether it worked
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## The 4 Methods
|
|
21
|
+
|
|
22
|
+
| Method | Action | Example |
|
|
23
|
+
|--------|--------|---------|
|
|
24
|
+
| `GET` | Read data | Get a list of users |
|
|
25
|
+
| `POST` | Create new data | Create a new user |
|
|
26
|
+
| `PUT` / `PATCH` | Update existing data | Update a user's email |
|
|
27
|
+
| `DELETE` | Remove data | Delete a user |
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## URL Design
|
|
32
|
+
|
|
33
|
+
Good URLs describe resources (nouns), not actions (verbs):
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
# GOOD
|
|
37
|
+
GET /api/users → list all users
|
|
38
|
+
GET /api/users/42 → get user with id 42
|
|
39
|
+
POST /api/users → create a new user
|
|
40
|
+
PUT /api/users/42 → update user 42
|
|
41
|
+
DELETE /api/users/42 → delete user 42
|
|
42
|
+
|
|
43
|
+
# BAD
|
|
44
|
+
GET /api/getUsers
|
|
45
|
+
POST /api/createUser
|
|
46
|
+
GET /api/deleteUser?id=42
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Building a REST API (Express)
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
const express = require('express');
|
|
55
|
+
const router = express.Router();
|
|
56
|
+
|
|
57
|
+
// GET all users
|
|
58
|
+
router.get('/', async (req, res) => {
|
|
59
|
+
const users = await db.query('SELECT id, name, email FROM users');
|
|
60
|
+
res.json(users);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// GET single user
|
|
64
|
+
router.get('/:id', async (req, res) => {
|
|
65
|
+
const user = await db.query('SELECT * FROM users WHERE id = $1', [req.params.id]);
|
|
66
|
+
if (!user) return res.status(404).json({ error: 'User not found' });
|
|
67
|
+
res.json(user);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// POST create user
|
|
71
|
+
router.post('/', async (req, res) => {
|
|
72
|
+
const { name, email } = req.body;
|
|
73
|
+
if (!name || !email) return res.status(400).json({ error: 'name and email required' });
|
|
74
|
+
const user = await db.query(
|
|
75
|
+
'INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *',
|
|
76
|
+
[name, email]
|
|
77
|
+
);
|
|
78
|
+
res.status(201).json(user);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// PUT update user
|
|
82
|
+
router.put('/:id', async (req, res) => {
|
|
83
|
+
const { name, email } = req.body;
|
|
84
|
+
const user = await db.query(
|
|
85
|
+
'UPDATE users SET name=$1, email=$2 WHERE id=$3 RETURNING *',
|
|
86
|
+
[name, email, req.params.id]
|
|
87
|
+
);
|
|
88
|
+
if (!user) return res.status(404).json({ error: 'User not found' });
|
|
89
|
+
res.json(user);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// DELETE user
|
|
93
|
+
router.delete('/:id', async (req, res) => {
|
|
94
|
+
await db.query('DELETE FROM users WHERE id = $1', [req.params.id]);
|
|
95
|
+
res.status(204).send();
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
module.exports = router;
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
```js
|
|
102
|
+
// In app.js
|
|
103
|
+
app.use('/api/users', require('./routes/users'));
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Calling an API (Frontend)
|
|
109
|
+
|
|
110
|
+
```js
|
|
111
|
+
// GET
|
|
112
|
+
const response = await fetch('/api/users');
|
|
113
|
+
const users = await response.json();
|
|
114
|
+
|
|
115
|
+
// POST
|
|
116
|
+
const response = await fetch('/api/users', {
|
|
117
|
+
method: 'POST',
|
|
118
|
+
headers: { 'Content-Type': 'application/json' },
|
|
119
|
+
body: JSON.stringify({ name: 'Jane', email: 'jane@example.com' })
|
|
120
|
+
});
|
|
121
|
+
const newUser = await response.json();
|
|
122
|
+
|
|
123
|
+
// DELETE
|
|
124
|
+
await fetch(`/api/users/${userId}`, { method: 'DELETE' });
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Always Return Consistent JSON
|
|
130
|
+
|
|
131
|
+
```js
|
|
132
|
+
// Success
|
|
133
|
+
res.status(200).json({ data: user });
|
|
134
|
+
|
|
135
|
+
// Error
|
|
136
|
+
res.status(400).json({ error: 'Email is required' });
|
|
137
|
+
|
|
138
|
+
// Created
|
|
139
|
+
res.status(201).json({ data: newUser, message: 'User created' });
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Pick a format and use it everywhere. Inconsistent responses break the frontend.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Testing Your API Without a Frontend
|
|
147
|
+
|
|
148
|
+
Use these tools to send requests manually:
|
|
149
|
+
- **Thunder Client** — VS Code extension, simplest option
|
|
150
|
+
- **Postman** — full-featured GUI
|
|
151
|
+
- **curl** — terminal, always available:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
curl http://localhost:3000/api/users
|
|
155
|
+
curl -X POST http://localhost:3000/api/users \
|
|
156
|
+
-H "Content-Type: application/json" \
|
|
157
|
+
-d '{"name":"Jane","email":"jane@example.com"}'
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
*Fire Flow Skills Library — MIT License*
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Skill: Environment Variables
|
|
2
|
+
|
|
3
|
+
**Category:** Basics
|
|
4
|
+
**Difficulty:** Beginner
|
|
5
|
+
**Applies to:** Every project
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## The Problem
|
|
10
|
+
|
|
11
|
+
You need a database password, an API key, or a secret token in your code.
|
|
12
|
+
If you type it directly into your code and push to GitHub, **anyone can see it**.
|
|
13
|
+
Even if you delete it later, it stays in the git history forever.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## The Solution: `.env` Files
|
|
18
|
+
|
|
19
|
+
Store secrets in a `.env` file. Never commit that file to git.
|
|
20
|
+
|
|
21
|
+
### Step 1 — Create `.env` in your project root
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
DATABASE_URL=postgresql://user:password@localhost:5432/mydb
|
|
25
|
+
JWT_SECRET=some-long-random-string-here
|
|
26
|
+
STRIPE_KEY=sk_live_abc123
|
|
27
|
+
PORT=3000
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Step 2 — Add `.env` to `.gitignore`
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
# .gitignore
|
|
34
|
+
.env
|
|
35
|
+
.env.local
|
|
36
|
+
.env.production
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Do this **before** your first commit. Once a secret is committed, you must rotate it (generate a new one) — the old one is compromised.
|
|
40
|
+
|
|
41
|
+
### Step 3 — Read variables in your code
|
|
42
|
+
|
|
43
|
+
**Node.js:**
|
|
44
|
+
```js
|
|
45
|
+
// Install: npm install dotenv
|
|
46
|
+
require('dotenv').config();
|
|
47
|
+
|
|
48
|
+
const dbUrl = process.env.DATABASE_URL;
|
|
49
|
+
const port = process.env.PORT || 3000;
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Python:**
|
|
53
|
+
```python
|
|
54
|
+
# Install: pip install python-dotenv
|
|
55
|
+
from dotenv import load_dotenv
|
|
56
|
+
import os
|
|
57
|
+
|
|
58
|
+
load_dotenv()
|
|
59
|
+
db_url = os.getenv('DATABASE_URL')
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Step 4 — Create `.env.example` for teammates
|
|
63
|
+
|
|
64
|
+
This file IS committed. It shows what variables are needed, but with no real values:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
DATABASE_URL=postgresql://user:password@localhost:5432/yourdb
|
|
68
|
+
JWT_SECRET=replace-with-a-long-random-string
|
|
69
|
+
STRIPE_KEY=sk_live_your-key-here
|
|
70
|
+
PORT=3000
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Rules to Never Break
|
|
76
|
+
|
|
77
|
+
| Rule | Why |
|
|
78
|
+
|------|-----|
|
|
79
|
+
| Never commit `.env` | Secrets in git are permanent |
|
|
80
|
+
| Always commit `.env.example` | Teammates need to know what variables exist |
|
|
81
|
+
| Rotate any key that was ever committed | Assume it was seen the moment it was pushed |
|
|
82
|
+
| Use different secrets for dev and production | A leaked dev key should not touch production |
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Quick Check
|
|
87
|
+
|
|
88
|
+
Before every commit, run:
|
|
89
|
+
```bash
|
|
90
|
+
git diff --cached | grep -i "password\|secret\|key\|token"
|
|
91
|
+
```
|
|
92
|
+
If you see real values, stop and move them to `.env`.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
*Fire Flow Skills Library — MIT License*
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# Skill: Error Handling Basics
|
|
2
|
+
|
|
3
|
+
**Category:** Basics
|
|
4
|
+
**Difficulty:** Beginner
|
|
5
|
+
**Applies to:** Node.js, Python, any backend
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## The Problem
|
|
10
|
+
|
|
11
|
+
When code crashes, users see a blank screen or a raw error message with your file paths exposed. Worse — you have no idea it happened because nothing was logged.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## The Solution: Catch, Log, Respond
|
|
16
|
+
|
|
17
|
+
Three things happen when an error occurs:
|
|
18
|
+
1. **Catch** it — don't let it bubble up and crash the app
|
|
19
|
+
2. **Log** it — record enough detail to debug later
|
|
20
|
+
3. **Respond** — send a clean message to the user, never the raw error
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Pattern 1: Try/Catch (Node.js)
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
// BAD — no error handling
|
|
28
|
+
app.get('/users/:id', async (req, res) => {
|
|
29
|
+
const user = await db.query('SELECT * FROM users WHERE id = $1', [req.params.id]);
|
|
30
|
+
res.json(user);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// GOOD — caught, logged, clean response
|
|
34
|
+
app.get('/users/:id', async (req, res) => {
|
|
35
|
+
try {
|
|
36
|
+
const user = await db.query('SELECT * FROM users WHERE id = $1', [req.params.id]);
|
|
37
|
+
if (!user) return res.status(404).json({ error: 'User not found' });
|
|
38
|
+
res.json(user);
|
|
39
|
+
} catch (err) {
|
|
40
|
+
console.error('GET /users/:id failed:', err.message);
|
|
41
|
+
res.status(500).json({ error: 'Something went wrong. Please try again.' });
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Pattern 2: Global Error Middleware (Express)
|
|
49
|
+
|
|
50
|
+
Catch every unhandled error in one place instead of repeating try/catch everywhere:
|
|
51
|
+
|
|
52
|
+
```js
|
|
53
|
+
// Put this LAST in your app, after all routes
|
|
54
|
+
app.use((err, req, res, next) => {
|
|
55
|
+
console.error(`[${new Date().toISOString()}] ${req.method} ${req.path}:`, err);
|
|
56
|
+
|
|
57
|
+
const status = err.status || 500;
|
|
58
|
+
const message = err.isOperational ? err.message : 'Something went wrong';
|
|
59
|
+
res.status(status).json({ error: message });
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Then in your routes, just call `next(err)` to hand off to this handler:
|
|
64
|
+
|
|
65
|
+
```js
|
|
66
|
+
app.get('/users/:id', async (req, res, next) => {
|
|
67
|
+
try {
|
|
68
|
+
const user = await db.query('SELECT * FROM users WHERE id = $1', [req.params.id]);
|
|
69
|
+
res.json(user);
|
|
70
|
+
} catch (err) {
|
|
71
|
+
next(err); // passes to global handler
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Pattern 3: Try/Except (Python)
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
# BAD
|
|
82
|
+
def get_user(user_id):
|
|
83
|
+
return db.query(f"SELECT * FROM users WHERE id = {user_id}")
|
|
84
|
+
|
|
85
|
+
# GOOD
|
|
86
|
+
def get_user(user_id):
|
|
87
|
+
try:
|
|
88
|
+
user = db.query("SELECT * FROM users WHERE id = %s", (user_id,))
|
|
89
|
+
if not user:
|
|
90
|
+
raise ValueError(f"User {user_id} not found")
|
|
91
|
+
return user
|
|
92
|
+
except ValueError as e:
|
|
93
|
+
print(f"[WARNING] {e}")
|
|
94
|
+
raise
|
|
95
|
+
except Exception as e:
|
|
96
|
+
print(f"[ERROR] get_user({user_id}) failed: {e}")
|
|
97
|
+
raise RuntimeError("Could not retrieve user") from e
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## HTTP Status Codes to Know
|
|
103
|
+
|
|
104
|
+
| Code | Meaning | Use When |
|
|
105
|
+
|------|---------|---------|
|
|
106
|
+
| 200 | OK | Success |
|
|
107
|
+
| 201 | Created | New resource created |
|
|
108
|
+
| 400 | Bad Request | User sent invalid data |
|
|
109
|
+
| 401 | Unauthorized | Not logged in |
|
|
110
|
+
| 403 | Forbidden | Logged in but no permission |
|
|
111
|
+
| 404 | Not Found | Resource doesn't exist |
|
|
112
|
+
| 500 | Server Error | Your code broke |
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Rules
|
|
117
|
+
|
|
118
|
+
- **Never send raw error objects to the client** — they expose file paths and stack traces
|
|
119
|
+
- **Always log server errors** — you need to know when things break
|
|
120
|
+
- **Distinguish user errors (4xx) from server errors (5xx)** — user errors are their fault; server errors are yours
|
|
121
|
+
- **Never swallow errors silently** — `catch (err) {}` with nothing inside is worse than no try/catch
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
*Fire Flow Skills Library — MIT License*
|