feed-the-machine 1.1.0 → 1.3.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 (92) hide show
  1. package/bin/generate-manifest.mjs +253 -0
  2. package/bin/install.mjs +372 -26
  3. package/docs/INBOX.md +233 -0
  4. package/ftm/SKILL.md +34 -0
  5. package/ftm-audit/SKILL.md +69 -0
  6. package/ftm-brainstorm/SKILL.md +51 -0
  7. package/ftm-browse/SKILL.md +39 -0
  8. package/ftm-capture/SKILL.md +370 -0
  9. package/ftm-capture.yml +4 -0
  10. package/ftm-codex-gate/SKILL.md +59 -0
  11. package/ftm-config/SKILL.md +35 -0
  12. package/ftm-council/SKILL.md +56 -0
  13. package/ftm-dashboard/SKILL.md +34 -0
  14. package/ftm-debug/SKILL.md +84 -0
  15. package/ftm-diagram/SKILL.md +44 -0
  16. package/ftm-executor/SKILL.md +97 -0
  17. package/ftm-git/SKILL.md +60 -0
  18. package/ftm-inbox/backend/__init__.py +0 -0
  19. package/ftm-inbox/backend/adapters/__init__.py +0 -0
  20. package/ftm-inbox/backend/adapters/_retry.py +64 -0
  21. package/ftm-inbox/backend/adapters/base.py +230 -0
  22. package/ftm-inbox/backend/adapters/freshservice.py +104 -0
  23. package/ftm-inbox/backend/adapters/gmail.py +125 -0
  24. package/ftm-inbox/backend/adapters/jira.py +136 -0
  25. package/ftm-inbox/backend/adapters/registry.py +192 -0
  26. package/ftm-inbox/backend/adapters/slack.py +110 -0
  27. package/ftm-inbox/backend/db/__init__.py +0 -0
  28. package/ftm-inbox/backend/db/connection.py +54 -0
  29. package/ftm-inbox/backend/db/schema.py +78 -0
  30. package/ftm-inbox/backend/executor/__init__.py +7 -0
  31. package/ftm-inbox/backend/executor/engine.py +149 -0
  32. package/ftm-inbox/backend/executor/step_runner.py +98 -0
  33. package/ftm-inbox/backend/main.py +103 -0
  34. package/ftm-inbox/backend/models/__init__.py +1 -0
  35. package/ftm-inbox/backend/models/unified_task.py +36 -0
  36. package/ftm-inbox/backend/planner/__init__.py +6 -0
  37. package/ftm-inbox/backend/planner/generator.py +127 -0
  38. package/ftm-inbox/backend/planner/schema.py +34 -0
  39. package/ftm-inbox/backend/requirements.txt +5 -0
  40. package/ftm-inbox/backend/routes/__init__.py +0 -0
  41. package/ftm-inbox/backend/routes/execute.py +186 -0
  42. package/ftm-inbox/backend/routes/health.py +52 -0
  43. package/ftm-inbox/backend/routes/inbox.py +68 -0
  44. package/ftm-inbox/backend/routes/plan.py +271 -0
  45. package/ftm-inbox/bin/launchagent.mjs +91 -0
  46. package/ftm-inbox/bin/setup.mjs +188 -0
  47. package/ftm-inbox/bin/start.sh +10 -0
  48. package/ftm-inbox/bin/status.sh +17 -0
  49. package/ftm-inbox/bin/stop.sh +8 -0
  50. package/ftm-inbox/config.example.yml +55 -0
  51. package/ftm-inbox/package-lock.json +2898 -0
  52. package/ftm-inbox/package.json +26 -0
  53. package/ftm-inbox/postcss.config.js +6 -0
  54. package/ftm-inbox/src/app.css +199 -0
  55. package/ftm-inbox/src/app.html +18 -0
  56. package/ftm-inbox/src/lib/api.ts +166 -0
  57. package/ftm-inbox/src/lib/components/ExecutionLog.svelte +81 -0
  58. package/ftm-inbox/src/lib/components/InboxFeed.svelte +143 -0
  59. package/ftm-inbox/src/lib/components/PlanStep.svelte +271 -0
  60. package/ftm-inbox/src/lib/components/PlanView.svelte +206 -0
  61. package/ftm-inbox/src/lib/components/StreamPanel.svelte +99 -0
  62. package/ftm-inbox/src/lib/components/TaskCard.svelte +190 -0
  63. package/ftm-inbox/src/lib/components/ui/EmptyState.svelte +63 -0
  64. package/ftm-inbox/src/lib/components/ui/KawaiiCard.svelte +86 -0
  65. package/ftm-inbox/src/lib/components/ui/PillButton.svelte +106 -0
  66. package/ftm-inbox/src/lib/components/ui/StatusBadge.svelte +67 -0
  67. package/ftm-inbox/src/lib/components/ui/StreamDrawer.svelte +149 -0
  68. package/ftm-inbox/src/lib/components/ui/ThemeToggle.svelte +80 -0
  69. package/ftm-inbox/src/lib/theme.ts +47 -0
  70. package/ftm-inbox/src/routes/+layout.svelte +76 -0
  71. package/ftm-inbox/src/routes/+page.svelte +401 -0
  72. package/ftm-inbox/static/favicon.png +0 -0
  73. package/ftm-inbox/svelte.config.js +12 -0
  74. package/ftm-inbox/tailwind.config.ts +63 -0
  75. package/ftm-inbox/tsconfig.json +13 -0
  76. package/ftm-inbox/vite.config.ts +6 -0
  77. package/ftm-intent/SKILL.md +44 -0
  78. package/ftm-manifest.json +3794 -0
  79. package/ftm-map/SKILL.md +50 -0
  80. package/ftm-mind/SKILL.md +173 -66
  81. package/ftm-pause/SKILL.md +43 -0
  82. package/ftm-researcher/SKILL.md +55 -0
  83. package/ftm-resume/SKILL.md +47 -0
  84. package/ftm-retro/SKILL.md +54 -0
  85. package/ftm-routine/SKILL.md +36 -0
  86. package/ftm-state/blackboard/capabilities.json +5 -0
  87. package/ftm-state/blackboard/capabilities.schema.json +27 -0
  88. package/ftm-upgrade/SKILL.md +41 -0
  89. package/hooks/ftm-blackboard-enforcer.sh +28 -27
  90. package/hooks/ftm-plan-gate.sh +21 -25
  91. package/install.sh +238 -111
  92. package/package.json +6 -2
@@ -308,3 +308,38 @@ If the YAML cannot be parsed, the skill will back up the broken file as `~/.clau
308
308
 
309
309
  ### Changes not taking effect
310
310
  Other ftm skills read the config at startup. If a ftm skill is already running, it will use the config that was active when it started. Changes apply to the next invocation.
311
+
312
+ ## Requirements
313
+
314
+ - config: `~/.claude/ftm-config.yml` | optional | main config file (created with defaults if missing)
315
+
316
+ ## Risk
317
+
318
+ - level: low_write
319
+ - scope: reads and writes ~/.claude/ftm-config.yml only; backs up malformed config to ftm-config.yml.bak before overwriting; no project files touched
320
+ - rollback: restore from ~/.claude/ftm-config.yml.bak or delete the file to reset to defaults on next invocation
321
+
322
+ ## Approval Gates
323
+
324
+ - trigger: reset command issued | action: show current config and ask "Proceed?" before restoring defaults
325
+ - trigger: invalid model name or profile name provided | action: reject with clear error showing valid options, do not write
326
+ - complexity_routing: micro → auto | small → auto | medium → auto | large → auto | xl → auto
327
+
328
+ ## Fallbacks
329
+
330
+ - condition: ftm-config.yml missing | action: create file with default balanced profile and all defaults
331
+ - condition: ftm-config.yml malformed YAML | action: back up as ftm-config.yml.bak, create fresh default config
332
+ - condition: invalid model or profile value provided | action: reject and show valid options without writing
333
+
334
+ ## Capabilities
335
+
336
+ - env: none required
337
+
338
+ ## Event Payloads
339
+
340
+ ### task_completed
341
+ - skill: string — "ftm-config"
342
+ - action: string — "display" | "set_profile" | "set_value" | "reset" | "show_profiles" | "show_skills"
343
+ - changed_key: string | null — dotted path of changed setting
344
+ - old_value: string | null — value before change
345
+ - new_value: string | null — value after change
@@ -130,3 +130,59 @@ After completing, update the blackboard:
130
130
  2. Write an experience file to `~/.claude/ftm-state/blackboard/experiences/YYYY-MM-DD_task-slug.json` capturing decision domain, verdict, round reached, dissent summary, and whether the verdict held up
131
131
  3. Update `~/.claude/ftm-state/blackboard/experiences/index.json` with the new entry
132
132
  4. Emit `task_completed` event
133
+
134
+ ## Requirements
135
+
136
+ - tool: `codex` | required | Codex CLI for independent peer investigation
137
+ - tool: `gemini` | required | Gemini CLI for independent peer investigation
138
+ - reference: `references/protocols/PREREQUISITES.md` | required | availability check, fallback logic, timeout config
139
+ - reference: `references/protocols/STEP-0-FRAMING.md` | required | problem framing format
140
+ - reference: `references/prompts/CLAUDE-INVESTIGATION.md` | required | Claude investigation prompt template
141
+ - reference: `references/prompts/CODEX-INVESTIGATION.md` | required | Codex investigation prompt template
142
+ - reference: `references/prompts/GEMINI-INVESTIGATION.md` | required | Gemini investigation prompt template
143
+ - reference: `references/prompts/REBUTTAL-TEMPLATE.md` | required | rebuttal round prompt template
144
+ - reference: `~/.claude/ftm-state/blackboard/context.json` | optional | session state
145
+
146
+ ## Risk
147
+
148
+ - level: read_only
149
+ - scope: reads codebase for independent investigation; does not modify source files; writes blackboard experience after verdict
150
+ - rollback: no source mutations; blackboard write can be reverted by editing JSON files
151
+
152
+ ## Approval Gates
153
+
154
+ - trigger: council prompt framed in Step 0 | action: show framed prompt to user and wait for confirmation before dispatching to council
155
+ - trigger: 2-of-3 majority reached | action: present verdict summary to user and ask if they want to proceed or dig into dissent
156
+ - trigger: auto-invocation by ftm-executor (INTENT.md conflict) | action: skip user framing confirmation, run immediately and return structured COUNCIL VERDICT to caller
157
+ - complexity_routing: micro → auto | small → auto | medium → auto | large → auto | xl → auto
158
+
159
+ ## Fallbacks
160
+
161
+ - condition: codex CLI not found | action: report missing dependency with install instructions and stop (do not run degraded council)
162
+ - condition: gemini CLI not found | action: report missing dependency with install instructions and stop
163
+ - condition: no majority after 5 rounds | action: synthesize final positions, highlight core tension, present 2-3 concrete options for user decision
164
+ - condition: model times out during a round | action: note timeout for that model, continue round with remaining models' responses
165
+
166
+ ## Capabilities
167
+
168
+ - cli: `codex` | required | OpenAI Codex CLI peer reviewer
169
+ - cli: `gemini` | required | Google Gemini CLI peer reviewer
170
+ - env: `OPENAI_API_KEY` | required | for Codex CLI authentication
171
+ - env: `GEMINI_API_KEY` | required | for Gemini CLI authentication
172
+
173
+ ## Event Payloads
174
+
175
+ ### review_complete
176
+ - skill: string — "ftm-council"
177
+ - verdict: string — "update_intent" | "revert_fix" | "option_a" | "option_b" | custom decision
178
+ - round: number — round in which majority was reached (1-5, or 5+ for synthesis)
179
+ - agreed_by: string[] — which models agreed on the verdict
180
+ - dissent: string | null — summary of dissenting position
181
+ - reasoning: string — why the majority won
182
+
183
+ ### task_completed
184
+ - skill: string — "ftm-council"
185
+ - decision_domain: string — topic the council deliberated on
186
+ - verdict: string — final decision
187
+ - round: number — rounds taken to reach verdict
188
+ - duration_ms: number — total deliberation time
@@ -118,6 +118,40 @@ Average plan modifications: 1.2 per plan
118
118
  - Keep output concise — one screen max
119
119
  - If data sources are empty (fresh install), show: "No data yet. Use FTM for a few sessions and check back."
120
120
 
121
+ ## Requirements
122
+
123
+ - reference: `~/.claude/ftm-state/events.log` | optional | JSONL event log for skill invocation tracking
124
+ - reference: `~/.claude/ftm-state/blackboard/context.json` | required | current session metadata
125
+ - reference: `~/.claude/ftm-state/blackboard/experiences/index.json` | optional | experience inventory and counts
126
+ - reference: `~/.claude/ftm-state/blackboard/patterns.json` | optional | pattern health for weekly stats
127
+ - reference: `~/.ftm/playbooks/` | optional | playbook use counts and stats
128
+
129
+ ## Risk
130
+
131
+ - level: read_only
132
+ - scope: reads event log and blackboard state only; does not modify any files
133
+ - rollback: no mutations to reverse
134
+
135
+ ## Approval Gates
136
+
137
+ - complexity_routing: micro → auto | small → auto | medium → auto | large → auto | xl → auto
138
+
139
+ ## Fallbacks
140
+
141
+ - condition: events.log missing or empty | action: show "No session events recorded yet" for relevant sections
142
+ - condition: blackboard context.json missing | action: show "No session data available" and suggest using FTM skills first
143
+ - condition: experiences/index.json missing | action: skip experience stats sections
144
+ - condition: playbooks directory missing | action: show 0 for all playbook stats
145
+
146
+ ## Capabilities
147
+
148
+ - env: none required
149
+
150
+ ## Event Payloads
151
+
152
+ ### (none)
153
+ ftm-dashboard is read-only and does not emit events directly. It listens to task_completed for session tracking only.
154
+
121
155
  ## Events
122
156
 
123
157
  ### Listens To
@@ -144,3 +144,87 @@ After completing, update the blackboard. Read `references/protocols/BLACKBOARD.m
144
144
  Before dispatching agents, read `~/.claude/ftm-config.yml`:
145
145
  - Use the `planning` model from the active profile for all investigation agents
146
146
  - If config missing, use session default
147
+
148
+ ## Requirements
149
+
150
+ - config: `~/.claude/ftm-config.yml` | optional | model profiles for investigation agents
151
+ - reference: `references/protocols/BLACKBOARD.md` | required | blackboard read/write protocol
152
+ - reference: `references/protocols/EDGE-CASES.md` | required | anti-patterns and fallback handling
153
+ - reference: `references/phases/PHASE-0-INTAKE.md` | required | intake steps and Explore agent prompt
154
+ - reference: `references/phases/PHASE-1-TRIAGE.md` | required | agent selection guide and worktree strategy
155
+ - reference: `references/phases/PHASE-2-WAR-ROOM-AGENTS.md` | required | all four agent prompts
156
+ - reference: `references/phases/PHASE-3-TO-6-EXECUTION.md` | required | synthesis, solver, reviewer prompts
157
+ - tool: `git` | required | worktree creation, diff inspection, commit history
158
+ - reference: `~/.claude/ftm-state/blackboard/context.json` | optional | session state
159
+ - reference: `~/.claude/ftm-state/blackboard/experiences/index.json` | optional | past bug fixes and known issues
160
+ - reference: `~/.claude/ftm-state/blackboard/patterns.json` | optional | recurring failure patterns
161
+
162
+ ## Risk
163
+
164
+ - level: medium_write
165
+ - scope: creates git worktrees for investigation and fix branches; modifies source files in Solver agent worktree; merges fix after Reviewer approval
166
+ - rollback: git worktree remove + git branch -D for debug/* worktrees; all fix changes isolated until user confirms merge
167
+
168
+ ## Approval Gates
169
+
170
+ - trigger: investigation plan formulated in Phase 0 | action: present plan to user and proceed unless user objects
171
+ - trigger: Solver produces fix | action: Reviewer agent must independently verify before presenting to user (hard gate — cannot skip)
172
+ - trigger: Reviewer APPROVED | action: present root cause + changes + evidence to user, wait for user confirmation before merging
173
+ - trigger: Solver NEEDS REWORK after 3 attempts | action: escalate to user with full context, wait for direction
174
+ - complexity_routing: micro → auto | small → auto | medium → plan_first | large → plan_first | xl → always_ask
175
+
176
+ ## Fallbacks
177
+
178
+ - condition: Instrumenter agent fails or produces no useful output | action: skip instrumentation worktree, proceed with remaining agents
179
+ - condition: Reproducer cannot create a minimal failing test | action: note as "reproduction failed", proceed with hypothesis-only approach
180
+ - condition: Researcher finds no relevant issues or docs | action: proceed with instrumentation and hypothesis findings only
181
+ - condition: fix still failing after 3 Solver iterations | action: escalate to user with all hypotheses tested and evidence gathered
182
+ - condition: project has no test suite | action: Reviewer uses build check + diff review + live runtime verification instead of test runner
183
+
184
+ ## Capabilities
185
+
186
+ - cli: `git` | required | worktree isolation for investigation agents
187
+ - mcp: `sequential-thinking` | optional | complex multi-hypothesis analysis
188
+ - mcp: `playwright` | optional | visual bug verification in Reviewer phase
189
+ - mcp: `WebSearch` | optional | Researcher agent for GitHub issues and Stack Overflow
190
+ - mcp: `WebFetch` | optional | Researcher agent for docs and changelogs
191
+
192
+ ## Event Payloads
193
+
194
+ ### bug_fixed
195
+ - skill: string — "ftm-debug"
196
+ - root_cause: string — one-sentence root cause description
197
+ - fix_approach: string — description of the fix applied
198
+ - worktree: string — path to fix worktree
199
+ - iterations: number — number of solver-reviewer cycles needed
200
+ - duration_ms: number — total war room duration
201
+
202
+ ### issue_found
203
+ - skill: string — "ftm-debug"
204
+ - phase: string — "phase1" | "phase2"
205
+ - agent: string — "instrumenter" | "researcher" | "reproducer" | "hypothesizer"
206
+ - finding: string — description of the specific issue found
207
+ - confidence: string — high | medium | low
208
+
209
+ ### test_passed
210
+ - skill: string — "ftm-debug"
211
+ - scope: string — "reproduction" | "full_suite"
212
+ - worktree: string — worktree path where tests ran
213
+
214
+ ### test_failed
215
+ - skill: string — "ftm-debug"
216
+ - scope: string — "reproduction" | "full_suite"
217
+ - worktree: string — worktree path
218
+ - error_summary: string — brief failure description
219
+
220
+ ### error_encountered
221
+ - skill: string — "ftm-debug"
222
+ - phase: string — war room phase where error occurred
223
+ - agent: string | null — agent that encountered the error
224
+ - error: string — error description
225
+
226
+ ### task_completed
227
+ - skill: string — "ftm-debug"
228
+ - outcome: string — "fixed" | "escalated" | "unresolved"
229
+ - root_cause: string — root cause if found
230
+ - duration_ms: number — total session duration
@@ -231,3 +231,47 @@ Read and display `ARCHITECTURE.mmd` + list available module diagrams.
231
231
  ### Auto-Invocation by ftm-executor
232
232
 
233
233
  This skill's format is used by ftm-executor's documentation pipeline. After every commit during plan execution, agents update INTENT.md (or DIAGRAM.mmd) entries following this skill's templates. The updates are automatic and don't require explicit skill invocation — agents reference the format directly.
234
+
235
+ ## Requirements
236
+
237
+ - reference: `.ftm-map/map.db` | optional | SQLite knowledge graph for accurate diagram generation (graph-powered mode)
238
+ - tool: `ftm-map/scripts/.venv/bin/python3` | optional | Python runtime for graph-powered views.py
239
+ - reference: `package.json` | optional | project structure detection for bootstrap
240
+ - reference: `tsconfig.json` | optional | TypeScript project structure detection
241
+
242
+ ## Risk
243
+
244
+ - level: low_write
245
+ - scope: writes .mmd diagram files to project directories; only creates or modifies ARCHITECTURE.mmd and per-module DIAGRAM.mmd files; does not touch source code
246
+ - rollback: git checkout on modified .mmd files; delete newly created .mmd files
247
+
248
+ ## Approval Gates
249
+
250
+ - trigger: bootstrap mode on large codebase (50+ modules) | action: report what was found and what will be created before writing, proceed unless user objects
251
+ - complexity_routing: micro → auto | small → auto | medium → auto | large → auto | xl → auto
252
+
253
+ ## Fallbacks
254
+
255
+ - condition: .ftm-map/map.db not found | action: fall back to standard import-grep analysis for diagram generation
256
+ - condition: Python venv not set up | action: fall back to standard analysis, log "Graph-powered mode unavailable — run ftm-map to enable"
257
+ - condition: no src/ or identifiable source root | action: ask user for source root before bootstrapping
258
+
259
+ ## Capabilities
260
+
261
+ - cli: `ftm-map/scripts/.venv/bin/python3` | optional | graph-powered diagram generation
262
+ - mcp: `git` | optional | detect changed files for incremental updates
263
+
264
+ ## Event Payloads
265
+
266
+ ### documentation_updated
267
+ - skill: string — "ftm-diagram"
268
+ - files_written: string[] — absolute paths to .mmd files created or modified
269
+ - modules_added: number — new module nodes added to ARCHITECTURE.mmd
270
+ - functions_added: number — new function nodes added across module DIAGRAMs
271
+ - edges_added: number — new dependency edges added
272
+
273
+ ### task_completed
274
+ - skill: string — "ftm-diagram"
275
+ - mode: string — "bootstrap" | "incremental"
276
+ - files_count: number — total .mmd files written
277
+ - duration_ms: number — total diagram sync duration
@@ -655,3 +655,100 @@ After completing, update the blackboard:
655
655
  2. Write an experience file to `/Users/kioja.kudumu/.claude/ftm-state/blackboard/experiences/YYYY-MM-DD_task-slug.json` capturing task_type, agent team used, wave count, audit outcomes, and lessons learned
656
656
  3. Update `/Users/kioja.kudumu/.claude/ftm-state/blackboard/experiences/index.json` with the new entry
657
657
  4. Emit `task_completed` event
658
+
659
+ ## Requirements
660
+
661
+ - tool: `git` | required | worktree creation, branch management, commit operations
662
+ - config: `~/.claude/ftm-config.yml` | optional | model profiles, max_parallel_agents, auto_audit, progress_tracking
663
+ - reference: `~/.claude/plans/` | optional | plan documents for execution
664
+ - tool: `node` | optional | project setup commands in worktrees
665
+ - reference: `~/.claude/skills/ftm-executor/references/STYLE-TEMPLATE.md` | optional | STYLE.md bootstrap template
666
+
667
+ ## Risk
668
+
669
+ - level: high_write
670
+ - scope: creates git worktrees and branches, modifies source files across multiple tasks, runs tests and builds, optionally pushes branches or creates PRs
671
+ - rollback: git worktree remove + git branch -D for each worktree; all changes isolated to plan-exec/* branches until explicitly merged
672
+
673
+ ## Approval Gates
674
+
675
+ - trigger: no plan document provided | action: generate plan and wait for explicit user approval before any code is written
676
+ - trigger: plan_checker returns FAIL | action: present blockers and ask user to fix or override before proceeding
677
+ - trigger: plan_checker returns WARN | action: show warnings to user, proceed unless they object
678
+ - trigger: wave complete and all agents done | action: auto-invoke ftm-codex-gate (no user gate needed for this step)
679
+ - trigger: final phase 6 verification passes | action: present 4 branch finishing options and wait for explicit user choice
680
+ - trigger: codex gate FAIL after 2 fix attempts | action: report to user and wait for input before continuing
681
+ - complexity_routing: micro → auto | small → auto | medium → plan_first | large → plan_first | xl → always_ask
682
+
683
+ ## Fallbacks
684
+
685
+ - condition: ftm-browse not installed at $HOME/.claude/skills/ftm-browse/bin/ftm-browse | action: skip visual smoke test checks, log "Visual smoke test skipped — ftm-browse not installed"
686
+ - condition: ftm-retro skill not available | action: skip retrospective phase, note in output and proceed to branch finishing
687
+ - condition: codex CLI not found | action: skip codex gate, log "Codex gate skipped — codex not installed", proceed to next wave
688
+ - condition: no package.json in project | action: skip npm install in worktree setup; skip knip-based audit layers
689
+ - condition: project has no test suite | action: skip test verification gates, rely on diff review and build checks
690
+ - condition: agent fails or gets stuck | action: read agent output, fix directly or respawn with more context
691
+
692
+ ## Capabilities
693
+
694
+ - cli: `git` | required | worktree management and version control
695
+ - cli: `node` | optional | project dependency installation
696
+ - mcp: `sequential-thinking` | optional | complex dependency analysis and plan validation
697
+ - env: none required directly (agents inherit from session)
698
+
699
+ ## Event Payloads
700
+
701
+ ### task_received
702
+ - skill: string — "ftm-executor"
703
+ - task_description: string — description of the task being queued
704
+ - plan_path: string — absolute path to plan document
705
+
706
+ ### plan_generated
707
+ - skill: string — "ftm-executor"
708
+ - plan_path: string — absolute path to saved plan file
709
+ - task_count: number — total tasks in the plan
710
+ - wave_count: number — number of parallel execution waves
711
+
712
+ ### plan_approved
713
+ - skill: string — "ftm-executor"
714
+ - plan_path: string — absolute path to approved plan
715
+ - approved_steps: number[] — step numbers approved for execution
716
+
717
+ ### code_changed
718
+ - skill: string — "ftm-executor"
719
+ - worktree: string — path to the worktree where files changed
720
+ - files: string[] — list of modified file paths
721
+ - agent: string — agent type that made the changes
722
+
723
+ ### code_committed
724
+ - skill: string — "ftm-executor"
725
+ - worktree: string — path to worktree
726
+ - commit_hash: string — short commit hash
727
+ - message: string — commit message
728
+ - task_number: number — plan task number this commit belongs to
729
+
730
+ ### test_passed
731
+ - skill: string — "ftm-executor"
732
+ - scope: string — "task" | "full_suite"
733
+ - task_number: number | null — task number if scoped to task
734
+ - worktree: string — worktree path
735
+
736
+ ### test_failed
737
+ - skill: string — "ftm-executor"
738
+ - scope: string — "task" | "full_suite"
739
+ - task_number: number | null — task number if scoped
740
+ - worktree: string — worktree path
741
+ - error_summary: string — brief description of failure
742
+
743
+ ### task_completed
744
+ - skill: string — "ftm-executor"
745
+ - task_number: number — completed task number
746
+ - audit_result: string — "pass" | "pass_with_fixes" | "fail" | "skipped"
747
+ - auto_fixed_count: number — issues auto-remediated by ftm-audit
748
+ - duration_ms: number — task execution time
749
+
750
+ ### error_encountered
751
+ - skill: string — "ftm-executor"
752
+ - phase: string — execution phase where error occurred
753
+ - task_number: number | null — associated task if applicable
754
+ - error: string — error description
package/ftm-git/SKILL.md CHANGED
@@ -193,3 +193,63 @@ After completing, update the blackboard:
193
193
  - Which patterns matched (to improve future scans)
194
194
  3. Update `experiences/index.json` with the new entry
195
195
  4. Emit `secrets_clear` or `secrets_remediated` or `secrets_blocked`
196
+
197
+ ## Requirements
198
+
199
+ - tool: `git` | required | staged file inspection, commit history scanning
200
+ - reference: `references/patterns/SECRET-PATTERNS.md` | required | Tier 1/2 patterns, severity table, ignore list
201
+ - reference: `references/protocols/REMEDIATION.md` | required | remediation protocol, env var patterns, report formats
202
+ - reference: `~/.claude/skills/ftm-git/scripts/pre-commit-secrets.sh` | required | pre-commit hook script for installation
203
+ - reference: `~/.claude/skills/ftm-git/hooks/post-commit-experience.sh` | optional | post-commit experience recorder hook
204
+
205
+ ## Risk
206
+
207
+ - level: medium_write
208
+ - scope: modifies source files to replace hardcoded secrets with env var references; creates/updates .env and .env.example files; installs git hooks in .git/hooks/; re-stages files after remediation
209
+ - rollback: git checkout on refactored source files; manually remove added .env and .gitignore entries; remove hook from .git/hooks/pre-commit
210
+
211
+ ## Approval Gates
212
+
213
+ - trigger: CRITICAL or HIGH severity secret found | action: BLOCK commit/push immediately, announce "BLOCKED — N secret(s) found", then attempt auto-remediation
214
+ - trigger: auto-remediation proposed for a finding | action: show proposed change (file, variable name, env var name) before applying
215
+ - trigger: re-scan after remediation still finds secrets | action: report remaining findings to user, do not proceed with commit
216
+ - complexity_routing: micro → auto | small → auto | medium → auto | large → auto | xl → auto
217
+
218
+ ## Fallbacks
219
+
220
+ - condition: .env file does not exist | action: create .env and .env.example and add .env to .gitignore before extracting secrets
221
+ - condition: .gitignore does not exist | action: create .gitignore with .env entry before remediation
222
+ - condition: language detection fails for env var pattern | action: extract secret to .env but flag source file refactoring as MANUAL_INTERVENTION_NEEDED
223
+ - condition: pre-commit hook already exists | action: append ftm-git scan to existing hook rather than overwriting
224
+
225
+ ## Capabilities
226
+
227
+ - cli: `git` | required | staged file listing, diff inspection, commit history traversal
228
+
229
+ ## Event Payloads
230
+
231
+ ### secrets_found
232
+ - skill: string — "ftm-git"
233
+ - findings_count: number — total secrets detected
234
+ - critical_count: number — CRITICAL severity findings
235
+ - high_count: number — HIGH severity findings
236
+ - files_affected: string[] — files containing secrets
237
+ - blocked: boolean — whether commit/push was halted
238
+
239
+ ### secrets_clear
240
+ - skill: string — "ftm-git"
241
+ - files_scanned: number — total files checked
242
+ - scope: string — "staged" | "working_tree" | "history" | "pre-push"
243
+
244
+ ### secrets_remediated
245
+ - skill: string — "ftm-git"
246
+ - findings_remediated: number — secrets successfully extracted
247
+ - env_vars_added: string[] — environment variable names created
248
+ - files_refactored: string[] — source files updated to use env vars
249
+ - manual_needed: number — findings requiring manual intervention
250
+
251
+ ### task_completed
252
+ - skill: string — "ftm-git"
253
+ - outcome: string — "clear" | "remediated" | "blocked"
254
+ - files_scanned: number — total files scanned
255
+ - duration_ms: number — total scan and remediation time
File without changes
File without changes
@@ -0,0 +1,64 @@
1
+ """
2
+ Exponential-backoff retry decorator for HTTP adapter calls.
3
+
4
+ Usage:
5
+ @retry(max_attempts=3, base_delay=1.0)
6
+ def poll(self) -> list[dict]:
7
+ ...
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import functools
13
+ import logging
14
+ import time
15
+ from typing import Callable, TypeVar
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+ F = TypeVar("F", bound=Callable)
20
+
21
+
22
+ def retry(
23
+ max_attempts: int = 3,
24
+ base_delay: float = 1.0,
25
+ backoff_factor: float = 2.0,
26
+ exceptions: tuple[type[Exception], ...] = (Exception,),
27
+ ) -> Callable[[F], F]:
28
+ """
29
+ Decorator: retry on exception with exponential backoff.
30
+
31
+ Args:
32
+ max_attempts: Total number of attempts (including the first).
33
+ base_delay: Initial sleep duration in seconds.
34
+ backoff_factor: Multiplier applied to delay after each failure.
35
+ exceptions: Exception types that trigger a retry.
36
+ """
37
+
38
+ def decorator(func: F) -> F:
39
+ @functools.wraps(func)
40
+ def wrapper(*args, **kwargs):
41
+ delay = base_delay
42
+ last_exc: Exception | None = None
43
+ for attempt in range(1, max_attempts + 1):
44
+ try:
45
+ return func(*args, **kwargs)
46
+ except exceptions as exc:
47
+ last_exc = exc
48
+ if attempt == max_attempts:
49
+ break
50
+ logger.warning(
51
+ "%s failed (attempt %d/%d): %s — retrying in %.1fs",
52
+ func.__qualname__,
53
+ attempt,
54
+ max_attempts,
55
+ exc,
56
+ delay,
57
+ )
58
+ time.sleep(delay)
59
+ delay *= backoff_factor
60
+ raise last_exc # type: ignore[misc]
61
+
62
+ return wrapper # type: ignore[return-value]
63
+
64
+ return decorator