feed-the-machine 1.7.13 → 1.7.15
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.
|
@@ -2,205 +2,90 @@
|
|
|
2
2
|
|
|
3
3
|
## Decide
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
### 1. Choose execution mode
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- `micro` → direct action
|
|
8
|
+
- `small` → pre-flight summary + action + verify
|
|
9
|
+
- `medium` → checkbox plan, wait for approval, execute
|
|
10
|
+
- `large` → `ftm-brainstorm` (no plan) or `ftm-executor` (plan exists)
|
|
8
11
|
|
|
9
|
-
-
|
|
10
|
-
- `small` -> pre-flight summary, then direct action plus verification
|
|
11
|
-
- `medium` -> numbered plan, wait for approval, then execute
|
|
12
|
-
- `large` -> `ftm-brainstorm` if no plan exists, or `ftm-executor` if a plan exists
|
|
12
|
+
Double-check forced escalation signals from Complexity Sizing reference. If any fired → medium minimum.
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
### 1.5 Plan Approval
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Read `ftm-config.yml` → `execution.approval_mode`.
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
**`auto`**: micro/small just go, medium outlines + executes, large routes to brainstorm/executor.
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
**`plan_first`** (recommended):
|
|
21
|
+
- Small: pre-flight summary, proceed unless user objects
|
|
22
|
+
- Medium/large: present checkbox plan, wait for explicit approval
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
**For small tasks**: Show a brief pre-flight summary before executing. Not a formal gate — just visibility:
|
|
26
|
-
|
|
27
|
-
```
|
|
28
|
-
Quick summary before I start:
|
|
29
|
-
- Read [file] to understand current behavior
|
|
30
|
-
- Change [X] to [Y] in [file]
|
|
31
|
-
- Verify: [test/lint/manual check]
|
|
32
|
-
|
|
33
|
-
Going ahead unless you say otherwise.
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
**For medium and large tasks**: Present a numbered task list and wait for the user to approve.
|
|
37
|
-
|
|
38
|
-
**Step 0: Discovery Interview (if applicable).** Before generating the plan, check whether a Discovery Interview is needed (see Orient reference). If the task involves external systems, stakeholder coordination, or unfamiliar code, run the interview FIRST.
|
|
39
|
-
|
|
40
|
-
**Step 1: Generate the plan.** Build a numbered checkbox list. This format is **mandatory** — no narrative steps, no prose paragraphs. Every plan MUST use: `N. [ ] One-line action → target`. See `references/protocols/PLAN-APPROVAL.md` for the full format spec, examples for code/ops/comms/infra tasks, and the list of NEVER-produce anti-patterns.
|
|
41
|
-
|
|
42
|
-
**Step 2: Parse the user's response.**
|
|
24
|
+
Plan format is **mandatory**: `N. [ ] One-line action → target`. See `protocols/PLAN-APPROVAL.md` for spec + examples.
|
|
43
25
|
|
|
44
26
|
| User says | Action |
|
|
45
|
-
|
|
46
|
-
|
|
|
47
|
-
|
|
|
48
|
-
|
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
|
|
|
52
|
-
| A longer message with mixed feedback | Parse each instruction. Apply all modifications. Present revised plan and ask for final approval. |
|
|
53
|
-
|
|
54
|
-
**Step 3: Execute the approved plan.** Work through steps sequentially. After each step show: `Step 2/5 done: [summary].` If a step fails, stop and report.
|
|
27
|
+
|---|---|
|
|
28
|
+
| approve/go/yes/lgtm | Execute all |
|
|
29
|
+
| skip N | Remove step, execute rest |
|
|
30
|
+
| only N,M | Execute only listed |
|
|
31
|
+
| for step N, [change] | Modify + execute all |
|
|
32
|
+
| add: [desc] after N | Insert, renumber, execute |
|
|
33
|
+
| deny/stop/cancel | Cancel entirely |
|
|
55
34
|
|
|
56
|
-
|
|
35
|
+
Execute sequentially. Show `Step 2/5 done: [summary]` after each. If step fails → stop and report.
|
|
57
36
|
|
|
58
|
-
|
|
59
|
-
Same as `plan_first` but applies to **small** tasks too. Only micro tasks skip the approval gate.
|
|
37
|
+
**`always_ask`**: Same as plan_first but also gates small tasks. Only micro skips.
|
|
60
38
|
|
|
61
|
-
|
|
62
|
-
When routing to a skill, plan approval still applies if mode is `plan_first` or `always_ask`. Present the strategy for user control.
|
|
39
|
+
### 2. Direct vs routed
|
|
63
40
|
|
|
64
|
-
|
|
41
|
+
Direct when: micro/small, routing overhead adds no value, faster to just do it.
|
|
42
|
+
Skill when: specialized workflow improves result, user invoked it, medium/large.
|
|
65
43
|
|
|
66
|
-
|
|
67
|
-
- the work is micro or small
|
|
68
|
-
- routing overhead adds no value
|
|
69
|
-
- the answer can be delivered faster than a delegated workflow
|
|
44
|
+
### 3. Supporting MCP reads
|
|
70
45
|
|
|
71
|
-
|
|
72
|
-
- its specialized workflow will materially improve the result
|
|
73
|
-
- the user explicitly invoked it
|
|
74
|
-
- the task is medium/large and the skill is the right vehicle
|
|
46
|
+
Fetch minimum required external context first (ticket, calendar, docs, browser state).
|
|
75
47
|
|
|
76
|
-
###
|
|
48
|
+
### 4. Loop decision
|
|
77
49
|
|
|
78
|
-
If
|
|
79
|
-
|
|
80
|
-
Examples:
|
|
81
|
-
- Jira URL -> read the ticket first
|
|
82
|
-
- meeting request -> read calendar first
|
|
83
|
-
- internal policy question -> search Glean first
|
|
84
|
-
- UI bug -> snapshot or inspect browser first
|
|
85
|
-
|
|
86
|
-
### 4. Decide whether to loop
|
|
87
|
-
|
|
88
|
-
If the next move will reveal new information, plan to re-enter Observe after the action.
|
|
50
|
+
If next move reveals new information → plan to re-enter Observe after.
|
|
89
51
|
|
|
90
52
|
## Act
|
|
91
53
|
|
|
92
|
-
Act
|
|
93
|
-
|
|
94
|
-
**HARD GATE — Pre-Act checkpoint**: Before executing ANYTHING (Bash, MCP, Write, Edit, API calls of any kind), verify ALL of these:
|
|
95
|
-
|
|
96
|
-
1. **Did you present a checkbox plan?** If the task is medium+ (forced escalation signals fired), you MUST have presented a `N. [ ] action → target` plan and received explicit user approval. "I'll do X, Y, Z" in prose is NOT a plan. Listing steps without `[ ]` checkboxes is NOT a plan. If you haven't presented one, STOP and present it now.
|
|
97
|
-
2. **Did the user approve it?** Look for "go", "approve", "yes", "lgtm", or similar. If the user hasn't responded to your plan yet, WAIT. Do not start executing.
|
|
98
|
-
3. **Is the plan marker written?** After approval, write to `~/.claude/ftm-state/.plan-presented` before executing. This signals to hooks that planning happened.
|
|
99
|
-
4. If the task involves external mutations (see Approval Gates), have you presented the specific actions and received approval?
|
|
100
|
-
5. If none of the above apply (micro/small task, no forced escalation), proceed.
|
|
101
|
-
|
|
102
|
-
**The rationalization trap**: You will feel the urge to skip the plan because:
|
|
103
|
-
- "The user said 'do as much as you can' — that's implicit approval" → NO. That's the task description, not plan approval.
|
|
104
|
-
- "I know what needs to happen, presenting a plan is just overhead" → NO. The plan is for the USER, not for you.
|
|
105
|
-
- "I'll just start with one small API call to check something" → NO. One call becomes five becomes a full execution without approval.
|
|
106
|
-
- "The user seems impatient" → NO. A 30-second plan saves 10 minutes of unwanted work.
|
|
107
|
-
|
|
108
|
-
**This applies to ALL execution methods** — Bash commands, MCP calls, Python scripts, curl, direct API calls. The plan-gate hook catches Edit/Write/MCP, but Bash API calls bypass it. This checkpoint is the only thing that catches those. Do not skip it.
|
|
109
|
-
|
|
110
|
-
### Compare Before You Loop (MANDATORY for external system operations)
|
|
54
|
+
### Pre-Act Checkpoint
|
|
111
55
|
|
|
112
|
-
|
|
56
|
+
Before executing, verify:
|
|
113
57
|
|
|
114
|
-
**
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
- Updating a Jira automation? Read a working rule's config before touching the broken one.
|
|
58
|
+
1. **Checkbox plan presented?** Medium+ tasks require `N. [ ] action → target` format, approved by user.
|
|
59
|
+
2. **User approved?** Wait for explicit go/approve/yes.
|
|
60
|
+
3. **Plan marker written?** Write to `~/.claude/ftm-state/.plan-presented` after approval.
|
|
61
|
+
4. None apply (micro/small, no forced escalation) → proceed.
|
|
119
62
|
|
|
120
|
-
**
|
|
121
|
-
Compare the working reference against the target. The fix is almost always a small, specific difference — a missing field option, a different encoding, a wrong position value. Find that diff. Don't hypothesize about what might be wrong.
|
|
122
|
-
|
|
123
|
-
**Step 3: Make targeted changes.**
|
|
124
|
-
Change ONLY what the diff revealed. One field at a time if needed. Verify after each change.
|
|
125
|
-
|
|
126
|
-
**The trial-and-error trap**: When an API call fails, your instinct is to try a different endpoint, different payload, different method. After 3 failed attempts you're in a loop — guessing at combinations. STOP. Go back to Step 1. The answer is in the working reference, not in your next guess.
|
|
127
|
-
|
|
128
|
-
**Red flags that you're in a loop:**
|
|
129
|
-
- You've made 3+ API calls to the same system without a success
|
|
130
|
-
- You're trying different URL path formats (underscore vs hyphen, internal ID vs display ID)
|
|
131
|
-
- You're adding/removing fields from the payload hoping one combination works
|
|
132
|
-
- You're reading API docs or source code to figure out the endpoint (the playbook should have this)
|
|
133
|
-
|
|
134
|
-
**When you detect a loop:** STOP executing. Tell the user: "I've tried N approaches and none worked. Let me compare against a working reference before continuing." Then do Step 1.
|
|
135
|
-
|
|
136
|
-
**The April 2026 lesson**: A one-field-option diff (`requester_can_edit: "true"`) was the entire fix for the Freshservice roles table not rendering. It took 15+ API calls, accidental field duplication, and destructive deletion of two catalog items to discover what a 30-second field-by-field comparison against the working HR Acuity item would have revealed immediately.
|
|
63
|
+
**Note**: The `ftm-guard` hook enforces approval gates, destructive action prevention, playbook checks, and loop detection at the tool-call level. You don't need to self-check these — the hook will stop you. But you should still present plans and get approval before acting.
|
|
137
64
|
|
|
138
65
|
### 1. Direct action
|
|
139
66
|
|
|
140
|
-
|
|
141
|
-
- do the work
|
|
142
|
-
- summarize what changed
|
|
143
|
-
|
|
144
|
-
For small tasks (when `approval_mode` is `plan_first` or `always_ask`):
|
|
145
|
-
- show the pre-flight summary first
|
|
146
|
-
- then do the work
|
|
147
|
-
- verify
|
|
148
|
-
- summarize what changed
|
|
67
|
+
Micro: do + summarize. Small (plan_first/always_ask): pre-flight → do → verify → summarize.
|
|
149
68
|
|
|
150
69
|
### 2. Skill routing
|
|
151
70
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
Examples:
|
|
155
|
-
- `Routing to ftm-debug: this is a flaky failure with real diagnostic uncertainty.`
|
|
156
|
-
- `Routing to ftm-brainstorm: this is still design-stage and benefits from research-backed planning.`
|
|
157
|
-
|
|
158
|
-
Then invoke the target skill with the full user input.
|
|
71
|
+
Show one routing line, then invoke: `Routing to ftm-debug: flaky failure with diagnostic uncertainty.`
|
|
159
72
|
|
|
160
73
|
### 3. MCP execution
|
|
161
74
|
|
|
162
|
-
|
|
163
|
-
- parallel reads when safe
|
|
164
|
-
- sequential writes
|
|
165
|
-
- approval gates only for external-facing actions
|
|
75
|
+
Parallel reads, sequential writes. The ftm-guard hook handles approval gates for external-facing actions.
|
|
166
76
|
|
|
167
|
-
### 3.5
|
|
77
|
+
### 3.5 Draft-before-send
|
|
168
78
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
**Drafts folder**: `.ftm-drafts/` in the project root (or `~/.claude/ftm-drafts/` if no project context).
|
|
172
|
-
|
|
173
|
-
**Ensure the folder exists and is gitignored.** Save every draft before presenting or sending:
|
|
174
|
-
|
|
175
|
-
- Filename: `YYYY-MM-DD_HH-MM_<type>_<recipient-or-channel>.md`
|
|
176
|
-
- Content includes frontmatter: type, to, subject (email only), drafted timestamp, status (draft/sent/cancelled)
|
|
177
|
-
|
|
178
|
-
**Workflow:**
|
|
179
|
-
1. Compose the message
|
|
180
|
-
2. Save to `.ftm-drafts/`
|
|
181
|
-
3. Present to user for approval
|
|
182
|
-
4. If approved and sent, update `status: sent`
|
|
183
|
-
5. If cancelled or modified, update accordingly
|
|
79
|
+
Slack/email/outbound comms → save to `.ftm-drafts/` AND `~/.claude/ftm-ops/drafts/` first. Filename: `YYYY-MM-DD_HH-MM_<type>_<recipient>.md`. Present for approval, update status on send/cancel.
|
|
184
80
|
|
|
185
81
|
### 4. Blackboard updates (mandatory)
|
|
186
82
|
|
|
187
|
-
After every completed task
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
4. Update `~/.claude/ftm-state/blackboard/experiences/index.json` with the new entry
|
|
193
|
-
|
|
194
|
-
The experience file should capture:
|
|
195
|
-
- `task_type`, `tags`, `outcome`, `lessons`, `files_touched`, `stakeholders`, `decisions_made`
|
|
196
|
-
|
|
197
|
-
Follow the schema and full-file write rules from `blackboard-schema.md`.
|
|
83
|
+
After every completed task:
|
|
84
|
+
1. Update `context.json` — current_task, recent_decisions, session_metadata
|
|
85
|
+
2. Write experience file to `experiences/YYYY-MM-DD_task-slug.json`
|
|
86
|
+
3. Update `experiences/index.json`
|
|
87
|
+
4. Include: task_type, tags, outcome, lessons, files_touched, stakeholders, decisions_made, code_patterns, api_gotchas
|
|
198
88
|
|
|
199
89
|
### 5. Loop
|
|
200
90
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
- if complete, answer and stop
|
|
204
|
-
- if new information appeared, return to Observe
|
|
205
|
-
- if blocked by approval or missing info, ask the user
|
|
206
|
-
- if the simple approach failed, re-orient and escalate one level
|
|
91
|
+
Complete → answer and stop. New info → re-observe. Blocked → ask user. Failed → re-orient, escalate one level.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Incident Reference
|
|
2
|
+
|
|
3
|
+
Named incidents referenced by Orient and Decide-Act protocols. Read this file only when an incident name is cited and you need the full context.
|
|
4
|
+
|
|
5
|
+
## Hindsight Incident (March 2026)
|
|
6
|
+
|
|
7
|
+
**What happened**: ftm-mind took an SSO setup task and autonomously created Okta groups, added users to production Okta, created Freshservice records, a service catalog item, and modified S3 workflow configs — all without presenting a plan or asking for approval once.
|
|
8
|
+
|
|
9
|
+
**Root cause**: No plan-first gate existed. The task "felt small" but touched 5+ external systems.
|
|
10
|
+
|
|
11
|
+
**What it taught us**: Any task that calls production APIs is forced-medium. Plans are mandatory. Approval gates are circuit breakers, not suggestions.
|
|
12
|
+
|
|
13
|
+
## Braintrust Incident (April 2026)
|
|
14
|
+
|
|
15
|
+
**What happened**: Freshservice catalog items #626 and #621 were deleted and recreated as #631 and #632 to "fix" duplicate fields. This broke the S3 workflow config (assign_after_app_owner_approval), required emergency patching, and custom_lookup_bigint fields had to be re-added manually.
|
|
16
|
+
|
|
17
|
+
**Root cause**: Three knowledge sources existed (playbook, blackboard, brain.py) and none were consulted. Then, when trial-and-error failed, the model chose a destructive action (delete + recreate) without considering dependencies or asking for approval.
|
|
18
|
+
|
|
19
|
+
**What it taught us**:
|
|
20
|
+
1. Always check playbooks before external system operations
|
|
21
|
+
2. Never delete and recreate external resources — IDs are depended on
|
|
22
|
+
3. Compare working references against broken ones instead of guessing
|
|
23
|
+
4. A one-field diff (`requester_can_edit: "true"`) was the entire fix — discoverable in 30 seconds by comparing the working HR Acuity item against the broken ones
|
|
@@ -1,348 +1,118 @@
|
|
|
1
|
-
# Orient Protocol
|
|
1
|
+
# Orient Protocol
|
|
2
2
|
|
|
3
3
|
## Capability Inventory: FTM Skills
|
|
4
4
|
|
|
5
|
-
Orient must know all ftm capabilities before deciding whether to route or act directly.
|
|
6
|
-
|
|
7
5
|
| Skill | Reach for it when... |
|
|
8
6
|
|---|---|
|
|
9
|
-
| `ftm-brainstorm` |
|
|
10
|
-
| `ftm-executor` |
|
|
11
|
-
| `ftm-debug` |
|
|
12
|
-
| `ftm-audit` |
|
|
13
|
-
| `ftm-council` |
|
|
14
|
-
| `ftm-codex-gate` |
|
|
15
|
-
| `ftm-intent` |
|
|
16
|
-
| `ftm-diagram` |
|
|
17
|
-
| `ftm-browse` |
|
|
18
|
-
| `ftm-pause`
|
|
19
|
-
| `ftm-
|
|
20
|
-
| `ftm-
|
|
21
|
-
| `ftm-
|
|
22
|
-
| `ftm-
|
|
23
|
-
| `ftm-
|
|
24
|
-
| `ftm-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
## MCP Inventory Reference
|
|
34
|
-
|
|
35
|
-
Read `~/.claude/skills/ftm-mind/references/mcp-inventory.md` for full MCP server details.
|
|
36
|
-
|
|
37
|
-
Orient must know the available MCPs and their contextual triggers.
|
|
38
|
-
|
|
39
|
-
| MCP server | Reach for it when... |
|
|
7
|
+
| `ftm-brainstorm` | Exploring ideas, designing systems, comparing approaches, research-backed planning |
|
|
8
|
+
| `ftm-executor` | Has a plan doc or wants autonomous multi-task implementation |
|
|
9
|
+
| `ftm-debug` | Broken behavior, errors, flaky tests, crashes, regressions |
|
|
10
|
+
| `ftm-audit` | Wiring checks, dead code analysis, structural verification |
|
|
11
|
+
| `ftm-council` | Multiple AI perspectives, debate, second opinions |
|
|
12
|
+
| `ftm-codex-gate` | Adversarial Codex review or correctness stress test |
|
|
13
|
+
| `ftm-intent` | Function/module purpose docs or INTENT.md updates |
|
|
14
|
+
| `ftm-diagram` | Diagrams, architecture visuals, Mermaid assets |
|
|
15
|
+
| `ftm-browse` | Browser, screenshots, DOM inspection, visual verification |
|
|
16
|
+
| `ftm-pause` / `ftm-resume` | Park or restore session state |
|
|
17
|
+
| `ftm-upgrade` | Check or upgrade ftm skills |
|
|
18
|
+
| `ftm-retro` | Post-run retrospective or execution review |
|
|
19
|
+
| `ftm-config` | Settings, model profiles, feature configuration |
|
|
20
|
+
| `ftm-git` | MANDATORY before any commit/push — secret scanning gate |
|
|
21
|
+
| `ftm-capture` | Save repeatable workflow as routine/playbook. Also suggest proactively when blackboard shows same task_type 2+ times |
|
|
22
|
+
| `ftm-ops` | Tasks, capacity, burnout, stakeholders, meetings, incidents, daily/weekly summaries |
|
|
23
|
+
|
|
24
|
+
Routing: do it directly if small enough. Route to a skill only when the workflow adds clear value. Explicit invocation is a strong signal.
|
|
25
|
+
|
|
26
|
+
## MCP Inventory
|
|
27
|
+
|
|
28
|
+
Read `references/mcp-inventory.md` for full details. Quick heuristics:
|
|
29
|
+
|
|
30
|
+
| Signal | MCP |
|
|
40
31
|
|---|---|
|
|
41
|
-
|
|
|
42
|
-
|
|
|
43
|
-
|
|
|
44
|
-
|
|
|
45
|
-
|
|
|
46
|
-
|
|
|
47
|
-
|
|
|
48
|
-
|
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
### MCP matching heuristics
|
|
56
|
-
|
|
57
|
-
Use the smallest relevant MCP set.
|
|
58
|
-
|
|
59
|
-
- Jira issue key or Atlassian URL -> `mcp-atlassian-personal` (or the configured personal account name)
|
|
60
|
-
- "internal docs", "runbook", "company wiki", "Glean" -> `glean_default`
|
|
61
|
-
- "how do I use X library" -> `context7`
|
|
62
|
-
- "calendar", "meeting", "free time" -> `google-calendar`
|
|
63
|
-
- "Slack", "channel", "thread", "notify" -> `slack`
|
|
64
|
-
- "email", "Gmail", "draft" -> `gmail`
|
|
65
|
-
- "ticket", "hardware", "access request" -> `freshservice-mcp`
|
|
66
|
-
- "browser", "screenshot", "look at the page" -> `playwright`
|
|
67
|
-
- "talk through trade-offs" -> `sequential-thinking`
|
|
68
|
-
- "SwiftUI" or Apple framework names -> `apple-doc-mcp`
|
|
69
|
-
- "find contact/company" -> `lusha`
|
|
70
|
-
|
|
71
|
-
### Multi-MCP chaining
|
|
72
|
-
|
|
73
|
-
Detect mixed-domain requests early.
|
|
74
|
-
|
|
75
|
-
Examples:
|
|
76
|
-
|
|
77
|
-
- "check my calendar and draft a Slack message" -> `google-calendar` + `slack`
|
|
78
|
-
- "read the Jira ticket, inspect the repo, then propose a fix" -> `mcp-atlassian-personal` + `git`
|
|
79
|
-
- "search internal docs, then update a Confluence page" -> `glean_default` + `mcp-atlassian-personal`
|
|
80
|
-
|
|
81
|
-
Rules:
|
|
82
|
-
|
|
83
|
-
- parallelize reads when safe
|
|
84
|
-
- gather state before proposing writes
|
|
85
|
-
- chain writes sequentially
|
|
32
|
+
| Jira key or Atlassian URL | `mcp-atlassian-personal` |
|
|
33
|
+
| Internal docs, runbook, company wiki | `glean_default` |
|
|
34
|
+
| Library/framework docs | `context7` |
|
|
35
|
+
| Calendar, meeting, free time | `google-calendar` |
|
|
36
|
+
| Slack, channel, thread | `slack` |
|
|
37
|
+
| Email, Gmail, draft | `gmail` |
|
|
38
|
+
| Ticket, hardware, access request | `freshservice-mcp` |
|
|
39
|
+
| Browser, screenshot | `playwright` |
|
|
40
|
+
| Trade-off analysis | `sequential-thinking` |
|
|
41
|
+
| Apple framework | `apple-doc-mcp` |
|
|
42
|
+
| Contact/company lookup | `lusha` |
|
|
43
|
+
|
|
44
|
+
Multi-MCP: parallelize reads, gather state before writes, chain writes sequentially.
|
|
86
45
|
|
|
87
46
|
## Session Trajectory
|
|
88
47
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
-
|
|
94
|
-
-
|
|
95
|
-
- Is the user moving from ideation -> execution -> validation?
|
|
96
|
-
- Did we already choose an approach that this request assumes?
|
|
97
|
-
|
|
98
|
-
Trajectory cues:
|
|
99
|
-
|
|
100
|
-
- brainstorm -> "ok go" usually means plan or executor
|
|
101
|
-
- debug -> "check it now" usually means verify, test, or audit
|
|
102
|
-
- executor -> "pause" means checkpoint, not new work
|
|
103
|
-
- resume -> "what's next?" means restore and continue
|
|
104
|
-
|
|
105
|
-
If a request branches away from the active thread, note that mentally and avoid corrupting the current session model.
|
|
48
|
+
Look for the arc, not just the last message:
|
|
49
|
+
- What happened just before? What did we learn?
|
|
50
|
+
- brainstorm → "ok go" = plan/executor
|
|
51
|
+
- debug → "check it now" = verify/test/audit
|
|
52
|
+
- executor → "pause" = checkpoint
|
|
53
|
+
- resume → "what's next?" = restore and continue
|
|
106
54
|
|
|
107
55
|
## Codebase State
|
|
108
56
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
Check:
|
|
112
|
-
|
|
113
|
-
- dirty worktree
|
|
114
|
-
- recent commits
|
|
115
|
-
- active branch
|
|
116
|
-
- user changes in progress
|
|
117
|
-
- whether the request conflicts with local state
|
|
118
|
-
|
|
119
|
-
Use codebase state to answer:
|
|
120
|
-
|
|
121
|
-
- is this safe to do directly?
|
|
122
|
-
- do we need to avoid stepping on unfinished work?
|
|
123
|
-
- is this request actually about the last commit or current unstaged diff?
|
|
124
|
-
- should we inspect a particular module first because recent changes point there?
|
|
125
|
-
|
|
126
|
-
Repo heuristics:
|
|
127
|
-
|
|
128
|
-
- uncommitted changes imply continuity and risk
|
|
129
|
-
- a clean tree lowers the cost of direct action
|
|
130
|
-
- a just-landed commit suggests review or regression-check behavior
|
|
131
|
-
- a ticket-linked branch suggests the user expects ticket-driven execution
|
|
132
|
-
|
|
133
|
-
## Approval Gates (HARD STOP — NOT OPTIONAL)
|
|
134
|
-
|
|
135
|
-
**This section is a circuit breaker, not a suggestion. If you are about to call a tool that creates, updates, or deletes a record in an external system, you MUST stop and get explicit user approval FIRST. No exceptions. No "the user implied it." No "it's part of the plan." STOP and ASK.**
|
|
136
|
-
|
|
137
|
-
The reason this exists: in March 2026, ftm-mind took a Hindsight SSO task and autonomously created Okta groups, added users to production Okta, created Freshservice records, created a service catalog item, and modified S3 workflow configs — all without asking once.
|
|
138
|
-
|
|
139
|
-
### What requires approval (STOP before each one)
|
|
140
|
-
|
|
141
|
-
Every individual external mutation needs its own approval. "The user approved the plan" does not mean "the user approved every API call in the plan."
|
|
142
|
-
|
|
143
|
-
- **Okta**: creating apps, groups, assigning users, modifying policies
|
|
144
|
-
- **Freshservice**: creating tickets, records, catalog items, custom objects
|
|
145
|
-
- **Jira / Confluence**: creating or updating issues, pages, comments
|
|
146
|
-
- **Slack / Email**: sending messages (draft-before-send protocol applies)
|
|
147
|
-
- **Calendar**: creating or modifying events
|
|
148
|
-
- **S3 / cloud storage**: writing or modifying objects
|
|
149
|
-
- **Browser forms**: submitting data through playwright/puppeteer
|
|
150
|
-
- **Deploys**: any production-affecting operation
|
|
151
|
-
- **Git remote**: pushes, PR creation
|
|
152
|
-
|
|
153
|
-
When multiple mutations are part of one plan, batch the approval request by phase — not one API call at a time, but not "approve the whole plan" either. Group related mutations and present per-phase.
|
|
154
|
-
|
|
155
|
-
### Destructive Actions (EXTRA HARD GATE — NEVER WITHOUT EXPLICIT CONFIRMATION)
|
|
156
|
-
|
|
157
|
-
Deleting, replacing, or recreating external resources is a **separate, higher gate** than creating or updating them. These actions are often irreversible and break downstream dependencies you can't see.
|
|
158
|
-
|
|
159
|
-
**NEVER do any of these without explicit user confirmation for each specific resource being destroyed:**
|
|
160
|
-
- **DELETE any external resource** (catalog items, custom objects, Okta groups/apps, Jira issues, S3 objects)
|
|
161
|
-
- **Recreate (delete + create)** to "fix" something — the new resource gets a different ID, breaking every automation that references the old one
|
|
162
|
-
- **Overwrite S3 objects** that other systems read from
|
|
163
|
-
- **Remove users from groups** or deactivate accounts
|
|
164
|
-
- **Close/resolve tickets** that others may be watching
|
|
165
|
-
|
|
166
|
-
**The "delete and recreate" trap**: When you can't update a resource cleanly via API, your instinct will be to delete it and create a fresh one. THIS IS ALMOST ALWAYS WRONG. External resources have IDs that other systems depend on — workflow configs, Lambda triggers, approval chains, custom object lookups, S3 references. Deleting breaks all of them silently. Instead:
|
|
167
|
-
1. Tell the user what you can't update via API
|
|
168
|
-
2. Suggest the minimal manual fix (admin UI link + exact steps)
|
|
169
|
-
3. Only delete if the user explicitly says "yes, delete it, I understand the dependencies"
|
|
170
|
-
|
|
171
|
-
**The April 2026 Braintrust incident**: ftm-mind deleted Freshservice catalog items #626 and #621 to "fix" duplicate fields, recreating them as #631 and #632. This broke the S3 workflow config (assign_after_app_owner_approval), required emergency patching, and the custom_lookup_bigint fields had to be re-added manually. The correct fix was: update only the roles field via API, and tell the user to delete the duplicate fields manually in the admin UI.
|
|
172
|
-
|
|
173
|
-
### What auto-proceeds (no approval needed)
|
|
174
|
-
|
|
175
|
-
- local code edits, documentation updates
|
|
176
|
-
- tests, lint, builds, audits
|
|
177
|
-
- local git operations (branch, commit, inspection)
|
|
178
|
-
- reading from any MCP or API (GET requests)
|
|
179
|
-
- blackboard reads and writes
|
|
180
|
-
- saving drafts to `.ftm-drafts/`
|
|
181
|
-
|
|
182
|
-
### The momentum trap
|
|
183
|
-
|
|
184
|
-
If you notice yourself thinking any of these, STOP — you are rationalizing past a gate:
|
|
57
|
+
Check: dirty worktree, recent commits, active branch, in-progress changes, conflicts with request. Clean tree = lower cost of direct action. Uncommitted changes = continuity and risk.
|
|
185
58
|
|
|
186
|
-
-
|
|
187
|
-
- "This is part of the approved plan"
|
|
188
|
-
- "I already started, might as well finish"
|
|
189
|
-
- "It's just one more API call"
|
|
190
|
-
- "The user will appreciate me being proactive"
|
|
191
|
-
|
|
192
|
-
None of these override the gate. Present the action, wait for approval, then execute.
|
|
193
|
-
|
|
194
|
-
## Ask-the-User Heuristic
|
|
195
|
-
|
|
196
|
-
Ask the user only when one of these is true:
|
|
197
|
-
|
|
198
|
-
- two materially different interpretations are both plausible
|
|
199
|
-
- an external-facing action needs approval
|
|
200
|
-
- a required credential, path, or identifier is missing **AND the blackboard has no experience confirming access** (see Blackboard-First Rule below)
|
|
201
|
-
- the user explicitly asked for options before action
|
|
202
|
-
- **the task is medium+ and involves external systems, stakeholder coordination, or unfamiliar code** (see Discovery Interview below) **AND the blackboard doesn't already confirm repo-level access**
|
|
203
|
-
|
|
204
|
-
When asking, ask one focused question with concrete choices.
|
|
205
|
-
|
|
206
|
-
### Blackboard-First Rule (MANDATORY before any access/auth questions)
|
|
207
|
-
|
|
208
|
-
**Before asking ANY question about credentials, API access, authorization, permissions, or "do you have access to X" — check the blackboard first.**
|
|
59
|
+
## Blackboard-First Rule (before any access/auth questions)
|
|
209
60
|
|
|
61
|
+
Before asking about credentials, API access, or authorization:
|
|
210
62
|
1. Read `experiences/index.json`
|
|
211
|
-
2. Look for
|
|
212
|
-
3. If
|
|
213
|
-
|
|
214
|
-
- **Do NOT run a discovery interview about authorization.** You have the answer.
|
|
215
|
-
- **Just do the thing.** If the credentials don't work, you'll find out when the API call fails — and that's a better signal than a speculative question.
|
|
216
|
-
4. If no matching experience exists, proceed with asking.
|
|
217
|
-
|
|
218
|
-
This rule exists because users set up repo-level context once (e.g., "my-tools repo has full API access to our admin systems") and expect Claude to remember it across every session. Asking "do you have admin access?" when the blackboard already says "yes, full access" is the #1 frustration signal.
|
|
219
|
-
|
|
220
|
-
### Access Declaration Detection (MANDATORY)
|
|
221
|
-
|
|
222
|
-
When a user declares repo-level access — either explicitly or as part of a task — **immediately write a blackboard experience so it persists across sessions.** Do NOT wait until the task is complete. Write it during Orient, before acting.
|
|
223
|
-
|
|
224
|
-
**Detection triggers** (any of these in the user's message):
|
|
225
|
-
- "I have access to...", "I have credentials for...", "I'm authenticated to..."
|
|
226
|
-
- "this repo has access to...", "we have API keys for..."
|
|
227
|
-
- "just do it, I have the creds", "you have access here", "credentials are configured"
|
|
228
|
-
- "I'm in [repo name] with my credentials"
|
|
229
|
-
- The user tells you to stop asking and just use an API
|
|
230
|
-
- An API call succeeds for the first time in a repo where no access experience exists
|
|
231
|
-
|
|
232
|
-
**What to write** — create an experience file at `~/.claude/ftm-state/blackboard/experiences/learning-{repo-name}-api-access.json`:
|
|
233
|
-
|
|
234
|
-
```json
|
|
235
|
-
{
|
|
236
|
-
"id": "learning-{repo-name}-api-access",
|
|
237
|
-
"timestamp": "{ISO 8601 now}",
|
|
238
|
-
"task_type": "environment-knowledge",
|
|
239
|
-
"tags": ["{repo-name}", "api-access", "environment", "learning"],
|
|
240
|
-
"outcome": "success",
|
|
241
|
-
"description": "User confirmed API access in {repo-name} repo. {any specifics they mentioned — which systems, what kind of access}.",
|
|
242
|
-
"lessons": [
|
|
243
|
-
"{repo-name} repo has configured access to {systems mentioned}",
|
|
244
|
-
"Do not ask about credentials or authorization when working in this repo — just act"
|
|
245
|
-
],
|
|
246
|
-
"confidence": 1.0,
|
|
247
|
-
"code_patterns": [],
|
|
248
|
-
"api_gotchas": []
|
|
249
|
-
}
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
Also update `experiences/index.json` with the new entry.
|
|
63
|
+
2. Look for tags: current repo name, `api-access`, `full-access`, or the target system
|
|
64
|
+
3. If match exists with confidence ≥ 0.7 → don't ask, just act
|
|
65
|
+
4. No match → proceed with asking
|
|
253
66
|
|
|
254
|
-
|
|
67
|
+
## Access Declaration Detection
|
|
255
68
|
|
|
256
|
-
|
|
69
|
+
When user declares repo-level access, **immediately** write a blackboard experience:
|
|
257
70
|
|
|
258
|
-
|
|
71
|
+
**Triggers**: "I have access to...", "credentials are configured", "just do it, I have the creds", user tells you to stop asking, or first successful API call in a repo without an access experience.
|
|
259
72
|
|
|
260
|
-
|
|
73
|
+
**Write**: `experiences/learning-{repo-name}-api-access.json` with tags `["{repo-name}", "api-access", "environment", "learning"]`, confidence 1.0. Update index.
|
|
261
74
|
|
|
262
|
-
|
|
75
|
+
## Discovery Interview (medium+ with external systems)
|
|
263
76
|
|
|
264
|
-
|
|
77
|
+
**Apply Blackboard-First Rule first.** If blackboard confirms access + task is a direct API operation → skip interview, just do it.
|
|
265
78
|
|
|
266
|
-
|
|
267
|
-
-
|
|
268
|
-
-
|
|
269
|
-
-
|
|
270
|
-
-
|
|
79
|
+
Interview is for genuine unknowns only (stakeholder coordination, multi-system migrations, policy changes). 2-4 focused questions:
|
|
80
|
+
- Who else needs to know?
|
|
81
|
+
- Downstream dependencies?
|
|
82
|
+
- Timeline/approval constraints?
|
|
83
|
+
- Parts to leave as-is?
|
|
271
84
|
|
|
272
|
-
**
|
|
273
|
-
- The user already provided comprehensive context
|
|
274
|
-
- The task is purely local with no external dependencies
|
|
275
|
-
- The user explicitly says "just do it" or "no questions, go"
|
|
276
|
-
- **The blackboard has an experience confirming API access for this repo + the task is a direct API operation** (not stakeholder coordination or multi-system migration)
|
|
85
|
+
**Skip when**: user provided context, purely local, user said "just do it", or blackboard confirms access for a direct API op.
|
|
277
86
|
|
|
278
|
-
## Brain.py Task Loading
|
|
279
|
-
|
|
280
|
-
During the Orient phase, enrich session context with the user's active operational state by loading tasks via brain.py:
|
|
87
|
+
## Brain.py Task Loading
|
|
281
88
|
|
|
282
89
|
```
|
|
283
90
|
python3 ~/.claude/skills/ftm/bin/brain.py --tasks --task-json
|
|
284
91
|
```
|
|
285
92
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
Skip this step if:
|
|
289
|
-
- brain.py is not present or returns an error (fail gracefully, do not block orientation)
|
|
290
|
-
- The session context already contains recently loaded task state (within 15 minutes)
|
|
291
|
-
- The request is purely local with no operational relevance (e.g., pure code edits)
|
|
292
|
-
|
|
293
|
-
## Playbook Lookup (MANDATORY before any external system operation)
|
|
294
|
-
|
|
295
|
-
**Before executing any operation on an external system (Freshservice, Okta, Jira, Trelica, S3, etc.), check for an existing playbook.** This is not optional. Playbooks encode hard-won lessons — API quirks, encoding requirements, field types that can't be updated, correct endpoint paths. Skipping this step means repeating every mistake the playbook was written to prevent.
|
|
296
|
-
|
|
297
|
-
**Step 1: Check brain.py playbooks.**
|
|
298
|
-
|
|
299
|
-
```
|
|
300
|
-
python3 ~/.claude/skills/ftm/bin/brain.py --playbook-match "[describe the operation]" --playbook-match-source freshservice
|
|
301
|
-
```
|
|
302
|
-
|
|
303
|
-
If a match returns with confidence > 0.2, read the full playbook before proceeding.
|
|
304
|
-
|
|
305
|
-
```
|
|
306
|
-
python3 ~/.claude/skills/ftm/bin/brain.py --playbook-list
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
Also list all playbooks and scan names — sometimes the match query misses a relevant one.
|
|
310
|
-
|
|
311
|
-
**Step 2: Check repo-local playbooks.**
|
|
93
|
+
Load active tasks, surface high-priority via TaskCreate. Skip if brain.py absent, tasks loaded recently (15min), or request is purely local.
|
|
312
94
|
|
|
313
|
-
|
|
314
|
-
ls docs/playbooks/ 2>/dev/null
|
|
315
|
-
```
|
|
95
|
+
## Playbook Lookup (MANDATORY before external system ops)
|
|
316
96
|
|
|
317
|
-
|
|
97
|
+
**Before any external system operation, check all three knowledge sources:**
|
|
318
98
|
|
|
319
|
-
|
|
99
|
+
1. `brain.py --playbook-match "[operation]"` + `--playbook-list`
|
|
100
|
+
2. `ls docs/playbooks/` in current repo
|
|
101
|
+
3. Blackboard experiences filtered by target system tags — check `code_patterns` and `api_gotchas`
|
|
320
102
|
|
|
321
|
-
|
|
103
|
+
If any source has relevant content, read it before writing code. After checking, write a marker: `~/.claude/ftm-state/.playbook-checked-{system}` so the ftm-guard hook knows you checked.
|
|
322
104
|
|
|
323
|
-
|
|
324
|
-
- Using raw HTML when Freshservice requires entity-encoded HTML (`html.escape()`)
|
|
325
|
-
- Trying to PUT on `service_catalog/items/{internal_id}` when the correct path is `service-catalog/items/{display_id}`
|
|
326
|
-
- Including `custom_lookup_bigint` fields in API updates (they're admin-UI-only)
|
|
327
|
-
- Deleting and recreating resources when an in-place update works
|
|
328
|
-
- Repeating 10+ failed API calls to discover what the playbook already documents
|
|
329
|
-
|
|
330
|
-
**The April 2026 Braintrust incident**: A playbook existed (`docs/playbooks/freshservice-service-catalog-item.md`), the blackboard had the lesson ("FS rich text tables require html.escape()"), and a brain.py playbook (`fs-hide-catalog-el`) was available. None were consulted. The result: 15+ failed API attempts, accidental creation of duplicate fields, then destructive deletion of two catalog items breaking S3 workflow automation.
|
|
105
|
+
## Orient Synthesis
|
|
331
106
|
|
|
332
|
-
|
|
107
|
+
Before leaving Orient, have one clear internal picture: what the user wants, task type, session continuity, codebase constraints, relevant lessons/patterns, capability mix, correct task size, whether approval or clarification is needed. Orient is complete when the next move feels obvious.
|
|
333
108
|
|
|
334
|
-
##
|
|
109
|
+
## Safety Protocols
|
|
335
110
|
|
|
336
|
-
|
|
111
|
+
**Approval gates, destructive action prevention, compare-before-you-loop, and loop detection are enforced by the `ftm-guard` hook**, which fires on every mutating tool call automatically. You do not need to self-enforce these — the hook will inject warnings if you're about to do something dangerous. But you should still be aware of them:
|
|
337
112
|
|
|
338
|
-
-
|
|
339
|
-
-
|
|
340
|
-
-
|
|
341
|
-
-
|
|
342
|
-
- relevant lessons
|
|
343
|
-
- relevant patterns
|
|
344
|
-
- capability mix
|
|
345
|
-
- smallest correct task size
|
|
346
|
-
- whether approval or clarification is needed
|
|
113
|
+
- External mutations need user approval per-phase (not per-call, not whole-plan)
|
|
114
|
+
- Destructive actions (delete, recreate) need per-resource confirmation
|
|
115
|
+
- 3+ failed API calls = stop and compare against a working reference
|
|
116
|
+
- Never trial-and-error; always diff a working resource first
|
|
347
117
|
|
|
348
|
-
|
|
118
|
+
See `references/incidents.md` for the full incident history behind these rules.
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# ftm-guard.sh
|
|
3
|
+
# Safety system for all Claude Code sessions with ftm installed.
|
|
4
|
+
# Fires on PreToolUse for mutating tools. Injects safety context
|
|
5
|
+
# before Claude executes external mutations, destructive actions,
|
|
6
|
+
# or enters trial-and-error loops.
|
|
7
|
+
#
|
|
8
|
+
# Hook: PreToolUse (matcher: Edit|Write|Bash|mcp__*)
|
|
9
|
+
#
|
|
10
|
+
# This is NOT gated on ftm session state — it protects ALL sessions.
|
|
11
|
+
|
|
12
|
+
set -eu
|
|
13
|
+
|
|
14
|
+
INPUT=$(cat)
|
|
15
|
+
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // ""' 2>/dev/null)
|
|
16
|
+
|
|
17
|
+
# Only gate mutating operations
|
|
18
|
+
IS_MUTATING=false
|
|
19
|
+
|
|
20
|
+
case "$TOOL_NAME" in
|
|
21
|
+
Edit|Write) IS_MUTATING=true ;;
|
|
22
|
+
Bash)
|
|
23
|
+
# Check if the bash command contains mutating API patterns
|
|
24
|
+
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // ""' 2>/dev/null)
|
|
25
|
+
case "$COMMAND" in
|
|
26
|
+
*deleteFS*|*delete_custom_object*|*DELETE*|*putFS*|*postFS*) IS_MUTATING=true ;;
|
|
27
|
+
*"curl -X DELETE"*|*"curl -X PUT"*|*"curl -X POST"*|*"curl -X PATCH"*) IS_MUTATING=true ;;
|
|
28
|
+
*"requests.delete"*|*"requests.put"*|*"requests.post"*|*"requests.patch"*) IS_MUTATING=true ;;
|
|
29
|
+
esac
|
|
30
|
+
;;
|
|
31
|
+
esac
|
|
32
|
+
|
|
33
|
+
# Also catch mutating MCP calls
|
|
34
|
+
case "$TOOL_NAME" in
|
|
35
|
+
mcp__*create*|mcp__*update*|mcp__*delete*|mcp__*send*|mcp__*add*|mcp__*remove*|mcp__*apply*|mcp__*transition*|mcp__*commit*|mcp__*push*|mcp__*post_message*|mcp__*reply*|mcp__*modify*|mcp__*batch*|mcp__*convert*)
|
|
36
|
+
IS_MUTATING=true ;;
|
|
37
|
+
esac
|
|
38
|
+
|
|
39
|
+
if [ "$IS_MUTATING" != "true" ]; then
|
|
40
|
+
exit 0
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
# --- Build safety context based on what's about to happen ---
|
|
44
|
+
|
|
45
|
+
FTM_STATE="$HOME/.claude/ftm-state"
|
|
46
|
+
CONTEXT_PARTS=""
|
|
47
|
+
|
|
48
|
+
# Check 1: Is this a destructive action?
|
|
49
|
+
IS_DESTRUCTIVE=false
|
|
50
|
+
case "$TOOL_NAME" in
|
|
51
|
+
mcp__*delete*|mcp__*remove*) IS_DESTRUCTIVE=true ;;
|
|
52
|
+
esac
|
|
53
|
+
case "${COMMAND:-}" in
|
|
54
|
+
*deleteFS*|*delete_custom_object*|*"curl -X DELETE"*|*"requests.delete"*|*DELETE*) IS_DESTRUCTIVE=true ;;
|
|
55
|
+
esac
|
|
56
|
+
|
|
57
|
+
if [ "$IS_DESTRUCTIVE" = "true" ]; then
|
|
58
|
+
CONTEXT_PARTS="$CONTEXT_PARTS [DESTRUCTIVE ACTION GATE] You are about to DELETE an external resource. STOP. Confirm with the user FIRST — name the specific resource being deleted and warn about downstream dependencies (workflow configs, automation references, lookup fields). Never delete-and-recreate to fix something. See ftm-mind/references/incidents.md -> Braintrust Incident."
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
# Check 2: Is there a playbook for this system?
|
|
62
|
+
SYSTEM=""
|
|
63
|
+
case "$TOOL_NAME" in
|
|
64
|
+
mcp__freshservice*) SYSTEM="freshservice" ;;
|
|
65
|
+
mcp__mcp-atlassian*) SYSTEM="jira" ;;
|
|
66
|
+
mcp__slack*) SYSTEM="slack" ;;
|
|
67
|
+
mcp__gmail*) SYSTEM="gmail" ;;
|
|
68
|
+
esac
|
|
69
|
+
# Also detect from bash commands
|
|
70
|
+
case "${COMMAND:-}" in
|
|
71
|
+
*freshservice*|*getFS*|*putFS*|*postFS*|*deleteFS*) SYSTEM="freshservice" ;;
|
|
72
|
+
*okta*|*OktaGroup*|*OktaUser*) SYSTEM="okta" ;;
|
|
73
|
+
esac
|
|
74
|
+
|
|
75
|
+
if [ -n "$SYSTEM" ]; then
|
|
76
|
+
# Check if playbook was consulted this session
|
|
77
|
+
PLAYBOOK_MARKER="$FTM_STATE/.playbook-checked-$SYSTEM"
|
|
78
|
+
if [ ! -f "$PLAYBOOK_MARKER" ]; then
|
|
79
|
+
CONTEXT_PARTS="$CONTEXT_PARTS [PLAYBOOK CHECK] You are calling $SYSTEM APIs. Did you check for playbooks FIRST? Run: brain.py --playbook-match and check docs/playbooks/ and blackboard experiences with code_patterns. If you haven't, STOP and check now. Write to $PLAYBOOK_MARKER after checking."
|
|
80
|
+
fi
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
# Check 3: Loop detection — count recent failures for this system
|
|
84
|
+
ERROR_TRACKER="$FTM_STATE/.error-tracker.jsonl"
|
|
85
|
+
if [ -f "$ERROR_TRACKER" ] && [ -n "$SYSTEM" ]; then
|
|
86
|
+
NOW=$(date +%s)
|
|
87
|
+
RECENT_ERRORS=$(python3 -c "
|
|
88
|
+
import json
|
|
89
|
+
count = 0
|
|
90
|
+
cutoff = $NOW - 600
|
|
91
|
+
for line in open('$ERROR_TRACKER'):
|
|
92
|
+
line = line.strip()
|
|
93
|
+
if not line: continue
|
|
94
|
+
try:
|
|
95
|
+
ev = json.loads(line)
|
|
96
|
+
if ev.get('module','').lower().find('$SYSTEM') >= 0 and ev.get('type') == 'error' and ev.get('ts',0) >= cutoff:
|
|
97
|
+
count += 1
|
|
98
|
+
except: pass
|
|
99
|
+
print(count)
|
|
100
|
+
" 2>/dev/null || echo "0")
|
|
101
|
+
|
|
102
|
+
if [ "$RECENT_ERRORS" -ge 3 ]; then
|
|
103
|
+
CONTEXT_PARTS="$CONTEXT_PARTS [LOOP DETECTED] $RECENT_ERRORS recent errors on $SYSTEM in the last 10 minutes. STOP trial-and-error. Find a WORKING reference resource, GET it, diff field-by-field against the broken one, and make targeted changes. The answer is in the diff, not in your next guess."
|
|
104
|
+
fi
|
|
105
|
+
fi
|
|
106
|
+
|
|
107
|
+
# Output combined safety context if any checks triggered
|
|
108
|
+
if [ -n "$CONTEXT_PARTS" ]; then
|
|
109
|
+
# Escape for JSON
|
|
110
|
+
ESCAPED=$(echo "$CONTEXT_PARTS" | sed 's/"/\\"/g' | tr '\n' ' ')
|
|
111
|
+
cat <<JSONEOF
|
|
112
|
+
{
|
|
113
|
+
"hookSpecificOutput": {
|
|
114
|
+
"hookEventName": "PreToolUse",
|
|
115
|
+
"additionalContext": "[ftm-guard]$ESCAPED"
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
JSONEOF
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
exit 0
|
|
@@ -22,6 +22,16 @@
|
|
|
22
22
|
"timeout": 5
|
|
23
23
|
}
|
|
24
24
|
]
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"matcher": "Bash|mcp__freshservice-mcp|mcp__mcp-atlassian|mcp__slack|mcp__gmail|mcp__git",
|
|
28
|
+
"hooks": [
|
|
29
|
+
{
|
|
30
|
+
"type": "command",
|
|
31
|
+
"command": "~/.claude/hooks/ftm-guard.sh",
|
|
32
|
+
"timeout": 5
|
|
33
|
+
}
|
|
34
|
+
]
|
|
25
35
|
}
|
|
26
36
|
],
|
|
27
37
|
"UserPromptSubmit": [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "feed-the-machine",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.15",
|
|
4
4
|
"description": "A brain upgrade for Claude Code — 26 skills that teach it how to think before acting, remember across conversations, debug like a war room, run plans on autopilot with agent teams, and get second opinions from GPT & Gemini. Plus 15 hooks that automate the boring stuff.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "kkudumu",
|